diff --git a/README.md b/README.md index 5031fd4645..5cd3a1528d 100644 --- a/README.md +++ b/README.md @@ -13,25 +13,9 @@ ESP-IDF is the development framework for Espressif SoCs supported on Windows, Li # ESP-IDF Release and SoC Compatibility -The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. The preview support is usually limited in time and intended for beta versions of chips. Please use an ESP-IDF release where the desired SoC is already supported. +![Chip support](https://dl.espressif.com/dl/esp-idf/chip-support.svg?v=1) -|Chip | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | | -|:----------- |:--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- | -|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) | -|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) | -|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) | -|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) | -|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) | -|ESP32-C5 | | | | |![alt text][supported] |since v5.5.1, [Announcement](https://www.espressif.com/en/news/ESP32-C5) | -|ESP32-C61 | | | | |![alt text][supported] |since v5.5.1, [Announcement](https://www.espressif.com/en/products/socs/esp32-c61) | - -[supported]: https://img.shields.io/badge/-supported-green "supported" -[preview]: https://img.shields.io/badge/-preview-orange "preview" - -There are variants of revisions for a series of chips. See [Compatibility Between ESP-IDF Releases and Revisions of Espressif SoCs](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY.md) for the details of the compatibility between ESP-IDF and chip revisions. +See [Compatibility Between ESP-IDF Releases and Revisions of Espressif SoCs](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY.md) for the details of the compatibility between ESP-IDF and chip revisions. Espressif SoCs released before 2016 (ESP8266 and ESP8285) are supported by [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead. diff --git a/README_CN.md b/README_CN.md index 168dd74b97..631d289fd9 100644 --- a/README_CN.md +++ b/README_CN.md @@ -13,26 +13,9 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux # ESP-IDF 与乐鑫芯片 -下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。 +![芯片支持](https://dl.espressif.com/dl/esp-idf/chip-support.svg?v=1) -芯片 | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | | -|:----------- | :--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------------ | -|ESP32 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | | -|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-C3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | | -|ESP32-S3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) | -|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) | -|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) | -|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) | -|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) | -|ESP32-C5 | | | | |![alt text][supported] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) | -|ESP32-C61 | | | | |![alt text][supported] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) | - - -[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported" -[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview" - -每款乐鑫芯片都可能有不同版本。建议参考 [ESP-IDF 版本与乐鑫芯片版本兼容性](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY_CN.md),了解 ESP-IDF 版本与各芯片版本之间的兼容性。 +请参考 [ESP-IDF 版本与乐鑫芯片版本兼容性](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY_CN.md) 了解 ESP-IDF 版本与芯片版本之间的兼容性详情。 对于 2016 年之前发布的乐鑫芯片(包括 ESP8266 和 ESP8285),请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。 diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index a215bd4e8e..af71a578fa 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -676,6 +676,10 @@ if(CONFIG_BT_ENABLED) "porting/transport/src/hci_transport.c" ) + list(APPEND include_dirs + host/nimble/port/include + ) + if(CONFIG_BT_CONTROLLER_DISABLED) list(APPEND srcs "host/nimble/nimble/porting/nimble/src/hal_uart.c" @@ -716,7 +720,12 @@ if(CONFIG_BT_ENABLED) ) endif() - if(NOT (CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS OR CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)) + # Compile TinyCrypt if: + # 1. Controller uses TinyCrypt (not mbedTLS), OR + # 2. NimBLE uses TinyCrypt (not mbedTLS), OR + # 3. Bluedroid Host SMP uses TinyCrypt + if(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT OR + (NOT CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS AND NOT CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)) list(APPEND include_dirs common/tinycrypt/include common/tinycrypt/port @@ -975,7 +984,7 @@ set(bt_priv_requires ) if(CONFIG_BLE_COMPRESSED_LOG_ENABLE) - set(BT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + set(CODE_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") # When log compression is enabled, selected logs are replaced # by auto-generated macros that emit pre-encoded data. # This eliminates the original format strings, reducing firmware size and diff --git a/components/bt/common/Kconfig.in b/components/bt/common/Kconfig.in index 4bcfaa79ce..0c0b040ab4 100644 --- a/components/bt/common/Kconfig.in +++ b/components/bt/common/Kconfig.in @@ -6,6 +6,43 @@ config BT_ALARM_MAX_NUM This option decides the maximum number of alarms which could be used by Bluetooth host. +choice BT_SMP_CRYPTO_STACK + prompt "SMP cryptographic stack" + depends on (BT_BLE_SMP_ENABLE || BT_SMP_ENABLE || BT_NIMBLE_SECURITY_ENABLE) + default BT_SMP_CRYPTO_STACK_NATIVE + help + Select the cryptographic library to use for SMP operations (AES, AES-CMAC, ECDH P-256). + + config BT_SMP_CRYPTO_STACK_NATIVE + bool "Native Bluedroid implementation" + depends on (BT_BLE_SMP_ENABLE || BT_SMP_ENABLE) + help + Use the built-in Bluedroid cryptographic implementation. + This provides compatibility with all features. + This option is only available for Bluedroid host. + + config BT_SMP_CRYPTO_STACK_TINYCRYPT + bool "TinyCrypt" + help + Use TinyCrypt library for cryptographic operations. + TinyCrypt is a lightweight cryptographic library designed for constrained devices. + This can reduce code size compared to the native implementation. + This is the default option. + + config BT_SMP_CRYPTO_STACK_MBEDTLS + bool "mbedTLS" + select MBEDTLS_AES_C + select MBEDTLS_CMAC_C + select MBEDTLS_ECDH_C + select MBEDTLS_ECP_C + select MBEDTLS_ECP_DP_SECP256R1_ENABLED + help + Use mbedTLS library for cryptographic operations. + This can provide hardware acceleration on supported platforms and reduce code size + by sharing crypto implementations with other components. + +endchoice + menu "BLE Log" source "$IDF_PATH/components/bt/common/ble_log/Kconfig.in" endmenu diff --git a/components/bt/common/ble_log/Kconfig.in b/components/bt/common/ble_log/Kconfig.in index edf459311d..35405367e2 100644 --- a/components/bt/common/ble_log/Kconfig.in +++ b/components/bt/common/ble_log/Kconfig.in @@ -110,12 +110,46 @@ if BLE_LOG_ENABLED help Enable BLE Log TS with external logging module - config BLE_LOG_SYNC_IO_NUM - int "GPIO number for Timestamp Synchronization (TS) toggle output" - depends on BLE_LOG_TS_ENABLED - default 0 - help - GPIO number for TS toggle output + if BLE_LOG_TS_ENABLED + config BLE_LOG_SYNC_IO_NUM + int "GPIO number for Timestamp Synchronization (TS) toggle output" + depends on BLE_LOG_TS_ENABLED + default 0 + help + GPIO number for TS toggle output + + config BLE_LOG_TS_TRIGGER_TIMEOUT_MS + int "Timeout (ms) for Timestamp Synchronization toggle" + default 1000 + help + Timeout (ms) for Timestamp Synchronization toggle + + choice BLE_LOG_TS_TRIGGER_CHOICE + prompt "BLE Log Timestamp Synchronization trigger choice" + default BLE_LOG_TS_TRIGGER_TASK_EVENT + help + Choose BLE Log Timestamp Synchronization trigger + + config BLE_LOG_TS_TRIGGER_ESP_TIMER + bool "BLE Log Timestamp Synchronization trigger - ESP Timer" + help + ESP Timer based periodic TS trigger + + config BLE_LOG_TS_TRIGGER_TASK_EVENT + bool "BLE Log Timestamp Synchronization trigger - Task Event" + help + Task Event based TS trigger (Light Sleep Test Compatibility) + endchoice + + config BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD + bool "Utilize ISR dispatch method for ESP Timer as Timestamp Synchronization trigger" + default n + select ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD + select GPIO_CTRL_FUNC_IN_IRAM + depends on BLE_LOG_TS_TRIGGER_ESP_TIMER + help + Utilize ISR dispatch method for ESP Timer as Timestamp Synchronization trigger + endif choice BLE_LOG_PRPH_CHOICE prompt "BLE Log peripheral choice" diff --git a/components/bt/common/ble_log/extension/log_compression/CMakeLists.txt b/components/bt/common/ble_log/extension/log_compression/CMakeLists.txt index 967b0e9b8e..15ae73550a 100644 --- a/components/bt/common/ble_log/extension/log_compression/CMakeLists.txt +++ b/components/bt/common/ble_log/extension/log_compression/CMakeLists.txt @@ -1,6 +1,6 @@ - set(LOG_COMPRESSED_MODULE "") set(LOG_COMPRESSED_MODULE_CODE_PATH "") +set(BT_ROOT_PATH $ENV{IDF_PATH}/components/bt) set(LOG_COMPRESSED_SRCS_DIR "${CMAKE_BINARY_DIR}/ble_log/.compressed_srcs") # default config value for ble mesh module @@ -17,32 +17,62 @@ set(BLE_HOST_TAGS_PRESERVE "") if(CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE) list(APPEND LOG_COMPRESSED_MODULE "BLE_MESH") - if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/mesh_log_index.h") - file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/mesh_log_index.h" "") - endif() - list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH "esp_ble_mesh") # update config file set(BLE_MESH_CODE_PATH "esp_ble_mesh") set(BLE_MESH_LOG_INDEX_HEADER "mesh_log_index.h") + set(BLE_MESH_LOG_SCRIPT_PATH + "${CMAKE_CURRENT_LIST_DIR}/scripts/module_scripts/ble_mesh/make_mesh_log_macro.py") # update BLE_MESH_TAGS and BLE_MESH_TAGS_PRESERVE include(${CMAKE_CURRENT_LIST_DIR}/cmake/ble_mesh_log_tags.cmake) - + if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_MESH_LOG_INDEX_HEADER}") + file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_MESH_LOG_INDEX_HEADER}" "") + endif() + list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${BLE_MESH_CODE_PATH}) endif() + if(CONFIG_BLE_HOST_COMPRESSED_LOG_ENABLE AND CONFIG_BT_BLUEDROID_ENABLED) list(APPEND LOG_COMPRESSED_MODULE "BLE_HOST") - list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH "host/bluedroid/stack") - if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/host_log_index.h") - file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/host_log_index.h" "") - endif() + # update config file set(HOST_CODE_PATH "host/bluedroid/stack") set(HOST_LOG_INDEX_HEADER "host_log_index.h") + set(BLE_HOST_LOG_SCRIPT_PATH + "${CMAKE_CURRENT_LIST_DIR}/scripts/module_scripts/bluedroid/make_bluedroid_log_macro.py") + include(${CMAKE_CURRENT_LIST_DIR}/cmake/ble_host_bluedroid_tags.cmake) + if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${HOST_LOG_INDEX_HEADER}") + file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${HOST_LOG_INDEX_HEADER}" "") + endif() + list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${HOST_CODE_PATH}) endif() + +if(BLE_COMPRESSED_LIB_LOG_BUILD) + if(NOT (BLE_COMPRESSED_LIB_NAME AND BLE_COMPRESSED_LIB_CODE_DIR AND BLE_COMPRESSED_LIB_LOG_TAGS)) + message(FATAL_ERROR "Invalid settings") + else() + message("Building compressed log for ${BLE_COMPRESSED_LIB_NAME}") + endif() + list(APPEND LOG_COMPRESSED_MODULE ${BLE_COMPRESSED_LIB_NAME}) + if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_COMPRESSED_LIB_LOG_INDEX_HEADER}") + file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_COMPRESSED_LIB_LOG_INDEX_HEADER}" "") + endif() + list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${BLE_COMPRESSED_LIB_CODE_DIR}) + + string(REPLACE ";" "," BLE_COMPRESSED_LIB_CODE_DIR "${BLE_COMPRESSED_LIB_CODE_DIR}") + string(REPLACE ";" "," BLE_COMPRESSED_LIB_LOG_TAGS "${BLE_COMPRESSED_LIB_LOG_TAGS}") + string(REPLACE ";" "," BLE_COMPRESSED_LIB_LOG_TAGS_PRESERVE "${BLE_COMPRESSED_LIB_LOG_TAGS_PRESERVE}") +else() + set(BLE_COMPRESSED_LIB_NAME "placeholder") +endif() + + if(LOG_COMPRESSED_MODULE) - list(APPEND srcs "common/ble_log/extension/log_compression/ble_log_compression.c") - list(APPEND include_dirs "${CMAKE_BINARY_DIR}/ble_log/include") + # When building the library, ble_log_compression.c and its dependencies are not needed + if(NOT BLE_COMPRESSED_LIB_LOG_BUILD) + list(APPEND srcs "common/ble_log/extension/log_compression/ble_log_compression.c") + list(APPEND include_dirs "${CMAKE_BINARY_DIR}/ble_log/include") + endif() if(NOT CMAKE_VERSION VERSION_LESS 3.15.0) set(Python3_FIND_STRATEGY LOCATION) find_package(Python3 COMPONENTS Interpreter) @@ -111,19 +141,39 @@ if(LOG_COMPRESSED_MODULE) "host/nimble/nimble/nimble/host/store/config/src") endif() - add_custom_target(ble_log_compression ALL - COMMAND ${BLE_PYTHON_EXECUTABLE} ${PYTHON_SCRIPT} - compress - --compressed_srcs_path "${LOG_COMPRESSED_SRCS_DIR}" - --build_path "${CMAKE_BINARY_DIR}" - --module "'${LOG_COMPRESSED_MODULE}'" - --bt_path "${BT_ROOT_PATH}" - --srcs "'${compressed_srcs}'" - DEPENDS ${compressed_srcs_with_abs_path} ${PYTHON_SCRIPT} - COMMENT "Log compression is being performed, please wait..." - WORKING_DIRECTORY ${BT_ROOT_PATH} - USES_TERMINAL - ) + if(BLE_COMPRESSED_LIB_LOG_BUILD) + execute_process(COMMAND ${BLE_PYTHON_EXECUTABLE} ${PYTHON_SCRIPT} + compress + --compressed_srcs_path "${LOG_COMPRESSED_SRCS_DIR}" + --build_path "${CMAKE_BINARY_DIR}" + --module "${LOG_COMPRESSED_MODULE}" + --code_base_path "${CODE_BASE_PATH}" + --srcs "${compressed_srcs}" + RESULT_VARIABLE result + OUTPUT_VARIABLE out + ERROR_VARIABLE err) + if(NOT ${result} EQUAL 0) + message(WARNING "${err}") + message(WARNING "Exit this log compression due to failure of compression") + set(LOG_COMPRESS_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE) + set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE) + return() + endif() + else() + add_custom_target(ble_log_compression ALL + COMMAND ${BLE_PYTHON_EXECUTABLE} ${PYTHON_SCRIPT} + compress + --compressed_srcs_path "${LOG_COMPRESSED_SRCS_DIR}" + --build_path "${CMAKE_BINARY_DIR}" + --module "'${LOG_COMPRESSED_MODULE}'" + --code_base_path "${CODE_BASE_PATH}" + --srcs "'${compressed_srcs}'" + DEPENDS ${compressed_srcs_with_abs_path} ${PYTHON_SCRIPT} + COMMENT "Log compression is being performed, please wait..." + WORKING_DIRECTORY ${BT_ROOT_PATH} + USES_TERMINAL + ) + endif() function(add_flags_if_in_list file file_list compile_flags) set(PROCESSED OFF PARENT_SCOPE) @@ -190,7 +240,10 @@ if(LOG_COMPRESSED_MODULE) set(LOG_COMPRESSION_TARGET ble_log_compression PARENT_SCOPE) # set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE) set(LOG_COMPRESS_SRCS "${compressed_srcs_with_abs_path};${uncompressed_srcs}" PARENT_SCOPE) - list(APPEND include_dirs "common/ble_log/extension/log_compression/include") + if(NOT BLE_COMPRESSED_LIB_LOG_BUILD) + list(APPEND include_dirs "common/ble_log/extension/log_compression/include") + endif() + list(APPEND include_dirs "${CMAKE_BINARY_DIR}/ble_log/include") set(LOG_COMPRESS_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE) else() set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE) diff --git a/components/bt/common/ble_log/extension/log_compression/scripts/ble_log_compress.py b/components/bt/common/ble_log/extension/log_compression/scripts/ble_log_compress.py index cb4e40bd57..2398036d8c 100644 --- a/components/bt/common/ble_log/extension/log_compression/scripts/ble_log_compress.py +++ b/components/bt/common/ble_log/extension/log_compression/scripts/ble_log_compress.py @@ -19,6 +19,7 @@ This script processes Bluetooth source files to compress logging statements. import argparse import enum +import importlib.util import logging import os import re @@ -33,6 +34,7 @@ from typing import Dict from typing import List from typing import Tuple from typing import Union +from typing import cast import tree_sitter_c as tsc import yaml @@ -72,10 +74,16 @@ CLANG_PARSER: Union[Parser, None] = None SOURCE_ENUM_MAP = { 'BLE_HOST': 0, 'BLE_MESH': 1, + 'BLE_MESH_LIB': 2, } # Functions that require hex formatting -HEX_FUNCTIONS = ['bt_hex'] # Used in Mesh and Audio modules +HEX_FUNCTIONS = { + # func_name: (arg_cnt, buf_idx, buf_len) + # Negative buf_len indicates constant buffer size + 'bt_hex': (2, 0, 1), # Used in Mesh and Audio modules + 'MAC2STR': (1, 0, -6), # Used in Bluedroid Host +} # C keywords to exclude from function names C_KEYWORDS = { @@ -119,15 +127,6 @@ LINE_MACROS = { '__LINE__', } -BLUEDROID_LOG_MODE_LEVEL_GET = { - 'BTM': 'btm_cb.trace_level', - 'L2CAP': 'l2cb.l2cap_trace_level', - 'GAP': 'gap_cb.trace_level', - 'GATT': 'gatt_cb.trace_level', - 'SMP': 'smp_cb.trace_level', - 'APPL': 'appl_trace_level', -} - class ARG_SIZE_TYPE(enum.IntEnum): U32 = 0 @@ -174,11 +173,12 @@ class LogCompressor: """Main class for BLE log compression.""" def __init__(self) -> None: - self.bt_component_path = Path() + self.code_base_path = Path() self.build_dir = Path() self.bt_compressed_srcs_path = Path() self.config: dict[str, Any] = {} self.module_info: dict[str, Any] = {} + self.module_mod: dict[str, Any] = {} def init_parser(self) -> Parser: """Initialize tree-sitter parser for C.""" @@ -371,15 +371,20 @@ class LogCompressor: if ( arg_node.type == 'call_expression' and arg_node.child_by_field_name('function') - and arg_node.child_by_field_name('function').text.decode('utf-8') in HEX_FUNCTIONS + and arg_node.child_by_field_name('function').text.decode('utf-8') in HEX_FUNCTIONS.keys() ): # Extract arguments of the hex function + hex_func_name = arg_node.child_by_field_name('function').text.decode('utf-8') hex_args = arg_node.child_by_field_name('arguments') - if hex_args and hex_args.named_child_count >= 2: - buf_node = hex_args.named_children[0] - len_node = hex_args.named_children[1] + hex_func_info = HEX_FUNCTIONS[hex_func_name] + if hex_args and hex_args.named_child_count == hex_func_info[0]: + buf_node = hex_args.named_children[hex_func_info[1]].text.decode('utf-8') + if hex_func_info[2] < 0: + len_node = abs(hex_func_info[2]) + else: + len_node = hex_args.named_children[hex_func_info[2]].text.decode('utf-8') token_list = list(token) - token_list[6] = f'@hex_func@{buf_node.text.decode("utf-8")}@{len_node.text.decode("utf-8")}' + token_list[6] = f'@hex_func@{buf_node}@{len_node}' tokens[tokens_tuple_map[i]] = tuple(token_list) log_info['argu_tokens'] = tokens @@ -419,7 +424,7 @@ class LogCompressor: if ( node.type == 'call_expression' and node.child_by_field_name('function') - and node.child_by_field_name('function').text.decode('utf-8') in HEX_FUNCTIONS + and node.child_by_field_name('function').text.decode('utf-8') in HEX_FUNCTIONS.keys() ): return True @@ -462,53 +467,6 @@ class LogCompressor: if not log_idx: return '' - def generate_mesh_log_prefix(source: str, tag: str, print_statm: str) -> str: - level = tag.split('_')[-1] - mod = tag.split('_')[0] - if level == 'ERR': - level = 'ERROR' - log_level = 'BLE_MESH_LOG_LEVEL_ERROR' - elif level == 'WARN': - level = 'WARN' - log_level = 'BLE_MESH_LOG_LEVEL_WARN' - elif level == 'INFO': - level = 'INFO' - log_level = 'BLE_MESH_LOG_LEVEL_INFO' - elif level == 'DBG': - level = 'DEBUG' - log_level = 'BLE_MESH_LOG_LEVEL_DEBUG' - else: - LOGGER.error(f'Invalid log level {level}') - return '' - if mod == 'NET': - used_log_levl = 'BLE_MESH_NET_BUF_LOG_LEVEL' - used_log_mod = 'BLE_MESH_NET_BUF' - else: - used_log_levl = 'BLE_MESH_LOG_LEVEL' - used_log_mod = 'BLE_MESH' - return ( - f'{{do {{ if (({used_log_levl} >= {log_level}) &&' - f' BLE_MESH_LOG_LEVEL_CHECK({used_log_mod}, {level})) {print_statm};}} while (0);}}\\\n' - ) - - def generate_bluedroid_log_prefix(source: str, tag: str, print_statm: str) -> str: - tag_info = tag.split('_') - mod = tag_info[0] - - return ( - f'{{if ({BLUEDROID_LOG_MODE_LEVEL_GET[mod]} >= BT_TRACE_LEVEL_{tag_info[-1]} &&' - f' BT_LOG_LEVEL_CHECK({mod}, {tag_info[-1]})) {print_statm};}}\\\n' - ) - - def generate_log_lvl_prefix(source: str, tag: str, print_statm: str) -> str: - if source == 'BLE_MESH': - return ' ' + generate_mesh_log_prefix(source, tag, print_statm) - elif source == 'BLE_HOST': # only bluedroid host supported for now - return ' ' + generate_bluedroid_log_prefix(source, tag, print_statm) - else: - LOGGER.error(f'Unknown source {source}') - return '' - source_value = SOURCE_ENUM_MAP.get(source.upper()) if source_value is None: raise ValueError(f'Invalid source: {source}') @@ -551,41 +509,22 @@ class LogCompressor: else: sizes.append(f'{int(ARG_SIZE_TYPE.U32)}') - if arg_count > 0: - size_str = ', '.join(sizes) - arg_str = ', '.join(arguments).replace('\n', '') - macro += generate_log_lvl_prefix( - source, - tag, - (f'BLE_LOG_COMPRESSED_HEX_PRINT({source_value}, {log_idx}, {arg_count}, {size_str}, {arg_str})'), - ) + stmt = self.module_mod[source].gen_compressed_stmt( + log_idx, + source_value, + tag, + log_info['arguments'][0], + [{'name': arg, 'size_type': size_type} for arg, size_type in zip(arguments, sizes)], + [ + { + 'buffer': hex_str.split('@')[2], + 'length': hex_str.split('@')[3], + } + for hex_str in hex_func + ], + ) + macro += cast(str, stmt) - for idx, item in enumerate(hex_func): - # hex_func format: @hex_func@buf@len - parts = item.split('@') - if len(parts) >= 4: - buf = parts[2] - buf_len = parts[3] - macro += generate_log_lvl_prefix( - source, - tag, - (f'BLE_LOG_COMPRESSED_HEX_PRINT_BUF({source_value}, {log_idx}, {idx}, {buf}, {buf_len})'), - ) - else: - macro += generate_log_lvl_prefix( - source, tag, f'BLE_LOG_COMPRESSED_HEX_PRINT_WITH_ZERO_ARGUMENTS({source_value}, {log_idx})' - ) - for idx, item in enumerate(hex_func): - # hex_func format: @hex_func@buf@len - parts = item.split('@') - if len(parts) >= 4: - buf = parts[2] - buf_len = parts[3] - macro += generate_log_lvl_prefix( - source, - tag, - (f'BLE_LOG_COMPRESSED_HEX_PRINT_BUF({source_value}, {log_idx}, {idx}, {buf}, {buf_len})'), - ) if ( 'tags_with_preserve' in self.module_info[source] and tag in self.module_info[source]['tags_with_preserve'] @@ -593,8 +532,7 @@ class LogCompressor: macro += f' {tag}(fmt, ##__VA_ARGS__);\\\n' else: # Non-hexified log - print_fmt = print_fmt or 'NULL' - macro += f' BLE_LOG_COMPRESSED_PRINT({source_value}, {log_idx}, "{print_fmt}", ##__VA_ARGS__); \\\n' + raise ValueError('Hexify convert failed') macro += '}\n' return macro @@ -716,7 +654,7 @@ class LogCompressor: total_cnt = 0 for src in srcs: if pattern.match(src): - src_path = self.bt_component_path / src + src_path = self.code_base_path / src dest_path = self.bt_compressed_srcs_path / src temp_path = f'{dest_path}.tmp' total_cnt += 1 @@ -754,7 +692,7 @@ class LogCompressor: module: Module name macros: List of (log_id, macro_definition) """ - # header_path = self.bt_component_path / self.module_info[module]['log_index_path'] + # header_path = self.code_base_path / self.module_info[module]['log_index_path'] header_path = self.build_dir / Path('ble_log') / Path('include') / self.module_info[module]['log_index_file'] # Create directory if needed header_path.parent.mkdir(parents=True, exist_ok=True) @@ -764,8 +702,7 @@ class LogCompressor: return elif update_state == self.db_manager.SOURCE_LOG_UPDATE_FULL: # Header template - header_content = ( - textwrap.dedent(f""" + header_content = textwrap.dedent(f""" /* * SPDX-FileCopyrightText: {datetime.now().year} Espressif Systems (Shanghai) CO LTD * @@ -778,22 +715,11 @@ class LogCompressor: #include #include - // Compression function declarations - extern int ble_log_compressed_hex_print - (uint32_t source, uint32_t log_index, size_t args_size_cnt, ...); - extern int ble_log_compressed_hex_print_buf - (uint8_t source, uint32_t log_index, uint8_t buf_idx, const uint8_t *buf, size_t len); - - // Compression macros - #define BLE_LOG_COMPRESSED_HEX_PRINT(source, log_index, args_cnt, ...) \\ - ble_log_compressed_hex_print(source, log_index, args_cnt, ##__VA_ARGS__) - #define BLE_LOG_COMPRESSED_HEX_PRINT_BUF(source, log_index, buf_idx, buf, len) \\ - ble_log_compressed_hex_print_buf(source, log_index, buf_idx, (const uint8_t *)buf, len) - #define BLE_LOG_COMPRESSED_HEX_PRINT_WITH_ZERO_ARGUMENTS(source, log_index) \\ - ble_log_compressed_hex_print(source, log_index, 0) """).strip() - + '\n\n' - ) + + header_content += self.module_mod[module].gen_header_head() + header_content += '\n\n' + # Add sorted macros for log_id, macro_def in sorted(macros, key=lambda x: x[0]): header_content += macro_def + '\n' @@ -852,6 +778,14 @@ class LogCompressor: for module in module_names: if module in modules: self.module_info[module] = modules[module] + module_script_path = self.module_info[module]['script'] + spec = self.module_mod[module] = importlib.util.spec_from_file_location(module, module_script_path) + if spec and spec.loader: + self.module_mod[module] = importlib.util.module_from_spec(spec) + spec.loader.exec_module(self.module_mod[module]) + else: + LOGGER.error(f"Failed to load module '{module}' script") + raise ImportError(' Failed to load module script') print(f'Found module {module} for compression\n', flush=True, end='', file=sys.stdout) else: LOGGER.warning(f"Skipping module '{module}' - config not found") @@ -863,7 +797,7 @@ class LogCompressor: compress_parser = subparsers.add_parser('compress') compress_parser.add_argument('--srcs', required=True, help='Semicolon-separated source file paths') - compress_parser.add_argument('--bt_path', required=True, help='Bluetooth component root path') + compress_parser.add_argument('--code_base_path', required=True, help='Component base path') compress_parser.add_argument('--module', required=True, help='Semicolon-separated module names') compress_parser.add_argument('--build_path', required=True, help='Build output directory') compress_parser.add_argument('--compressed_srcs_path', required=True, help='Directory for processed sources') @@ -871,7 +805,7 @@ class LogCompressor: args = parser.parse_args() # Setup paths - self.bt_component_path = Path(args.bt_path) + self.code_base_path = Path(args.code_base_path) self.build_dir = Path(args.build_path) self.bt_compressed_srcs_path = Path(args.compressed_srcs_path) @@ -947,7 +881,7 @@ class LogCompressor: # Mark files as processed for module, info in self.module_info.items(): for temp_path in info['files_to_process']: - src_path = self.bt_component_path / os.path.relpath(temp_path[:-4], self.bt_compressed_srcs_path) + src_path = self.code_base_path / os.path.relpath(temp_path[:-4], self.bt_compressed_srcs_path) db_manager.mark_file_processed(module, src_path, temp_path) for root, _, files in os.walk(self.bt_compressed_srcs_path): for name in files: diff --git a/components/bt/common/ble_log/extension/log_compression/scripts/configs/module_info.yml.in b/components/bt/common/ble_log/extension/log_compression/scripts/configs/module_info.yml.in index 853dcd4748..5201f57503 100644 --- a/components/bt/common/ble_log/extension/log_compression/scripts/configs/module_info.yml.in +++ b/components/bt/common/ble_log/extension/log_compression/scripts/configs/module_info.yml.in @@ -6,6 +6,7 @@ log_config: description: "BLE Mesh" code_path: [@BLE_MESH_CODE_PATH@] log_index_file: @BLE_MESH_LOG_INDEX_HEADER@ + script: @BLE_MESH_LOG_SCRIPT_PATH@ tags: [@BLE_MESH_TAGS@] tags_with_preserve: [@BLE_MESH_TAGS_PRESERVE@] @@ -13,5 +14,14 @@ log_config: description: "BLE Host" code_path: [@HOST_CODE_PATH@] log_index_file: @HOST_LOG_INDEX_HEADER@ + script: @BLE_HOST_LOG_SCRIPT_PATH@ tags: [@BLE_HOST_TAGS@] tags_with_preserve: [@BLE_HOST_TAGS_PRESERVE@] + + @BLE_COMPRESSED_LIB_NAME@: + description: "@BLE_COMPRESSED_LIB_DESC@" + code_path: [@BLE_COMPRESSED_LIB_CODE_DIR@] + log_index_file: @BLE_COMPRESSED_LIB_LOG_INDEX_HEADER@ + script: @BLE_COMPRESSED_LIB_LOG_SCRIPT_PATH@ + tags: [@BLE_COMPRESSED_LIB_LOG_TAGS@] + tags_with_preserve: [@BLE_COMPRESSED_LIB_LOG_TAGS_PRESERVE@] diff --git a/components/bt/common/ble_log/extension/log_compression/scripts/inttypes_map.py b/components/bt/common/ble_log/extension/log_compression/scripts/inttypes_map.py index 9e95a18cff..44f193ac22 100644 --- a/components/bt/common/ble_log/extension/log_compression/scripts/inttypes_map.py +++ b/components/bt/common/ble_log/extension/log_compression/scripts/inttypes_map.py @@ -163,4 +163,5 @@ TYPES_MACRO_MAP = { 'SCNoPTR': __PRIPTR_PREFIX + 'o', 'SCNuPTR': __PRIPTR_PREFIX + 'u', 'SCNxPTR': __PRIPTR_PREFIX + 'x', + 'MACSTR': '%s', } diff --git a/components/bt/common/ble_log/extension/log_compression/scripts/module_scripts/ble_mesh/make_mesh_log_macro.py b/components/bt/common/ble_log/extension/log_compression/scripts/module_scripts/ble_mesh/make_mesh_log_macro.py new file mode 100644 index 0000000000..791de5f8ab --- /dev/null +++ b/components/bt/common/ble_log/extension/log_compression/scripts/module_scripts/ble_mesh/make_mesh_log_macro.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import textwrap + + +def generate_mesh_log_prefix(tag: str, print_statm: str) -> str: + level = tag.split('_')[-1] + mod = tag.split('_')[0] + if level == 'ERR': + level = 'ERROR' + log_level = 'BLE_MESH_LOG_LEVEL_ERROR' + elif level == 'WARN': + level = 'WARN' + log_level = 'BLE_MESH_LOG_LEVEL_WARN' + elif level == 'INFO': + level = 'INFO' + log_level = 'BLE_MESH_LOG_LEVEL_INFO' + elif level == 'DBG': + level = 'DEBUG' + log_level = 'BLE_MESH_LOG_LEVEL_DEBUG' + else: + return '' + if mod == 'NET': + used_log_levl = 'BLE_MESH_NET_BUF_LOG_LEVEL' + used_log_mod = 'BLE_MESH_NET_BUF' + else: + used_log_levl = 'BLE_MESH_LOG_LEVEL' + used_log_mod = 'BLE_MESH' + return ( + f'{{do {{ if (({used_log_levl} >= {log_level}) &&' + f' BLE_MESH_LOG_LEVEL_CHECK({used_log_mod}, {level})) {print_statm};}} while (0);}}\\\n' + ) + + +def gen_header_head() -> str: + head = textwrap.dedent(""" + // Compression function declarations + extern int ble_log_compressed_hex_print + (uint8_t source, uint32_t log_index, size_t args_size_cnt, ...); + extern int ble_log_compressed_hex_print_buf + (uint8_t source, uint32_t log_index, uint8_t buf_idx, const uint8_t *buf, size_t len); + """) + return head + + +def gen_compressed_stmt( + log_index: int, module_id: int, func_name: str, fmt: str, args: list[dict], buffer_args: list[dict] +) -> str: + if len(args) == 0: + stmt = f' ble_log_compressed_hex_print({module_id}, {log_index}, 0);' + for idx, buffer_arg in enumerate(buffer_args): + stmt += '\\\n' + stmt += ( + f' ble_log_compressed_hex_print_buf(' + f'{module_id}, {log_index}, {idx}, ' + f'(const uint8_t *){buffer_arg["buffer"]}, {buffer_arg["length"]});' + ) + stmt += '\\\n' + return ' ' + generate_mesh_log_prefix(func_name, stmt) + size_str = ', '.join([arg['size_type'] for arg in args]) + args_str = ', '.join([arg['name'] for arg in args]).replace('\n', '') + stmt = f' ble_log_compressed_hex_print({module_id}, {log_index}, {len(args)}, {size_str}, {args_str});' + for idx, buffer_arg in enumerate(buffer_args): + stmt += '\\\n' + stmt += ( + f' ble_log_compressed_hex_print_buf(' + f'{module_id}, {log_index}, {idx}, ' + f'(const uint8_t *){buffer_arg["buffer"]}, {buffer_arg["length"]});' + ) + stmt += '\\\n' + return ' ' + generate_mesh_log_prefix(func_name, stmt) diff --git a/components/bt/common/ble_log/extension/log_compression/scripts/module_scripts/bluedroid/make_bluedroid_log_macro.py b/components/bt/common/ble_log/extension/log_compression/scripts/module_scripts/bluedroid/make_bluedroid_log_macro.py new file mode 100644 index 0000000000..72be38c081 --- /dev/null +++ b/components/bt/common/ble_log/extension/log_compression/scripts/module_scripts/bluedroid/make_bluedroid_log_macro.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import textwrap + +BLUEDROID_LOG_MODE_LEVEL_GET = { + 'BTM': 'btm_cb.trace_level', + 'L2CAP': 'l2cb.l2cap_trace_level', + 'GAP': 'gap_cb.trace_level', + 'GATT': 'gatt_cb.trace_level', + 'SMP': 'smp_cb.trace_level', + 'APPL': 'appl_trace_level', +} + + +def generate_bluedroid_log_prefix(tag: str, print_statm: str) -> str: + tag_info = tag.split('_') + mod = tag_info[0] + + return ( + f'{{if ({BLUEDROID_LOG_MODE_LEVEL_GET[mod]} >= BT_TRACE_LEVEL_{tag_info[-1]} &&' + f' BT_LOG_LEVEL_CHECK({mod}, {tag_info[-1]})) {print_statm};}}\\\n' + ) + + +def gen_header_head() -> str: + head = textwrap.dedent(""" + // Compression function declarations + extern int ble_log_compressed_hex_print + (uint8_t source, uint32_t log_index, size_t args_size_cnt, ...); + extern int ble_log_compressed_hex_print_buf + (uint8_t source, uint32_t log_index, uint8_t buf_idx, const uint8_t *buf, size_t len); + """) + return head + + +def gen_compressed_stmt( + log_index: int, module_id: int, func_name: str, fmt: str, args: list[dict], buffer_args: list[dict] +) -> str: + if len(args) == 0: + stmt = f' ble_log_compressed_hex_print({module_id},{log_index}, 0);' + for idx, buffer_arg in enumerate(buffer_args): + stmt += '\\\n' + stmt += ( + f' ble_log_compressed_hex_print_buf(' + f'{module_id}, {log_index}, {idx}, ' + f'(const uint8_t *){buffer_arg["buffer"]}, {buffer_arg["length"]});' + ) + stmt += '\\\n' + return ' ' + generate_bluedroid_log_prefix(func_name, stmt) + size_str = ', '.join([arg['size_type'] for arg in args]) + args_str = ', '.join([arg['name'] for arg in args]).replace('\n', '') + stmt = f' ble_log_compressed_hex_print({module_id},{log_index}, {len(args)}, {size_str}, {args_str});' + for idx, buffer_arg in enumerate(buffer_args): + stmt += '\\\n' + stmt += ( + f' ble_log_compressed_hex_print_buf(' + f'{module_id}, {log_index}, {idx}, ' + f'(const uint8_t *){buffer_arg["buffer"]}, {buffer_arg["length"]});' + ) + stmt += '\\\n' + return ' ' + generate_bluedroid_log_prefix(func_name, stmt) diff --git a/components/bt/common/ble_log/src/ble_log_lbm.c b/components/bt/common/ble_log/src/ble_log_lbm.c index 0cc996c721..4504663c5f 100644 --- a/components/bt/common/ble_log/src/ble_log_lbm.c +++ b/components/bt/common/ble_log/src/ble_log_lbm.c @@ -107,7 +107,8 @@ void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_cod } if (len_append) { #if CONFIG_SOC_ESP_NIMBLE_CONTROLLER - if (omdata) { + if (omdata && !BLE_LOG_IN_ISR()) { + /* os_mbuf_copydata is in flash and not safe to call from ISR */ os_mbuf_copydata((struct os_mbuf *)addr_append, 0, len_append, buf + BLE_LOG_FRAME_HEAD_LEN + len); } diff --git a/components/bt/common/ble_log/src/ble_log_rt.c b/components/bt/common/ble_log/src/ble_log_rt.c index 7268797e36..951d4d2a45 100644 --- a/components/bt/common/ble_log/src/ble_log_rt.c +++ b/components/bt/common/ble_log/src/ble_log_rt.c @@ -19,6 +19,15 @@ BLE_LOG_STATIC TaskHandle_t rt_task_handle = NULL; BLE_LOG_STATIC QueueHandle_t rt_queue_handle = NULL; #if CONFIG_BLE_LOG_TS_ENABLED BLE_LOG_STATIC bool rt_ts_enabled = false; +#if CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER +BLE_LOG_STATIC esp_timer_handle_t rt_ts_timer = NULL; +#endif /* CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER */ +#endif /* CONFIG_BLE_LOG_TS_ENABLED */ + +/* PRIVATE FUNCTION DECLARATION */ +#if CONFIG_BLE_LOG_TS_ENABLED +BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters); +BLE_LOG_STATIC void ble_log_rt_ts_trigger(void *arg); #endif /* CONFIG_BLE_LOG_TS_ENABLED */ /* PRIVATE FUNCTION */ @@ -56,15 +65,9 @@ BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters) }; ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t)); -#if CONFIG_BLE_LOG_TS_ENABLED - if (rt_ts_enabled) { - ble_log_ts_info_t *ts_info = NULL; - ble_log_ts_info_update(&ts_info); - if (ts_info) { - ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)ts_info, sizeof(ble_log_ts_info_t)); - } - } -#endif /* CONFIG_BLE_LOG_TS_ENABLED */ +#if CONFIG_BLE_LOG_TS_TRIGGER_TASK_EVENT + ble_log_rt_ts_trigger(NULL); +#endif /* CONFIG_BLE_LOG_TS_TRIGGER_TASK_EVENT */ #if CONFIG_BLE_LOG_ENH_STAT_ENABLED ble_log_write_enh_stat(); @@ -72,6 +75,24 @@ BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters) } } +#if CONFIG_BLE_LOG_TS_ENABLED +#if CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD +BLE_LOG_IRAM_ATTR +#endif /* CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD */ +BLE_LOG_STATIC void ble_log_rt_ts_trigger(void *arg) +{ + (void)arg; + if (!rt_inited || !rt_ts_enabled) { + return; + } + ble_log_ts_info_t *ts_info = NULL; + ble_log_ts_info_update(&ts_info); + if (ts_info) { + ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)ts_info, sizeof(ble_log_ts_info_t)); + } +} +#endif /* CONFIG_BLE_LOG_TS_ENABLED */ + /* INTERFACE */ bool ble_log_rt_init(void) { @@ -92,10 +113,28 @@ bool ble_log_rt_init(void) goto exit; } - rt_inited = true; #if CONFIG_BLE_LOG_TS_ENABLED rt_ts_enabled = false; +#if CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER + /* Initialize ESP Timer Trigger */ + esp_timer_create_args_t ts_timer_args = { + .callback = ble_log_rt_ts_trigger, + .arg = NULL, +#if CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD + .dispatch_method = ESP_TIMER_ISR, +#endif /* CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD */ + .name = "ble_log_ts_timer", + }; + if (esp_timer_create(&ts_timer_args, &rt_ts_timer) != ESP_OK) { + goto exit; + } + if (esp_timer_start_periodic(rt_ts_timer, BLE_LOG_TS_TRIGGER_TIMEOUT_US) != ESP_OK) { + goto exit; + } +#endif /* CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER */ #endif /* CONFIG_BLE_LOG_TS_ENABLED */ + + rt_inited = true; return true; exit: @@ -108,6 +147,13 @@ void ble_log_rt_deinit(void) rt_inited = false; #if CONFIG_BLE_LOG_TS_ENABLED rt_ts_enabled = false; +#if CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER + if (rt_ts_timer) { + esp_timer_stop(rt_ts_timer); + esp_timer_delete(rt_ts_timer); + rt_ts_timer = NULL; + } +#endif /* CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER */ #endif /* CONFIG_BLE_LOG_TS_ENABLED */ /* CRITICAL: diff --git a/components/bt/common/ble_log/src/ble_log_ts.c b/components/bt/common/ble_log/src/ble_log_ts.c index e01611da10..db719b3dc5 100644 --- a/components/bt/common/ble_log/src/ble_log_ts.c +++ b/components/bt/common/ble_log/src/ble_log_ts.c @@ -61,6 +61,9 @@ void ble_log_ts_deinit(void) gpio_reset_pin(CONFIG_BLE_LOG_SYNC_IO_NUM); } +#if CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD +BLE_LOG_IRAM_ATTR +#endif /* CONFIG_BLE_LOG_TS_TRIGGER_ESP_TIMER_ISR_DISPATCH_METHOD */ void ble_log_ts_info_update(ble_log_ts_info_t **info) { if (!ts_inited) { diff --git a/components/bt/common/ble_log/src/ble_log_util.c b/components/bt/common/ble_log/src/ble_log_util.c index c084d6d249..aac709e4e1 100644 --- a/components/bt/common/ble_log/src/ble_log_util.c +++ b/components/bt/common/ble_log/src/ble_log_util.c @@ -20,7 +20,8 @@ portMUX_TYPE ble_log_spin_lock = portMUX_INITIALIZER_UNLOCKED; #if CONFIG_BLE_LOG_XOR_CHECKSUM_ENABLED #include "esp_compiler.h" -static inline uint32_t ror32(uint32_t word, uint32_t shift) +BLE_LOG_IRAM_ATTR BLE_LOG_STATIC BLE_LOG_INLINE +uint32_t ror32(uint32_t word, uint32_t shift) { if (unlikely(shift == 0)) { return word; diff --git a/components/bt/common/ble_log/src/internal_include/ble_log_rt.h b/components/bt/common/ble_log/src/internal_include/ble_log_rt.h index ae8b4b05a3..7becb1202b 100644 --- a/components/bt/common/ble_log/src/internal_include/ble_log_rt.h +++ b/components/bt/common/ble_log/src/internal_include/ble_log_rt.h @@ -22,7 +22,12 @@ /* MACRO */ #define BLE_LOG_TASK_PRIO (ESP_TASK_PRIO_MAX - 1) #define BLE_LOG_TASK_STACK_SIZE CONFIG_BLE_LOG_TASK_STACK_SIZE +#if CONFIG_BLE_LOG_TS_ENABLED +#define BLE_LOG_TS_TRIGGER_TIMEOUT_US (CONFIG_BLE_LOG_TS_TRIGGER_TIMEOUT_MS * 1000) +#define BLE_LOG_TASK_HOOK_TIMEOUT_MS CONFIG_BLE_LOG_TS_TRIGGER_TIMEOUT_MS +#else /* !CONFIG_BLE_LOG_TS_ENABLED */ #define BLE_LOG_TASK_HOOK_TIMEOUT_MS (1000) +#endif /* CONFIG_BLE_LOG_TS_ENABLED */ /* INTERFACE */ bool ble_log_rt_init(); diff --git a/components/bt/common/hci_log/bt_hci_log.c b/components/bt/common/hci_log/bt_hci_log.c index fa3de907d6..fef3760b3f 100644 --- a/components/bt/common/hci_log/bt_hci_log.c +++ b/components/bt/common/hci_log/bt_hci_log.c @@ -225,6 +225,10 @@ esp_err_t IRAM_ATTR bt_hci_log_record_data(bt_hci_log_t *p_hci_log_ctl, char *st ts = esp_timer_get_time(); temp_buf = (uint8_t *)malloc(data_len + 8); + if (!temp_buf) { + return ESP_ERR_NO_MEM; + } + memset(temp_buf, 0x0, data_len + 8); memcpy(temp_buf, &ts, 8); diff --git a/components/bt/common/include/bt_common.h b/components/bt/common/include/bt_common.h index f687e3afe7..372ea68e7e 100644 --- a/components/bt/common/include/bt_common.h +++ b/components/bt/common/include/bt_common.h @@ -61,6 +61,22 @@ #define HEAP_MEMORY_DEBUG FALSE #endif +#if UC_BT_BLUEDROID_MEM_STATS +#define HEAP_MEMORY_STATS TRUE +#else +#define HEAP_MEMORY_STATS FALSE +#endif + +#if UC_BT_BLUEDROID_THREAD_DEBUG +#define OSI_THREAD_DEBUG TRUE +#else +#define OSI_THREAD_DEBUG FALSE +#endif + +#define OSI_THREAD_BLOCK_TIME UC_BT_BLUEDROID_THREAD_BLOCK_TIME + +#define OSI_THREAD_BLOCK_MSG UC_BT_BLUEDROID_THREAD_BLOCK_MSG + #ifndef BT_BLE_DYNAMIC_ENV_MEMORY #define BT_BLE_DYNAMIC_ENV_MEMORY FALSE #endif diff --git a/components/bt/common/include/bt_user_config.h b/components/bt/common/include/bt_user_config.h index 5632b5fe22..3ddc188f13 100644 --- a/components/bt/common/include/bt_user_config.h +++ b/components/bt/common/include/bt_user_config.h @@ -107,6 +107,30 @@ #define UC_BT_BLUEDROID_MEM_DEBUG FALSE #endif +#ifdef CONFIG_BT_BLUEDROID_MEM_STATS +#define UC_BT_BLUEDROID_MEM_STATS TRUE +#else +#define UC_BT_BLUEDROID_MEM_STATS FALSE +#endif + +#ifdef CONFIG_BT_BLUEDROID_THREAD_DEBUG +#define UC_BT_BLUEDROID_THREAD_DEBUG TRUE +#else +#define UC_BT_BLUEDROID_THREAD_DEBUG FALSE +#endif + +#ifdef CONFIG_BT_BLUEDROID_THREAD_BLOCK_TIME +#define UC_BT_BLUEDROID_THREAD_BLOCK_TIME CONFIG_BT_BLUEDROID_THREAD_BLOCK_TIME +#else +#define UC_BT_BLUEDROID_THREAD_BLOCK_TIME 1000 +#endif + +#ifdef CONFIG_BT_BLUEDROID_THREAD_BLOCK_MSG +#define UC_BT_BLUEDROID_THREAD_BLOCK_MSG CONFIG_BT_BLUEDROID_THREAD_BLOCK_MSG +#else +#define UC_BT_BLUEDROID_THREAD_BLOCK_MSG 50 +#endif + #ifdef CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #else diff --git a/components/bt/common/osi/allocator.c b/components/bt/common/osi/allocator.c index 0293daa8c4..68a5bdb3a4 100644 --- a/components/bt/common/osi/allocator.c +++ b/components/bt/common/osi/allocator.c @@ -20,6 +20,12 @@ #include "bt_common.h" #include "osi/allocator.h" +#if HEAP_MEMORY_STATS +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#endif extern void *pvPortZalloc(size_t size); extern void vPortFree(void *pv); @@ -198,6 +204,28 @@ uint32_t osi_mem_dbg_get_max_size_section(uint8_t index) } #endif +#if HEAP_MEMORY_STATS +static size_t s_mem_used_size = 0; +static SemaphoreHandle_t s_mem_mutex = NULL; + +int osi_mem_init(void) +{ + s_mem_mutex = xSemaphoreCreateMutex(); + if (s_mem_mutex == NULL) { + return -1; + } + return 0; +} + +void osi_mem_deinit(void) +{ + if (s_mem_mutex) { + vSemaphoreDelete(s_mem_mutex); + s_mem_mutex = NULL; + } +} +#endif + char *osi_strdup(const char *str) { size_t size = strlen(str) + 1; // + 1 for the null terminator @@ -216,12 +244,23 @@ void *osi_malloc_func(size_t size) void *p = osi_malloc_base(size); if (size != 0 && p == NULL) { - OSI_TRACE_ERROR("malloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size); + OSI_TRACE_ERROR("malloc failed (caller=%p size=%u)", __builtin_return_address(0), size); + OSI_TRACE_ERROR("heap info: free=%d, largest_block=%d", + heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); #if HEAP_ALLOCATION_FAILS_ABORT assert(0); #endif } +#if HEAP_MEMORY_STATS + if (s_mem_mutex != NULL && p != NULL) { + size_t alloc_size = heap_caps_get_allocated_size(p); + xSemaphoreTake(s_mem_mutex, portMAX_DELAY); + s_mem_used_size += alloc_size; + xSemaphoreGive(s_mem_mutex); + } +#endif + return p; } @@ -230,16 +269,53 @@ void *osi_calloc_func(size_t size) void *p = osi_calloc_base(size); if (size != 0 && p == NULL) { - OSI_TRACE_ERROR("calloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size); + OSI_TRACE_ERROR("calloc failed (caller=%p size=%u)", __builtin_return_address(0), size); + OSI_TRACE_ERROR("heap info: free=%d, largest_block=%d", + heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); #if HEAP_ALLOCATION_FAILS_ABORT assert(0); #endif } +#if HEAP_MEMORY_STATS + if (s_mem_mutex != NULL && p != NULL) { + size_t alloc_size = heap_caps_get_allocated_size(p); + xSemaphoreTake(s_mem_mutex, portMAX_DELAY); + s_mem_used_size += alloc_size; + xSemaphoreGive(s_mem_mutex); + } +#endif + return p; } void osi_free_func(void *ptr) { - osi_free(ptr); +#if HEAP_MEMORY_DEBUG + osi_mem_dbg_clean(ptr, __func__, __LINE__); +#endif + +#if HEAP_MEMORY_STATS + if (s_mem_mutex != NULL && ptr != NULL) { + size_t free_size = heap_caps_get_allocated_size(ptr); + xSemaphoreTake(s_mem_mutex, portMAX_DELAY); + if (s_mem_used_size >= free_size) { + s_mem_used_size -= free_size; + } else { + OSI_TRACE_ERROR("The size of malloc and free not match: alloc_size=%u free_size=%u", + s_mem_used_size, free_size); + } + xSemaphoreGive(s_mem_mutex); + } +#endif + + free(ptr); } + +#if HEAP_MEMORY_STATS +// Get the size of memory allocated by Bluedroid but not yet freed +uint32_t esp_host_used_heap_size_get(void) +{ + return s_mem_used_size; +} +#endif diff --git a/components/bt/common/osi/include/osi/allocator.h b/components/bt/common/osi/include/osi/allocator.h index d95040538d..caba42f3ea 100644 --- a/components/bt/common/osi/include/osi/allocator.h +++ b/components/bt/common/osi/include/osi/allocator.h @@ -21,8 +21,13 @@ #include #include +#include "bt_common.h" #include "esp_heap_caps.h" +#if HEAP_MEMORY_STATS +int osi_mem_init(void); +void osi_mem_deinit(void); +#endif char *osi_strdup(const char *str); void *osi_malloc_func(size_t size); @@ -108,7 +113,7 @@ do { \ // Memory alloc function with print and assertion when fails #define osi_malloc(size) osi_malloc_func((size)) #define osi_calloc(size) osi_calloc_func((size)) -#define osi_free(p) free((p)) +#define osi_free(p) osi_free_func((p)) #endif /* HEAP_MEMORY_DEBUG */ diff --git a/components/bt/common/osi/mutex.c b/components/bt/common/osi/mutex.c index b7fe38a1ee..5a4de81ee5 100644 --- a/components/bt/common/osi/mutex.c +++ b/components/bt/common/osi/mutex.c @@ -65,10 +65,15 @@ void osi_mutex_unlock(osi_mutex_t *mutex) xSemaphoreGive(*mutex); } -/** Delete a semaphore - * @param mutex the mutex to delete */ +/** Delete a mutex + * @param mutex the mutex to delete + * Note: Safe to call with NULL or uninitialized mutex (IDFGH-16853) + */ void osi_mutex_free(osi_mutex_t *mutex) { + if (mutex == NULL || *mutex == NULL) { + return; + } vSemaphoreDelete(*mutex); *mutex = NULL; } diff --git a/components/bt/common/osi/pkt_queue.c b/components/bt/common/osi/pkt_queue.c index 4c149be2c6..50720de0c5 100644 --- a/components/bt/common/osi/pkt_queue.c +++ b/components/bt/common/osi/pkt_queue.c @@ -19,7 +19,7 @@ struct pkt_queue { struct pkt_queue *pkt_queue_create(void) { - struct pkt_queue *queue = calloc(1, sizeof(struct pkt_queue)); + struct pkt_queue *queue = osi_calloc(sizeof(struct pkt_queue)); if (queue == NULL) { return NULL; } diff --git a/components/bt/common/osi/semaphore.c b/components/bt/common/osi/semaphore.c index 14823160e3..5acbb67b8f 100644 --- a/components/bt/common/osi/semaphore.c +++ b/components/bt/common/osi/semaphore.c @@ -69,9 +69,15 @@ osi_sem_take(osi_sem_t *sem, uint32_t timeout) return ret; } -// Deallocates a semaphore +/** Deallocates a semaphore + * @param sem the semaphore to delete + * Note: Safe to call with NULL or uninitialized semaphore (IDFGH-16853) + */ void osi_sem_free(osi_sem_t *sem) { + if (sem == NULL || *sem == NULL) { + return; + } vSemaphoreDelete(*sem); *sem = NULL; } diff --git a/components/bt/common/osi/thread.c b/components/bt/common/osi/thread.c index 91bc7906ce..95475670be 100644 --- a/components/bt/common/osi/thread.c +++ b/components/bt/common/osi/thread.c @@ -61,6 +61,10 @@ struct osi_event { static const size_t DEFAULT_WORK_QUEUE_CAPACITY = 100; +#if OSI_THREAD_DEBUG +static void osi_thread_run_item(osi_thread_t *thread, int wq_idx, struct work_item *item); +#endif + static struct work_queue *osi_work_queue_create(size_t capacity) { if (capacity == 0) { @@ -162,7 +166,11 @@ static void osi_thread_run(void *arg) struct work_item item; while (!thread->stop && idx < thread->work_queue_num) { if (osi_thead_work_queue_get(thread->work_queues[idx], &item) == true) { + #if OSI_THREAD_DEBUG + osi_thread_run_item(thread, idx, &item); + #else item.func(item.context); + #endif idx = 0; continue; } else { @@ -451,3 +459,45 @@ bool osi_thread_post_event(struct osi_event *event, uint32_t timeout) return ret; } + +#if OSI_THREAD_DEBUG +static void osi_thread_run_item(osi_thread_t *thread, int wq_idx, struct work_item *item) +{ + uint32_t pre_time; + uint32_t pre_msg_cnt; + uint32_t cur_time; + uint32_t cur_msg_cnt; + + pre_time = esp_log_timestamp(); + pre_msg_cnt = uxQueueMessagesWaiting(thread->work_queues[wq_idx]->queue); + item->func(item->context); + cur_time = esp_log_timestamp(); + cur_msg_cnt = uxQueueMessagesWaiting(thread->work_queues[wq_idx]->queue); + if ((cur_time - pre_time) >= OSI_THREAD_BLOCK_TIME || + (cur_msg_cnt > pre_msg_cnt && (cur_msg_cnt - pre_msg_cnt) >= OSI_THREAD_BLOCK_MSG)) { + OSI_TRACE_ERROR("%s was blocked while running item: %p exec_time=[%u %u] msg_inc=[%u %u]", + pcTaskGetName(thread->thread_handle), item->func, cur_time, pre_time, cur_msg_cnt, pre_msg_cnt); + assert(0); + } +} + +void osi_thread_workqueue_dump(osi_thread_t *thread) +{ + int idx = 0; + struct work_item item; + + vTaskSuspendAll(); + + while (idx < thread->work_queue_num) { + if (osi_thead_work_queue_get(thread->work_queues[idx], &item) == true) { + esp_rom_printf("[%u] %p %p\n", idx, item.func, item.context); + idx = 0; + continue; + } else { + idx++; + } + } + + xTaskResumeAll(); +} +#endif // OSI_THREAD_DEBUG diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index c9b227a5f7..41149cd8e5 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.c @@ -232,6 +232,10 @@ static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); #if CONFIG_FREERTOS_USE_TICKLESS_IDLE static bool esp_bt_check_wakeup_by_bt(void); #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) +#include "tinycrypt/ecc.h" +static int ecc_rand_func(uint8_t *dst, unsigned int len); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) /* Local variable definition *************************************************************************** */ @@ -1024,6 +1028,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "hci transport init failed %d", ret); goto free_controller; } +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) + uECC_set_rng(ecc_rand_func); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) return ESP_OK; free_controller: hci_transport_deinit(); @@ -1457,6 +1464,29 @@ static mbedtls_ecp_keypair keypair; #if CONFIG_BT_LE_SM_SC #include "tinycrypt/cmac_mode.h" #include "tinycrypt/ecc_dh.h" + + +#if CONFIG_BT_CONTROLLER_ONLY +/* Used by uECC to get random data */ +static int ecc_rand_func(uint8_t *dst, unsigned int len) +{ + int offset_cnt = 0; + uint8_t *u8ptr = dst; + uint64_t random64 = 0; + + while(len > 0) { + random64 = (uint64_t)esp_random(); + random64 = (random64 << 32)| (uint64_t)esp_random();; + offset_cnt = len < sizeof(uint64_t) ? len : sizeof(uint64_t); + memcpy(u8ptr, &random64, offset_cnt); + len -= offset_cnt; + u8ptr += offset_cnt; + } + + return 1; +} + +#endif // CONFIG_BT_CONTROLLER_ONLY #endif // CONFIG_BT_LE_SM_SC #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS @@ -1548,11 +1578,11 @@ exit: } #else - if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { + if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { return BLE_SM_KEY_ERR; } - rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1); + rc = uECC_shared_secret(pk, priv, dh, uECC_secp256r1()); if (rc == TC_CRYPTO_FAIL) { return BLE_SM_KEY_ERR; } @@ -1628,7 +1658,7 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) return BLE_SM_KEY_ERR; } #else - if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + if (uECC_make_key(pk, priv, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { return BLE_SM_KEY_ERR; } #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS diff --git a/components/bt/controller/esp32c5/Kconfig.in b/components/bt/controller/esp32c5/Kconfig.in index cfcef62e17..dbd2a8e212 100644 --- a/components/bt/controller/esp32c5/Kconfig.in +++ b/components/bt/controller/esp32c5/Kconfig.in @@ -951,3 +951,11 @@ config BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN When this option is enabled, the Controller continues receiving PDUs In the next connection event instead of entering latency After a data packet is received. + +config BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN + bool "Enables the automatic initiation of a data length update(Experimental)." + default n + help + When this option is enabled, the Controller automatically initiates a data length update + Using the appropriate data length parameters + When a PHY update or a connection interval update occurs. diff --git a/components/bt/controller/esp32c5/bt.c b/components/bt/controller/esp32c5/bt.c index 7453a6917f..2b1945ccd9 100644 --- a/components/bt/controller/esp32c5/bt.c +++ b/components/bt/controller/esp32c5/bt.c @@ -180,6 +180,7 @@ extern int r_ble_get_npl_element_info(esp_bt_controller_config_t *cfg, ble_npl_c extern char *ble_controller_get_compile_version(void); extern int esp_ble_register_bb_funcs(void); extern void esp_ble_unregister_bb_funcs(void); +extern bool esp_ble_controller_lib_check(void); extern uint32_t _bt_bss_start; extern uint32_t _bt_bss_end; extern uint32_t _bt_controller_bss_start; @@ -218,6 +219,10 @@ static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); #if CONFIG_FREERTOS_USE_TICKLESS_IDLE static bool esp_bt_check_wakeup_by_bt(void); #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) +#include "tinycrypt/ecc.h" +static int ecc_rand_func(uint8_t *dst, unsigned int len); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) /* Local variable definition *************************************************************************** */ @@ -1121,6 +1126,13 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto free_controller; } + if (!esp_ble_controller_lib_check()) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Controller lib version mismatch!"); + } + +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) + uECC_set_rng(ecc_rand_func); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) return ESP_OK; free_controller: hci_transport_deinit(); @@ -1594,6 +1606,26 @@ static mbedtls_ecp_keypair keypair; #if CONFIG_BT_LE_SM_SC #include "tinycrypt/cmac_mode.h" #include "tinycrypt/ecc_dh.h" +#if CONFIG_BT_CONTROLLER_ONLY +/* Used by uECC to get random data */ +static int ecc_rand_func(uint8_t *dst, unsigned int len) +{ + int offset_cnt = 0; + uint8_t *u8ptr = dst; + uint64_t random64 = 0; + + while(len > 0) { + random64 = (uint64_t)esp_random(); + random64 = (random64 << 32)| (uint64_t)esp_random();; + offset_cnt = len < sizeof(uint64_t) ? len : sizeof(uint64_t); + memcpy(u8ptr, &random64, offset_cnt); + len -= offset_cnt; + u8ptr += offset_cnt; + } + + return 1; +} +#endif // CONFIG_BT_CONTROLLER_ONLY #endif // CONFIG_BT_LE_SM_SC #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS @@ -1685,11 +1717,11 @@ exit: } #else - if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { + if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { return BLE_SM_KEY_ERR; } - rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1); + rc = uECC_shared_secret(pk, priv, dh, uECC_secp256r1()); if (rc == TC_CRYPTO_FAIL) { return BLE_SM_KEY_ERR; } @@ -1765,7 +1797,7 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) return BLE_SM_KEY_ERR; } #else - if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + if (uECC_make_key(pk, priv, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { return BLE_SM_KEY_ERR; } #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS diff --git a/components/bt/controller/esp32c5/esp_bt_cfg.h b/components/bt/controller/esp32c5/esp_bt_cfg.h index 4dbe2f2fe8..20f2ec7edb 100644 --- a/components/bt/controller/esp32c5/esp_bt_cfg.h +++ b/components/bt/controller/esp32c5/esp_bt_cfg.h @@ -215,6 +215,13 @@ extern "C" { #define DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN (0) #endif + +#if defined(CONFIG_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN) +#define DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN (CONFIG_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN) +#else +#define DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN (0) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else diff --git a/components/bt/controller/esp32c6/Kconfig.in b/components/bt/controller/esp32c6/Kconfig.in index bffab12e66..58fc31715d 100644 --- a/components/bt/controller/esp32c6/Kconfig.in +++ b/components/bt/controller/esp32c6/Kconfig.in @@ -985,3 +985,11 @@ config BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN When this option is enabled, the Controller continues receiving PDUs In the next connection event instead of entering latency After a data packet is received. + +config BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN + bool "Enables the automatic initiation of a data length update(Experimental)." + default n + help + When this option is enabled, the Controller automatically initiates a data length update + Using the appropriate data length parameters + When a PHY update or a connection interval update occurs. diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index a442f8d85c..018f06ff6f 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -34,8 +34,8 @@ #include "os/endian.h" #include "esp_bt.h" -#include "esp_intr_alloc.h" #include "ble_priv.h" +#include "esp_intr_alloc.h" #include "esp_sleep.h" #include "esp_pm.h" #ifdef CONFIG_ESP_PHY_ENABLED @@ -133,7 +133,6 @@ typedef union { }; uint32_t val; } bt_wakeup_params_t; - /* External functions or variables ************************************************************************ */ @@ -192,6 +191,7 @@ extern int r_ble_get_npl_element_info(esp_bt_controller_config_t *cfg, ble_npl_c extern char *ble_controller_get_compile_version(void); extern int esp_ble_register_bb_funcs(void); extern void esp_ble_unregister_bb_funcs(void); +extern bool esp_ble_controller_lib_check(void); extern uint32_t _bt_bss_start; extern uint32_t _bt_bss_end; extern uint32_t _bt_controller_bss_start; @@ -233,6 +233,11 @@ static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); #if CONFIG_FREERTOS_USE_TICKLESS_IDLE static bool esp_bt_check_wakeup_by_bt(void); #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE + +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) +#include "tinycrypt/ecc.h" +static int ecc_rand_func(uint8_t *dst, unsigned int len); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) /* Local variable definition *************************************************************************** */ @@ -1055,6 +1060,7 @@ static void ble_rtc_clk_init(esp_bt_controller_config_t *cfg) esp_bt_rtc_slow_clk_select(s_bt_lpclk_src); } + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { uint8_t mac[6]; @@ -1191,6 +1197,13 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto free_controller; } + if (!esp_ble_controller_lib_check()) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Controller lib version mismatch!"); + } + +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) + uECC_set_rng(ecc_rand_func); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) return ESP_OK; free_controller: hci_transport_deinit(); @@ -1443,7 +1456,6 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) return ret; } - esp_bt_controller_status_t esp_bt_controller_get_status(void) { return ble_controller_status; @@ -1664,6 +1676,27 @@ static mbedtls_ecp_keypair keypair; #if CONFIG_BT_LE_SM_SC #include "tinycrypt/cmac_mode.h" #include "tinycrypt/ecc_dh.h" + +#if CONFIG_BT_CONTROLLER_ONLY +/* Used by uECC to get random data */ +static int ecc_rand_func(uint8_t *dst, unsigned int len) +{ + int offset_cnt = 0; + uint8_t *u8ptr = dst; + uint64_t random64 = 0; + + while(len > 0) { + random64 = (uint64_t)esp_random(); + random64 = (random64 << 32)| (uint64_t)esp_random();; + offset_cnt = len < sizeof(uint64_t) ? len : sizeof(uint64_t); + memcpy(u8ptr, &random64, offset_cnt); + len -= offset_cnt; + u8ptr += offset_cnt; + } + + return 1; +} +#endif // CONFIG_BT_CONTROLLER_ONLY #endif // CONFIG_BT_LE_SM_SC #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS @@ -1755,11 +1788,11 @@ exit: } #else - if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { + if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { return BLE_SM_KEY_ERR; } - rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1); + rc = uECC_shared_secret(pk, priv, dh, uECC_secp256r1()); if (rc == TC_CRYPTO_FAIL) { return BLE_SM_KEY_ERR; } @@ -1835,7 +1868,7 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) return BLE_SM_KEY_ERR; } #else - if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + if (uECC_make_key(pk, priv, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { return BLE_SM_KEY_ERR; } #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS @@ -1851,7 +1884,6 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) #endif // CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC #endif // (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED) - #if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED #include "esp_gdbstub.h" #endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED diff --git a/components/bt/controller/esp32c6/esp_bt_cfg.h b/components/bt/controller/esp32c6/esp_bt_cfg.h index 71f7f9d194..e5d378ad9b 100644 --- a/components/bt/controller/esp32c6/esp_bt_cfg.h +++ b/components/bt/controller/esp32c6/esp_bt_cfg.h @@ -218,6 +218,13 @@ extern "C" { #define DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN (0) #endif + +#if defined(CONFIG_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN) +#define DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN (CONFIG_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN) +#else +#define DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN (0) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else @@ -307,7 +314,6 @@ extern "C" { #define RUN_QA_TEST (0) #define NIMBLE_DISABLE_SCAN_BACKOFF (0) #define BT_LL_CTRL_PRIO_LVL_CFG ((CONFIG_BT_LE_DFT_SYNC_SCHED_PRIO_LEVEL << 4) | (CONFIG_BT_LE_DFT_PERIODIC_ADV_SCHED_PRIO_LEVEL << 2) | CONFIG_BT_LE_DFT_ADV_SCHED_PRIO_LEVEL) - #ifdef __cplusplus } #endif diff --git a/components/bt/controller/esp32h2/Kconfig.in b/components/bt/controller/esp32h2/Kconfig.in index c3d7df55e0..47820f717c 100644 --- a/components/bt/controller/esp32h2/Kconfig.in +++ b/components/bt/controller/esp32h2/Kconfig.in @@ -989,3 +989,11 @@ config BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN When this option is enabled, the Controller continues receiving PDUs In the next connection event instead of entering latency After a data packet is received. + +config BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN + bool "Enables the automatic initiation of a data length update(Experimental)." + default n + help + When this option is enabled, the Controller automatically initiates a data length update + Using the appropriate data length parameters + When a PHY update or a connection interval update occurs. diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index 6ea4185a27..9fb20c0f57 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -187,6 +187,7 @@ extern int r_ble_get_npl_element_info(esp_bt_controller_config_t *cfg, ble_npl_c extern char *ble_controller_get_compile_version(void); extern int esp_ble_register_bb_funcs(void); extern void esp_ble_unregister_bb_funcs(void); +extern bool esp_ble_controller_lib_check(void); extern uint32_t _bt_bss_start; extern uint32_t _bt_bss_end; extern uint32_t _bt_controller_bss_start; @@ -226,6 +227,10 @@ static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); #if CONFIG_FREERTOS_USE_TICKLESS_IDLE static bool esp_bt_check_wakeup_by_bt(void); #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) +#include "tinycrypt/ecc.h" +static int ecc_rand_func(uint8_t *dst, unsigned int len); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) /* Local variable definition *************************************************************************** */ @@ -1144,6 +1149,13 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto free_controller; } + if (!esp_ble_controller_lib_check()) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Controller lib version mismatch!"); + } + +#if (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) + uECC_set_rng(ecc_rand_func); +#endif // (CONFIG_BT_CONTROLLER_ONLY) && (CONFIG_BT_LE_SM_SC) && (!CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS) return ESP_OK; free_controller: hci_transport_deinit(); @@ -1614,6 +1626,27 @@ static mbedtls_ecp_keypair keypair; #if CONFIG_BT_LE_SM_SC #include "tinycrypt/cmac_mode.h" #include "tinycrypt/ecc_dh.h" + +#if CONFIG_BT_CONTROLLER_ONLY +/* Used by uECC to get random data */ +static int ecc_rand_func(uint8_t *dst, unsigned int len) +{ + int offset_cnt = 0; + uint8_t *u8ptr = dst; + uint64_t random64 = 0; + + while(len > 0) { + random64 = (uint64_t)esp_random(); + random64 = (random64 << 32)| (uint64_t)esp_random();; + offset_cnt = len < sizeof(uint64_t) ? len : sizeof(uint64_t); + memcpy(u8ptr, &random64, offset_cnt); + len -= offset_cnt; + u8ptr += offset_cnt; + } + + return 1; +} +#endif // CONFIG_BT_CONTROLLER_ONLY #endif // CONFIG_BT_LE_SM_SC #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS @@ -1705,11 +1738,11 @@ exit: } #else - if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { + if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { return BLE_SM_KEY_ERR; } - rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1); + rc = uECC_shared_secret(pk, priv, dh, uECC_secp256r1()); if (rc == TC_CRYPTO_FAIL) { return BLE_SM_KEY_ERR; } @@ -1785,7 +1818,7 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) return BLE_SM_KEY_ERR; } #else - if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + if (uECC_make_key(pk, priv, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { return BLE_SM_KEY_ERR; } #endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS @@ -1801,6 +1834,7 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) #endif // CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC #endif // (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED) + #if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED #include "esp_gdbstub.h" #endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED diff --git a/components/bt/controller/esp32h2/esp_bt_cfg.h b/components/bt/controller/esp32h2/esp_bt_cfg.h index 4dbe2f2fe8..20f2ec7edb 100644 --- a/components/bt/controller/esp32h2/esp_bt_cfg.h +++ b/components/bt/controller/esp32h2/esp_bt_cfg.h @@ -215,6 +215,13 @@ extern "C" { #define DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN (0) #endif + +#if defined(CONFIG_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN) +#define DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN (CONFIG_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN) +#else +#define DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN (0) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index a184fa951e..1359f195ed 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit a184fa951eb366c3d99a968a4171feb33b99fb82 +Subproject commit 1359f195ed834130739f0130322e1a1cd5464a11 diff --git a/components/bt/controller/lib_esp32c2/esp32c2-bt-lib b/components/bt/controller/lib_esp32c2/esp32c2-bt-lib index 7c104a8d09..6db3a4abe6 160000 --- a/components/bt/controller/lib_esp32c2/esp32c2-bt-lib +++ b/components/bt/controller/lib_esp32c2/esp32c2-bt-lib @@ -1 +1 @@ -Subproject commit 7c104a8d09e35f3244636fcf01004d5c767f12c2 +Subproject commit 6db3a4abe6f2f9ec60067a61732c8ef32557e821 diff --git a/components/bt/controller/lib_esp32c3_family b/components/bt/controller/lib_esp32c3_family index 9b50531537..16cda80aab 160000 --- a/components/bt/controller/lib_esp32c3_family +++ b/components/bt/controller/lib_esp32c3_family @@ -1 +1 @@ -Subproject commit 9b50531537e755792ac827d00d233eab499a0b37 +Subproject commit 16cda80aab0a008093592b7e304c77dcb3ac9ea4 diff --git a/components/bt/controller/lib_esp32c5/esp32c5-bt-lib b/components/bt/controller/lib_esp32c5/esp32c5-bt-lib index a5feba34e1..95899f11a3 160000 --- a/components/bt/controller/lib_esp32c5/esp32c5-bt-lib +++ b/components/bt/controller/lib_esp32c5/esp32c5-bt-lib @@ -1 +1 @@ -Subproject commit a5feba34e144c82374fb9818108d6efc5216dc1f +Subproject commit 95899f11a3f21aae115121ea778cfb8cb1047885 diff --git a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib index cf7c287226..d40be82077 160000 --- a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib +++ b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib @@ -1 +1 @@ -Subproject commit cf7c287226c2c8575dc1cb9896d54a14a18d1dd4 +Subproject commit d40be82077fab8d80aed1eecc39f30673dbcc90d diff --git a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib index a568fa5a03..1034b3c595 160000 --- a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib +++ b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib @@ -1 +1 @@ -Subproject commit a568fa5a03545dd133a301ccdbae99afa3692923 +Subproject commit 1034b3c595cc3a570d2bfb6e0b08b45f3b1f5fae diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index 9a12e8c125..e35d34c993 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -42,6 +42,7 @@ static int adv_send(struct net_buf *buf) uint8_t adv_cnt = 0; struct bt_mesh_adv_data ad = {0}; int err = 0; + bool start_cb_called = (BLE_MESH_ADV(buf)->flags & BLE_MESH_ADV_FLAG_SKIP_START_CB); BT_DBG("LegacyAdvSend, Type %u", BLE_MESH_ADV(buf)->type); BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); @@ -175,7 +176,10 @@ static int adv_send(struct net_buf *buf) net_buf_unref(buf); - adv_send_start(duration, err, cb, cb_data); + if (!start_cb_called && cb && cb->start) { + cb->start(duration, err, cb_data); + } + if (err) { BT_ERR("Start advertising failed: err %d", err); return err; @@ -194,7 +198,7 @@ static int adv_send(struct net_buf *buf) err = bt_le_adv_stop(); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ - adv_send_end(err, cb, cb_data); + BLE_MESH_SEND_END_CB(err, cb, cb_data); if (err) { BT_ERR("Stop advertising failed: err %d", err); return 0; diff --git a/components/bt/esp_ble_mesh/core/adv_common.c b/components/bt/esp_ble_mesh/core/adv_common.c index ff4e50ac1c..cd6157e3bc 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.c +++ b/components/bt/esp_ble_mesh/core/adv_common.c @@ -55,6 +55,29 @@ static bt_mesh_ext_adv_t ext_long_relay_adv_pool[CONFIG_BLE_MESH_LONG_PACKET_REL #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ +const uint8_t adv_type[] = { + [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, + [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#if CONFIG_BLE_MESH_EXT_ADV + [BLE_MESH_ADV_EXT_PROV] = BLE_MESH_DATA_MESH_PROV, + [BLE_MESH_ADV_EXT_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, + [BLE_MESH_ADV_EXT_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#if CONFIG_BLE_MESH_LONG_PACKET + [BLE_MESH_ADV_EXT_LONG_PROV] = BLE_MESH_DATA_MESH_PROV, + [BLE_MESH_ADV_EXT_LONG_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, + [BLE_MESH_ADV_EXT_LONG_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ +#endif /* CONFIG_BLE_MESH_EXT_ADV */ +#if CONFIG_BLE_MESH_FRIEND + [BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE, +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + [BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#endif + [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, + [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, +}; + static inline void init_adv_with_defaults(struct bt_mesh_adv *adv, enum bt_mesh_adv_type type) { diff --git a/components/bt/esp_ble_mesh/core/adv_common.h b/components/bt/esp_ble_mesh/core/adv_common.h index 54267ee522..c52fc18cc3 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.h +++ b/components/bt/esp_ble_mesh/core/adv_common.h @@ -48,6 +48,9 @@ extern "C" { #define BLE_MESH_ADV_INST_UNUSED 0xFF +/* Flags for struct bt_mesh_adv */ +#define BLE_MESH_ADV_FLAG_SKIP_START_CB BIT(0) /* Skip start callback (already called by GATT) */ + struct bt_mesh_adv { const struct bt_mesh_send_cb *cb; void *cb_data; @@ -61,6 +64,7 @@ struct bt_mesh_adv { uint32_t adv_itvl; uint8_t adv_cnt; uint8_t channel_map; + uint8_t flags; /* See BLE_MESH_ADV_FLAG_* */ }; #if CONFIG_BLE_MESH_USE_BLE_50 @@ -171,29 +175,7 @@ typedef enum { BLE_MESH_BUF_REF_MAX, } bt_mesh_buf_ref_flag_t; - -static const uint8_t adv_type[] = { - [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, - [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, -#if CONFIG_BLE_MESH_EXT_ADV - [BLE_MESH_ADV_EXT_PROV] = BLE_MESH_DATA_MESH_PROV, - [BLE_MESH_ADV_EXT_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, - [BLE_MESH_ADV_EXT_DATA] = BLE_MESH_DATA_MESH_MESSAGE, -#if CONFIG_BLE_MESH_LONG_PACKET - [BLE_MESH_ADV_EXT_LONG_PROV] = BLE_MESH_DATA_MESH_PROV, - [BLE_MESH_ADV_EXT_LONG_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, - [BLE_MESH_ADV_EXT_LONG_DATA] = BLE_MESH_DATA_MESH_MESSAGE, -#endif /* CONFIG_BLE_MESH_LONG_PACKET */ -#endif /* CONFIG_BLE_MESH_EXT_ADV */ -#if CONFIG_BLE_MESH_FRIEND - [BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE, -#endif -#if CONFIG_BLE_MESH_RELAY_ADV_BUF - [BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, -#endif - [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, - [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, -}; +extern const uint8_t adv_type[]; typedef struct bt_mesh_adv *(*bt_mesh_pool_allocator_t)(int id, enum bt_mesh_adv_type type); typedef void (*bt_mesh_adv_queue_send_cb_t)(bt_mesh_msg_t *msg, uint32_t timeout, bool front); @@ -214,22 +196,22 @@ static inline TickType_t K_WAIT(int32_t val) return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); } -static inline void adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->start) { - cb->start(duration, err, cb_data); - } -} +#define BLE_MESH_SEND_START_CB(_buf, _duration, _err, _cb, _cb_data) \ + do { \ + if (!(BLE_MESH_ADV(_buf)->flags & BLE_MESH_ADV_FLAG_SKIP_START_CB)) { \ + if ((_cb) && (_cb)->start) { \ + (_cb)->start((_duration), (_err), (_cb_data)); \ + } \ + BLE_MESH_ADV(_buf)->flags |= BLE_MESH_ADV_FLAG_SKIP_START_CB; \ + } \ + } while (0) -static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->end) { - cb->end(err, cb_data); - } -} +#define BLE_MESH_SEND_END_CB(_err, _cb, _cb_data) \ + do { \ + if ((_cb) && (_cb)->end) { \ + (_cb)->end((_err), (_cb_data)); \ + } \ + } while (0) struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void); diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index e31d4186e7..a322c0ab86 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -1874,6 +1874,7 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, TRUE, BLE_ADDR_UNKNOWN_TYPE, + false, 0xFF, 0xFF, BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); #else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* Min_interval: 15ms @@ -1889,6 +1890,7 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, + false, 0xFF, 0xFF, BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ diff --git a/components/bt/esp_ble_mesh/core/ext_adv.c b/components/bt/esp_ble_mesh/core/ext_adv.c index 8b85076aed..c4feaa7a4e 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.c +++ b/components/bt/esp_ble_mesh/core/ext_adv.c @@ -181,7 +181,7 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) break; } - adv_send_start(duration, err, cb, cb_data); + BLE_MESH_SEND_START_CB(buf, duration, err, cb, cb_data); if (err) { BT_ERR("Start advertising failed: err %d", err); return err; @@ -381,8 +381,8 @@ static uint32_t received_adv_evts_handle(uint32_t recv_evts) } else #endif { - adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, - BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); + BLE_MESH_SEND_END_CB(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, + BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL); diff --git a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h index 39c359d695..20c656e690 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h @@ -37,21 +37,12 @@ extern "C" { */ #ifdef CONFIG_BT_BLUEDROID_ENABLED #if CONFIG_IDF_TARGET_ESP32 -#define BLE_MESH_MAX_CONN 1 +#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_ACL_CONNECTIONS, CONFIG_BTDM_CTRL_BLE_MAX_CONN) #elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) -/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */ -#if CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) -/* decrease the adv,scan */ -#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) -#else -#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS -#endif /* CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) */ -#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 -#if CONFIG_BT_ACL_CONNECTIONS > CONFIG_BT_LE_MAX_CONNECTIONS -#define BLE_MESH_MAX_CONN CONFIG_BT_LE_MAX_CONNECTIONS -#else -#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS -#endif /* CONFIG_BT_ACL_CONNECTIONS > CONFIG_BT_LE_MAX_CONNECTIONS */ +#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_ACL_CONNECTIONS, (CONFIG_BT_CTRL_BLE_MAX_ACT - 2)) +#elif (CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || \ + CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61) +#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_ACL_CONNECTIONS, CONFIG_BT_LE_MAX_CONNECTIONS) #else /* default setting */ #define BLE_MESH_MAX_CONN 1 @@ -60,16 +51,11 @@ extern "C" { #ifdef CONFIG_BT_NIMBLE_ENABLED #if CONFIG_IDF_TARGET_ESP32 -#define BLE_MESH_MAX_CONN 1 +#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_NIMBLE_MAX_CONNECTIONS, CONFIG_BTDM_CTRL_BLE_MAX_CONN) #elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) -/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */ -#if CONFIG_BT_NIMBLE_MAX_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) -/* decrease the adv,scan */ -#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) -#else -#define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS -#endif /* CONFIG_BT_NIMBLE_MAX_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) */ -#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 +#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_NIMBLE_MAX_CONNECTIONS, (CONFIG_BT_CTRL_BLE_MAX_ACT - 2)) +#elif (CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || \ + CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61) #define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS #else /* default setting */ diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index fde5b5cdda..b436ce5d6b 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -1239,6 +1239,15 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, send_cb = NULL; goto done; } + + /* GATT bearer sends faster than ADV bearer, so the remote node + * may receive the message and respond before ADV bearer starts. + * To avoid issues where the start callback hasn't been called + * when the response arrives, we call the start callback here + * immediately after GATT bearer sends successfully. The ADV + * bearer will skip start callback since the flag is set. + */ + BLE_MESH_SEND_START_CB(buf, 0, 0, send_cb, cb_data); } } #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ @@ -1253,9 +1262,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, * See BLEMESH24-76 for more details. */ if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - if (send_cb && send_cb->start) { - send_cb->start(0, 0, cb_data); - } + BLE_MESH_SEND_START_CB(buf, 0, 0, send_cb, cb_data); net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); diff --git a/components/bt/esp_ble_mesh/core/net.h b/components/bt/esp_ble_mesh/core/net.h index 1141bd2bd9..b5f5ff0a78 100644 --- a/components/bt/esp_ble_mesh/core/net.h +++ b/components/bt/esp_ble_mesh/core/net.h @@ -472,7 +472,8 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data, static inline void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, enum bt_mesh_net_if net_if) { - struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; + struct bt_mesh_net_rx rx = {0}; + rx.ctx.recv_rssi = rssi; #if CONFIG_BLE_MESH_EXT_ADV rx.ctx.enh.adv_cfg_used = false; rx.ctx.enh.ext_adv_cfg_used = false; diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index 4d598a333e..1992fb87b3 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -474,7 +474,7 @@ void bt_mesh_ble_ext_adv_report(struct ble_gap_ext_disc_desc *desc) /* Here, only a shallow copy needs to be implemented; * deep copying behavior occurs in btc_ble_mesh_ble_copy_req_data. */ - adv_rpt.data = desc->length_data ? desc->data : NULL; + adv_rpt.data = desc->length_data ? (uint8_t *)desc->data : NULL; adv_rpt.event_type = desc->props; adv_rpt.addr_type = desc->addr.type; diff --git a/components/bt/esp_ble_mesh/core/transport.enh.c b/components/bt/esp_ble_mesh/core/transport.enh.c index 967b523379..3147ee86a1 100644 --- a/components/bt/esp_ble_mesh/core/transport.enh.c +++ b/components/bt/esp_ble_mesh/core/transport.enh.c @@ -2528,10 +2528,6 @@ found_rx: } } - if (rpl) { - bt_mesh_update_rpl(rpl, net_rx); - } - /* Mark segment as received */ rx->block |= BIT(seg_o); @@ -2543,6 +2539,10 @@ found_rx: BT_DBG("Complete SDU"); + if (rpl) { + bt_mesh_update_rpl(rpl, net_rx); + } + *pdu_type = BLE_MESH_FRIEND_PDU_COMPLETE; /* Stop SAR Discard timer when processing result is Last Segment */ diff --git a/components/bt/esp_ble_mesh/lib/ext.c b/components/bt/esp_ble_mesh/lib/ext.c index d9803b830a..3f654f82de 100644 --- a/components/bt/esp_ble_mesh/lib/ext.c +++ b/components/bt/esp_ble_mesh/lib/ext.c @@ -211,11 +211,6 @@ void bt_mesh_ext_mem_swap(void *buf, size_t length) sys_mem_swap(buf, length); } -uint32_t bt_mesh_ext_log_timestamp(void) -{ - return esp_log_timestamp(); -} - /* Net buf */ void bt_mesh_ext_buf_simple_init(struct net_buf_simple *buf, size_t reserve_head) { @@ -4006,8 +4001,6 @@ void bt_mesh_ext_mbt_server_cb_evt_to_btc(uint8_t event, void *model, void *ctx) } typedef struct { - uint64_t config_ble_mesh_stack_trace_level : 3; - uint64_t config_ble_mesh_use_ble_50: 1; uint64_t config_ble_mesh_use_duplicate_scan : 1; uint64_t config_ble_mesh_pb_adv : 1; @@ -4172,8 +4165,6 @@ typedef struct { } bt_mesh_ext_config_t; static const bt_mesh_ext_config_t bt_mesh_ext_cfg = { - .config_ble_mesh_stack_trace_level = BLE_MESH_LOG_LEVEL, - .config_ble_mesh_use_ble_50 = IS_ENABLED(CONFIG_BLE_MESH_USE_BLE_50), .config_ble_mesh_use_duplicate_scan = IS_ENABLED(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN), .config_ble_mesh_pb_adv = IS_ENABLED(CONFIG_BLE_MESH_PB_ADV), @@ -4963,6 +4954,106 @@ static const bt_mesh_ext_funcs_t bt_mesh_ext_func = { /* CONFIG_BLE_MESH_MBT_SRV */ }; +#define BLE_MESH_LIB_TRACE_TAG "BLE_MESH(lib)" +#define BLE_MESH_LOG_FORMAT_START(level) LOG_COLOR_ ## level #level " (%" PRIu32 ") %s: " +#define BLE_MESH_LOG_FORMAT_END LOG_RESET_COLOR "\n" + +void bt_mesh_lib_log_error(const char *format, ...) +{ +#if (CONFIG_BLE_MESH_NO_LOG ||\ + /* Disable log output when compressed logging + * is enabled but ERR logs are not preserved */\ + (CONFIG_BLE_MESH_STACK_ERR_LOG_COMPRESSION &&\ + !CONFIG_BLE_MESH_STACK_ERR_LOG_PRESERVE)) + return; +#else + if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_ERROR) && + BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, ERROR)) { + va_list args = {0}; + va_start(args, format); + esp_log_write(ESP_LOG_ERROR, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_START(E), esp_log_timestamp(), BLE_MESH_LIB_TRACE_TAG); + esp_log_writev(ESP_LOG_ERROR, BLE_MESH_LIB_TRACE_TAG, format, args); + esp_log_write(ESP_LOG_ERROR, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_END); + va_end(args); + } +#endif +} + +void bt_mesh_lib_log_warn(const char *format, ...) +{ +#if (CONFIG_BLE_MESH_NO_LOG ||\ + /* Disable log output when compressed logging + * is enabled but WARN logs are not preserved */\ + (CONFIG_BLE_MESH_STACK_WARN_LOG_COMPRESSION &&\ + !CONFIG_BLE_MESH_STACK_WARN_LOG_PRESERVE)) + return; +#else + if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_WARN) && + BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, WARN)) { + va_list args = {0}; + va_start(args, format); + esp_log_write(ESP_LOG_WARN, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_START(W), esp_log_timestamp(), BLE_MESH_LIB_TRACE_TAG); + esp_log_writev(ESP_LOG_WARN, BLE_MESH_LIB_TRACE_TAG, format, args); + esp_log_write(ESP_LOG_WARN, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_END); + va_end(args); + } +#endif +} + +void bt_mesh_lib_log_info(const char *format, ...) +{ +#if (CONFIG_BLE_MESH_NO_LOG ||\ + /* Disable log output when compressed logging + * is enabled but INFO logs are not preserved */\ + (CONFIG_BLE_MESH_STACK_INFO_LOG_COMPRESSION &&\ + !CONFIG_BLE_MESH_STACK_INFO_LOG_PRESERVE)) + return; +#else + if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_INFO) && + BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, INFO)) { + va_list args = {0}; + va_start(args, format); + esp_log_write(ESP_LOG_INFO, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_START(I), esp_log_timestamp(), BLE_MESH_LIB_TRACE_TAG); + esp_log_writev(ESP_LOG_INFO, BLE_MESH_LIB_TRACE_TAG, format, args); + esp_log_write(ESP_LOG_INFO, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_END); + va_end(args); + } +#endif +} + +void bt_mesh_lib_log_debug(const char *format, ...) +{ +#if (CONFIG_BLE_MESH_NO_LOG ||\ + /* Disable log output when compressed logging + * is enabled but DEBUG logs are not preserved */\ + (CONFIG_BLE_MESH_STACK_DEBUG_LOG_COMPRESSION &&\ + !CONFIG_BLE_MESH_STACK_DEBUG_LOG_PRESERVE)) + return; +#else + if ((BLE_MESH_LOG_LEVEL >= BLE_MESH_LOG_LEVEL_DEBUG) && + BLE_MESH_LOG_LEVEL_CHECK(BLE_MESH, DEBUG)) { + va_list args = {0}; + va_start(args, format); + esp_log_write(ESP_LOG_DEBUG, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_START(D), esp_log_timestamp(), BLE_MESH_LIB_TRACE_TAG); + esp_log_writev(ESP_LOG_DEBUG, BLE_MESH_LIB_TRACE_TAG, format, args); + esp_log_write(ESP_LOG_DEBUG, BLE_MESH_LIB_TRACE_TAG, BLE_MESH_LOG_FORMAT_END); + va_end(args); + } +#endif +} + +/** + * @brief Keep symbols alive. + * @note Dummy function to stop the linker from + * optimizing away unused code.The dummy + * function is discarded after linking, + * so it adds zero bytes to the final binary. + */ +void bt_mesh_lib_ext_func_dummy_call(void) +{ + (void *)bt_hex(NULL, 0); +} + int bt_mesh_v11_ext_init(void) { return bt_mesh_v11_init(&bt_mesh_ext_cfg, sizeof(bt_mesh_ext_cfg), diff --git a/components/bt/esp_ble_mesh/lib/lib b/components/bt/esp_ble_mesh/lib/lib index d9fe7de9a9..85e64e61f8 160000 --- a/components/bt/esp_ble_mesh/lib/lib +++ b/components/bt/esp_ble_mesh/lib/lib @@ -1 +1 @@ -Subproject commit d9fe7de9a9eb2a4e4c51172b9c303f9d800706fa +Subproject commit 85e64e61f8471f34bd940e1fe1bdc92f58ed6bef diff --git a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h index 165450ed56..0f9097262a 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h +++ b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h @@ -186,6 +186,8 @@ struct esp_ble_mesh_blob_xfer { esp_ble_mesh_blob_xfer_mode_t mode; /*!< BLOB transfer mode. */ uint8_t block_size_log; /*!< Logarithmic representation of the block size. */ uint16_t chunk_size; /*!< Base chunk size. May be smaller for the last chunk. */ + /* Enhanced parameters for message context in blob chunks */ + esp_ble_mesh_msg_enh_params_t chunk_enh_params; }; /** BLOB transfer data block. */ diff --git a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h index 6ef42d3dd8..f2b2d121c1 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h +++ b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h @@ -782,6 +782,8 @@ struct esp_ble_mesh_dfu_cli_xfer_blob_params { uint8_t block_size_log; /** Base chunk size. May be smaller for the last chunk. */ uint16_t chunk_size; + /* Enhanced parameters for message context in blob chunks */ + esp_ble_mesh_msg_enh_params_t chunk_enh_params; }; /** Firmware Update Client transfer parameters */ diff --git a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_mbt_model_api.h b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_mbt_model_api.h index 54b4f20aa8..38bfa103cf 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_mbt_model_api.h +++ b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_mbt_model_api.h @@ -14,7 +14,6 @@ #define _BLE_MESH_MBT_DEPRECATE_WARN #warning "warning: 'All content in this document, including data structures and APIs, will be deprecated." #endif -#endif /* CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI */ #ifdef __cplusplus extern "C" { @@ -773,4 +772,5 @@ esp_err_t esp_ble_mesh_mbt_server_get_blob_reception_progress(esp_ble_mesh_model } #endif +#endif /* CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI */ #endif /* _ESP_BLE_MESH_MBT_MODEL_API_H_ */ diff --git a/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_mbt_model.h b/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_mbt_model.h index 4bb82ed1a3..3a90a7739e 100644 --- a/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_mbt_model.h +++ b/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_mbt_model.h @@ -19,6 +19,9 @@ extern "C" { #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif +#define BTC_BLE_MESH_MBT_CLIENT_RESULT_COMPLETE 0x00 +#define BTC_BLE_MESH_MBT_CLIENT_RESULT_FAIL 0x01 + typedef enum { BTC_BLE_MESH_ACT_MBT_CLIENT_RETRIEVE_CAPABILITIES, BTC_BLE_MESH_ACT_MBT_CLIENT_TRANSFER_BLOB, @@ -36,6 +39,49 @@ typedef enum { BTC_BLE_MESH_ACT_MBT_CLIENT_MAX, } btc_ble_mesh_mbt_client_act_t; +typedef enum { + BTC_BLE_MESH_EVT_MBT_CLIENT_RETRIEVE_CAPABILITIES_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_TRANSFER_BLOB_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_SEND_BLOCK_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_SEND_DATA_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_DETERMINE_BLOCK_STATUS_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_DETERMINE_TRANSFER_STATUS_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_CANCEL_TRANSFER_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_SET_TRANSFER_TTL_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_CLEAR_TRANSFER_TTL_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_SET_APP_IDX_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_CLEAR_APP_IDX_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_SET_MULTICAST_ADDR_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_CLEAR_MULTICAST_ADDR_COMP, + BTC_BLE_MESH_EVT_MBT_CLIENT_MAX, +} btc_ble_mesh_mbt_client_evt_t; + +typedef enum { + BTC_BLE_MESH_ACT_MBT_SERVER_INITIALIZE_BLOB_RECEIVE, + BTC_BLE_MESH_ACT_MBT_SERVER_CANCEL_BLOB_RECEIVE, + BTC_BLE_MESH_ACT_MBT_SERVER_SET_BLOB_CAPABILITIES, + BTC_BLE_MESH_ACT_MBT_SERVER_MAX, +} btc_ble_mesh_mbt_server_act_t; + +typedef enum { + BTC_BLE_MESH_EVT_MBT_SERVER_INITIALIZE_BLOB_RECEIVE_COMP, + BTC_BLE_MESH_EVT_MBT_SERVER_CANCEL_BLOB_RECEIVE_COMP, + BTC_BLE_MESH_EVT_MBT_SERVER_SET_BLOB_CAPABILITIES_COMP, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_TRANSFER_GET, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_TRANSFER_START, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_TRANSFER_CANCEL, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_BLOCK_GET, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_BLOCK_START, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_CHUNK_TRANSFER, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_INFORMATION_GET, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOCK_RECEIVE_COMP, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_RECEIVE_COMP, + BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_RECEIVE_TIMEOUT, + BTC_BLE_MESH_EVT_MBT_SERVER_MAX, +} btc_ble_mesh_mbt_server_evt_t; + +#if CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI + typedef union { esp_ble_mesh_retrieve_capabilities_t retrieve_capabilities; esp_ble_mesh_transfer_blob_t transfer_blob; @@ -67,26 +113,6 @@ typedef union { } clear_multicast_addr; } btc_ble_mesh_mbt_client_args_t; -#define BTC_BLE_MESH_MBT_CLIENT_RESULT_COMPLETE 0x00 -#define BTC_BLE_MESH_MBT_CLIENT_RESULT_FAIL 0x01 - -typedef enum { - BTC_BLE_MESH_EVT_MBT_CLIENT_RETRIEVE_CAPABILITIES_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_TRANSFER_BLOB_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_SEND_BLOCK_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_SEND_DATA_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_DETERMINE_BLOCK_STATUS_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_DETERMINE_TRANSFER_STATUS_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_CANCEL_TRANSFER_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_SET_TRANSFER_TTL_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_CLEAR_TRANSFER_TTL_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_SET_APP_IDX_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_CLEAR_APP_IDX_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_SET_MULTICAST_ADDR_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_CLEAR_MULTICAST_ADDR_COMP, - BTC_BLE_MESH_EVT_MBT_CLIENT_MAX, -} btc_ble_mesh_mbt_client_evt_t; - void btc_ble_mesh_mbt_client_call_handler(btc_msg_t *msg); void btc_ble_mesh_mbt_client_cb_handler(btc_msg_t *msg); @@ -103,12 +129,6 @@ void btc_ble_mesh_mbt_client_publish_callback(uint32_t opcode, void bt_mesh_mbt_client_cb_evt_to_btc(uint8_t event, uint8_t result, struct bt_mesh_model *model); -typedef enum { - BTC_BLE_MESH_ACT_MBT_SERVER_INITIALIZE_BLOB_RECEIVE, - BTC_BLE_MESH_ACT_MBT_SERVER_CANCEL_BLOB_RECEIVE, - BTC_BLE_MESH_ACT_MBT_SERVER_SET_BLOB_CAPABILITIES, - BTC_BLE_MESH_ACT_MBT_SERVER_MAX, -} btc_ble_mesh_mbt_server_act_t; typedef union { esp_ble_mesh_initialize_blob_receive_t initialize_blob_receive; @@ -116,23 +136,6 @@ typedef union { esp_ble_mesh_set_blob_capabilities_t set_blob_capabilities; } btc_ble_mesh_mbt_server_args_t; -typedef enum { - BTC_BLE_MESH_EVT_MBT_SERVER_INITIALIZE_BLOB_RECEIVE_COMP, - BTC_BLE_MESH_EVT_MBT_SERVER_CANCEL_BLOB_RECEIVE_COMP, - BTC_BLE_MESH_EVT_MBT_SERVER_SET_BLOB_CAPABILITIES_COMP, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_TRANSFER_GET, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_TRANSFER_START, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_TRANSFER_CANCEL, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_BLOCK_GET, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_BLOCK_START, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_CHUNK_TRANSFER, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_INFORMATION_GET, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOCK_RECEIVE_COMP, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_RECEIVE_COMP, - BTC_BLE_MESH_EVT_MBT_SERVER_BLOB_RECEIVE_TIMEOUT, - BTC_BLE_MESH_EVT_MBT_SERVER_MAX, -} btc_ble_mesh_mbt_server_evt_t; - void btc_ble_mesh_mbt_server_call_handler(btc_msg_t *msg); void btc_ble_mesh_mbt_server_cb_handler(btc_msg_t *msg); @@ -141,6 +144,8 @@ void bt_mesh_mbt_server_cb_evt_to_btc(uint8_t event, struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx); +#endif /* CONFIG_BLE_MESH_MBT_SRV || CONFIG_BLE_MESH_MBT_CLI */ + #if CONFIG_IDF_CI_BUILD #pragma GCC diagnostic pop #endif diff --git a/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c b/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c index e5ff20c328..21eea26d43 100644 --- a/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c @@ -1236,9 +1236,14 @@ int bt_mesh_dfu_cli_send(struct bt_mesh_dfu_cli *cli, cli->xfer.flags = 0U; if (xfer->blob_params) { - cli->xfer.flags |= FLAG_SKIP_CAPS_GET; - cli->xfer.blob.block_size_log = xfer->blob_params->block_size_log; - cli->xfer.blob.chunk_size = xfer->blob_params->chunk_size; + if (xfer->blob_params->block_size_log && + xfer->blob_params->chunk_size) { + cli->xfer.flags |= FLAG_SKIP_CAPS_GET; + cli->xfer.blob.block_size_log = xfer->blob_params->block_size_log; + cli->xfer.blob.chunk_size = xfer->blob_params->chunk_size; + } + memcpy(&cli->xfer.blob.chunk_enh_params, &xfer->blob_params->chunk_enh_params, + sizeof(bt_mesh_msg_enh_params_t)); } /* Phase will be set based on target status messages: */ diff --git a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h index 531e359994..306af5fbad 100644 --- a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h +++ b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h @@ -243,6 +243,8 @@ struct bt_mesh_dfu_cli_xfer_blob_params { uint8_t block_size_log; /** Base chunk size. May be smaller for the last chunk. */ uint16_t chunk_size; + /* Enhanced parameters for message context in blob chunks */ + bt_mesh_msg_enh_params_t chunk_enh_params; }; /** Firmware Update Client transfer parameters: */ diff --git a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h index 29199360a4..bd797e41ff 100644 --- a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h +++ b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h @@ -141,6 +141,8 @@ struct bt_mesh_blob_xfer { uint8_t block_size_log; /** Base chunk size. May be smaller for the last chunk. */ uint16_t chunk_size; + /* Enhanced parameters for message context in blob chunks */ + bt_mesh_msg_enh_params_t chunk_enh_params; }; /** BLOB stream interaction mode. */ diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob.h b/components/bt/esp_ble_mesh/v1.1/mbt/blob.h index c539219d9e..79d09d89f4 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob.h +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob.h @@ -34,19 +34,37 @@ #define BLOB_CHUNK_SIZE_MAX(sdu_max) ((sdu_max) - BLOB_CHUNK_SDU_OVERHEAD) #define BLOB_CHUNK_SDU_LEN(chunk_size) (BLOB_CHUNK_SDU_OVERHEAD + (chunk_size)) +#if CONFIG_BLE_MESH_LONG_PACKET +#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \ + CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_RX_SDU_MAX) +#define BLOB_RX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_RX_SDU_MAX) +#else +#define BLOB_RX_CHUNK_SIZE CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE +#endif +#else // CONFIG_BLE_MESH_LONG_PACKET #if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \ CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_RX_SDU_MAX) #define BLOB_RX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_RX_SDU_MAX) #else #define BLOB_RX_CHUNK_SIZE CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE #endif +#endif +#if CONFIG_BLE_MESH_LONG_PACKET +#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \ + CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_TX_SDU_MAX) +#define BLOB_TX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_TX_SDU_MAX) +#else +#define BLOB_TX_CHUNK_SIZE CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE +#endif +#else // CONFIG_BLE_MESH_LONG_PACKET #if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \ CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_TX_SDU_MAX) #define BLOB_TX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_TX_SDU_MAX) #else #define BLOB_TX_CHUNK_SIZE CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE #endif +#endif // CONFIG_BLE_MESH_LONG_PACKET /* Utility macros for calculating log2 of a number at compile time. * Used to determine the log2 representation of the block size, which diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c index 9132829a23..435ef3b5bc 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c @@ -18,6 +18,8 @@ #if CONFIG_BLE_MESH_BLOB_CLI +#define CHUNK_SIZE_MAX BLOB_TX_CHUNK_SIZE + #define TARGETS_FOR_EACH(cli, target) \ SYS_SLIST_FOR_EACH_CONTAINER((sys_slist_t *)&(cli)->inputs->targets, \ target, n) @@ -49,7 +51,8 @@ _Static_assert((BLOB_BLOCK_STATUS_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_BLO BLE_MESH_MIC_SHORT) <= BLE_MESH_RX_SDU_MAX, "The BLOB Block Status message does not fit into the maximum incoming SDU size."); -NET_BUF_SIMPLE_DEFINE_STATIC(chunk_buf, BLE_MESH_TX_SDU_MAX); +NET_BUF_SIMPLE_DEFINE_STATIC(chunk_buf, BLOB_CHUNK_SDU_LEN(CHUNK_SIZE_MAX)); +static bool chunk_sending; struct block_status { enum bt_mesh_blob_status status; @@ -591,6 +594,12 @@ static int tx(struct bt_mesh_blob_cli *cli, uint16_t addr, .addr = addr, .send_ttl = cli->inputs->ttl, }; + + if (chunk_sending) { + memcpy(&ctx.enh, &cli->xfer->chunk_enh_params, + sizeof(bt_mesh_msg_enh_params_t)); + } + int err; err = bt_mesh_model_send((struct bt_mesh_model *)cli->mod, &ctx, buf, &end_cb, cli); @@ -615,6 +624,10 @@ static void send_end(int err, void *user_data) { struct bt_mesh_blob_cli *cli = user_data; + if (chunk_sending) { + chunk_sending = false; + } + if (!cli->tx.ctx.is_inited) { return; } @@ -642,7 +655,12 @@ static void xfer_start_tx(struct bt_mesh_blob_cli *cli, uint16_t dst) net_buf_simple_add_le64(&buf, cli->xfer->id); net_buf_simple_add_le32(&buf, cli->xfer->size); net_buf_simple_add_u8(&buf, cli->xfer->block_size_log); +#if CONFIG_BLE_MESH_LONG_PACKET + /* todo: could let user select methold */ + net_buf_simple_add_le16(&buf, BLE_MESH_EXT_TX_SDU_MAX); +#else net_buf_simple_add_le16(&buf, BLE_MESH_TX_SDU_MAX); +#endif tx(cli, dst, &buf); } @@ -959,6 +977,8 @@ static void chunk_send(struct bt_mesh_blob_cli *cli) chunk_size(cli->xfer, &cli->block, cli->chunk_idx)); cli->state = BT_MESH_BLOB_CLI_STATE_BLOCK_SEND; + chunk_sending = true; + blob_cli_broadcast(cli, &ctx); } diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c b/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c index 3540a6abea..88fe61ad0b 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c @@ -25,7 +25,11 @@ #if CONFIG_BLE_MESH_BLOB_SRV +#if CONFIG_BLE_MESH_LONG_PACKET +#define MTU_SIZE_MAX (BLE_MESH_EXT_RX_SDU_MAX - BLE_MESH_MIC_SHORT) +#else #define MTU_SIZE_MAX (BLE_MESH_RX_SDU_MAX - BLE_MESH_MIC_SHORT) +#endif /* The Receive BLOB Timeout Timer */ #define SERVER_TIMEOUT_SECS(srv) (10 * (1 + (srv)->state.timeout_base)) diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index edf146769c..022913ca29 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -33,13 +33,6 @@ config BT_BTU_TASK_STACK_SIZE help This select btu task stack size -config BT_BLUEDROID_MEM_DEBUG - bool "Bluedroid memory debug" - depends on BT_BLUEDROID_ENABLED - default n - help - Bluedroid memory debug - config BT_BLUEDROID_ESP_COEX_VSC bool "Enable Espressif Vendor-specific HCI commands for coexist status configuration" depends on BT_BLUEDROID_ENABLED @@ -377,6 +370,23 @@ config BT_GATTS_APPEARANCE_WRITABLE help Enabling this option allows remote GATT clients to write appearance +config BT_GATTS_SECURITY_LEVELS_CHAR + bool "Enable LE GATT Security Levels Characteristic" + depends on BT_GATTS_ENABLE + default n + help + Enable LE GATT Security Levels Characteristic + +config BT_GATTS_KEY_MATERIAL_CHAR + bool "Enable Encrypted Data Key Material Characteristic" + depends on BT_GATTS_ENABLE + default n + help + Enable the Encrypted Data Key Material characteristic in GAP service. + This characteristic allows advertising data to be decrypted and authenticated + using the key material (session key + IV) as defined in Bluetooth Core + Specification Version 5.4. The characteristic requires encrypted link to read. + menuconfig BT_GATTC_ENABLE bool "Include GATT client module(GATTC)" depends on BT_BLE_ENABLED @@ -395,7 +405,7 @@ config BT_GATTC_MAX_CACHE_CHAR config BT_GATTC_NOTIF_REG_MAX int "Max gattc notify(indication) register number" depends on BT_GATTC_ENABLE - range 1 64 + range 1 255 default 5 help Maximum GATTC notify(indication) register number @@ -474,6 +484,48 @@ config BT_BLE_RPA_SUPPORTED For other BLE chips, devices support network privacy mode and device privacy mode, users can switch the two modes according to their own needs. So this option is enabled by default. +menu "Bluedroid debug option" + config BT_BLUEDROID_MEM_DEBUG + bool "Bluedroid memory debug" + depends on BT_BLUEDROID_ENABLED + default n + help + Bluedroid memory debug + + config BT_BLUEDROID_MEM_STATS + bool "Bluedroid memory statistics" + depends on BT_BLUEDROID_ENABLED + depends on !BT_BLUEDROID_MEM_DEBUG + default n + help + Enable Bluedroid memory usage statistics + + config BT_BLUEDROID_THREAD_DEBUG + bool "Bluedroid thread debug" + depends on BT_BLUEDROID_ENABLED + default n + help + Enable Bluedroid thread debug mode. + Used to debug whether the thread is blocked and + dump information about the thread’s related work queue. + + config BT_BLUEDROID_THREAD_BLOCK_TIME + int "OSI thread block time (in ms)" + depends on BT_BLUEDROID_THREAD_DEBUG + default 1000 + help + Indicates how long it takes for the thread to execute an item + before it is considered blocked. + + config BT_BLUEDROID_THREAD_BLOCK_MSG + int "OSI thread block message count" + depends on BT_BLUEDROID_THREAD_DEBUG + default 50 + help + Indicates how many messages are added to the queue + while the threadis executing an item before it is considered blocked. +endmenu #BT debug option + config BT_STACK_NO_LOG bool "Disable BT debug logs (minimize bin size)" depends on BT_BLUEDROID_ENABLED @@ -1302,7 +1354,7 @@ config BT_BLE_RPA_TIMEOUT Default is 900 s (15 minutes). Range is 1 s to 1 hour (3600 s). menuconfig BT_BLE_50_FEATURES_SUPPORTED - bool "Enable BLE 5.0 features(please disable BLE 4.2 if enable BLE 5.0)" + bool "Enable BLE 5.0 and above features(please disable BLE 4.2 if enable BLE 5.0)" depends on (BT_BLE_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_50_SUPPORTED) || BT_CONTROLLER_DISABLED)) default y help @@ -1366,36 +1418,15 @@ config BT_BLE_FEAT_CREATE_SYNC_ENH help Enable the create sync enhancements -menuconfig BT_BLE_42_FEATURES_SUPPORTED - bool "Enable BLE 4.2 features(please disable BLE 5.0 if enable BLE 4.2)" - depends on BT_BLE_ENABLED - default y if IDF_TARGET_ESP32 - default n +config BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX + int "Maximum retry count for periodic advertising create sync" + depends on BT_BLE_50_EXTEND_SYNC_EN + default 3 + range 0 16 help - This enables BLE 4.2 features. - This option is universally supported by all ESP chips with BLE capabilities. - BLE 4.2 and BLE 5.0 cannot be used simultaneously. - -config BT_BLE_42_DTM_TEST_EN - bool "Enable BLE 4.2 DTM test" - depends on BT_BLE_42_FEATURES_SUPPORTED - default y - help - This enables BLE 4.2 direct test mode - -config BT_BLE_42_ADV_EN - bool "Enable BLE 4.2 advertising" - depends on BT_BLE_42_FEATURES_SUPPORTED - default y - help - This enables BLE v4.2 advertising - -config BT_BLE_42_SCAN_EN - bool "Enable BLE 4.2 scan" - depends on BT_BLE_42_FEATURES_SUPPORTED - default y - help - This enables BLE v4.2 scan + Set the maximum retry count when periodic advertising create sync fails + with error code 0x3E (Connection Failed to be Established). + Set to 0 to disable retry. Default is 3. menuconfig BT_BLE_FEAT_ISO_EN bool "Enable BLE 5.2 iso feature" @@ -1509,6 +1540,58 @@ config BT_BLE_FEAT_CONN_SUBRATING help Enable BLE connection subrating feature +config BT_BLE_FEAT_PAWR_EN + bool "Enable Periodic Advertisement with Response(PAwR)" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_PAWR_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable BLE Periodic Advertisement with Response(PAwR) feature + +config BT_BLE_FEAT_ADV_CODING_SELECTION + bool "Enable Advertising Coding Selection" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_ADV_CODING_SELECT_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable Advertising Coding Selection + +config BT_BLE_FEAT_CHANNEL_SOUNDING + bool "Enable BLE channel sounding" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_CHANNEL_SOUNDING_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable BLE channel sounding + +menuconfig BT_BLE_42_FEATURES_SUPPORTED + bool "Enable BLE 4.2 features(please disable BLE 5.0 if enable BLE 4.2)" + depends on BT_BLE_ENABLED + default y if IDF_TARGET_ESP32 + default n + help + This enables BLE 4.2 features. + This option is universally supported by all ESP chips with BLE capabilities. + BLE 4.2 and BLE 5.0 cannot be used simultaneously. + +config BT_BLE_42_DTM_TEST_EN + bool "Enable BLE 4.2 DTM test" + depends on BT_BLE_42_FEATURES_SUPPORTED + default y + help + This enables BLE 4.2 direct test mode + +config BT_BLE_42_ADV_EN + bool "Enable BLE 4.2 advertising" + depends on BT_BLE_42_FEATURES_SUPPORTED + default y + help + This enables BLE v4.2 advertising + +config BT_BLE_42_SCAN_EN + bool "Enable BLE 4.2 scan" + depends on BT_BLE_42_FEATURES_SUPPORTED + default y + help + This enables BLE v4.2 scan + config BT_BLE_VENDOR_HCI_EN bool "Enable BLE Vendor HCI command and event" depends on BT_BLE_ENABLED diff --git a/components/bt/host/bluedroid/api/esp_ble_iso_api.c b/components/bt/host/bluedroid/api/esp_ble_iso_api.c index 826991e6bf..d2239844f0 100644 --- a/components/bt/host/bluedroid/api/esp_ble_iso_api.c +++ b/components/bt/host/bluedroid/api/esp_ble_iso_api.c @@ -37,6 +37,10 @@ esp_err_t esp_ble_iso_create_big(esp_ble_iso_big_creat_params_t *big_creat_param return ESP_ERR_INVALID_ARG; } + if (big_creat_param->num_bis > BLE_ISO_BIS_MAX_COUNT) { + return ESP_ERR_INVALID_ARG; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_ISO_BLE; msg.act = BTC_ISO_ACT_BIG_CREATE; @@ -58,6 +62,10 @@ esp_err_t esp_ble_iso_create_big_test(esp_ble_iso_big_creat_test_params_t *big_c return ESP_ERR_INVALID_ARG; } + if (big_creat_test_param->num_bis > BLE_ISO_BIS_MAX_COUNT) { + return ESP_ERR_INVALID_ARG; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_ISO_BLE; msg.act = BTC_ISO_ACT_BIG_CREATE_TEST; diff --git a/components/bt/host/bluedroid/api/esp_bt_main.c b/components/bt/host/bluedroid/api/esp_bt_main.c index fb7d59f02f..a728e81c35 100644 --- a/components/bt/host/bluedroid/api/esp_bt_main.c +++ b/components/bt/host/bluedroid/api/esp_bt_main.c @@ -153,6 +153,13 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg) osi_mem_dbg_init(); #endif +#if HEAP_MEMORY_STATS + if (osi_mem_init() != 0) { + LOG_ERROR("Bluedroid Initialize Fail"); + return ESP_FAIL; + } +#endif + ret = bluedroid_config_init(cfg); if (ret != BT_STATUS_SUCCESS) { LOG_ERROR("Bluedroid stack initialize fail, ret:%d", ret); @@ -243,6 +250,10 @@ esp_err_t esp_bluedroid_deinit(void) bt_hci_log_deinit(); #endif // (BT_HCI_LOG_INCLUDED == TRUE) +#if HEAP_MEMORY_STATS + osi_mem_deinit(); +#endif + s_bt_host_state = ESP_BLUEDROID_STATUS_UNINITIALIZED; return ESP_OK; } diff --git a/components/bt/host/bluedroid/api/esp_gap_ble_api.c b/components/bt/host/bluedroid/api/esp_gap_ble_api.c index d592b6b77f..7dfe9dd3dd 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -440,6 +440,28 @@ esp_err_t esp_ble_gap_get_device_name(void) return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +esp_err_t esp_ble_gap_set_key_material(const uint8_t session_key[16], const uint8_t iv[8]) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (session_key == NULL || iv == NULL) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ACT_SET_KEY_MATERIAL; + memcpy(arg.set_key_material.session_key, session_key, 16); + memcpy(arg.set_key_material.iv, iv, 8); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + esp_err_t esp_ble_gap_get_local_used_addr(esp_bd_addr_t local_used_addr, uint8_t * addr_type) { if(esp_bluedroid_get_status() != (ESP_BLUEDROID_STATUS_ENABLED)) { @@ -502,6 +524,29 @@ esp_err_t esp_ble_gap_config_adv_data_raw(uint8_t *raw_data, uint32_t raw_data_l btc_gap_ble_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } + +esp_err_t esp_ble_gap_config_scan_rsp_data_raw(uint8_t *raw_data, uint32_t raw_data_len) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if ((raw_data_len != 0 && raw_data == NULL) || raw_data_len > ESP_BLE_ADV_DATA_LEN_MAX) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ACT_CFG_SCAN_RSP_DATA_RAW; + arg.cfg_scan_rsp_data_raw.raw_scan_rsp = raw_data; + arg.cfg_scan_rsp_data_raw.raw_scan_rsp_len = raw_data_len; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, + btc_gap_ble_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + +} + #endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gap_read_rssi(esp_bd_addr_t remote_addr) @@ -525,28 +570,7 @@ esp_err_t esp_ble_gap_read_rssi(esp_bd_addr_t remote_addr) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } -#if (BLE_42_FEATURE_SUPPORT == TRUE) -esp_err_t esp_ble_gap_config_scan_rsp_data_raw(uint8_t *raw_data, uint32_t raw_data_len) -{ - btc_msg_t msg = {0}; - btc_ble_gap_args_t arg; - - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - - if ((raw_data_len != 0 && raw_data == NULL) || raw_data_len > ESP_BLE_ADV_DATA_LEN_MAX) { - return ESP_ERR_INVALID_ARG; - } - - msg.sig = BTC_SIG_API_CALL; - msg.pid = BTC_PID_GAP_BLE; - msg.act = BTC_GAP_BLE_ACT_CFG_SCAN_RSP_DATA_RAW; - arg.cfg_scan_rsp_data_raw.raw_scan_rsp = raw_data; - arg.cfg_scan_rsp_data_raw.raw_scan_rsp_len = raw_data_len; - - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, - btc_gap_ble_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); - -} +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) esp_err_t esp_ble_gap_add_duplicate_scan_exceptional_device(esp_ble_duplicate_exceptional_info_type_t type, esp_duplicate_info_t device_info) { @@ -614,7 +638,8 @@ esp_err_t esp_ble_gap_clean_duplicate_scan_exceptional_list(esp_duplicate_scan_e return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } -#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) + #if (SMP_INCLUDED == TRUE) esp_err_t esp_ble_gap_set_security_param(esp_ble_sm_param_t param_type, void *value, uint8_t len) @@ -1940,6 +1965,10 @@ esp_err_t esp_ble_gap_set_path_loss_reporting_params(esp_ble_path_loss_rpt_param return ESP_ERR_INVALID_STATE; } + if (path_loss_rpt_params == NULL) { + return ESP_ERR_INVALID_ARG; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GAP_BLE; msg.act = BTC_GAP_BLE_SET_PATH_LOSS_REPORT_PARAMS; @@ -2006,7 +2035,7 @@ esp_err_t esp_ble_gap_set_default_subrate(esp_ble_default_subrate_param_t *defau } if (!default_subrate_params) { - return ESP_ERR_NOT_ALLOWED; + return ESP_ERR_INVALID_ARG; } msg.sig = BTC_SIG_API_CALL; @@ -2033,7 +2062,7 @@ esp_err_t esp_ble_gap_subrate_request(esp_ble_subrate_req_param_t *subrate_req_p } if (!subrate_req_params) { - return ESP_ERR_NOT_ALLOWED; + return ESP_ERR_INVALID_ARG; } msg.sig = BTC_SIG_API_CALL; @@ -2082,3 +2111,437 @@ esp_err_t esp_ble_gap_set_host_feature(uint16_t bit_num, uint8_t bit_val) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) + +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +esp_err_t esp_ble_gap_set_periodic_adv_subevent_data(esp_ble_per_adv_subevent_data_params *subevent_data_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((!subevent_data_params) || (!subevent_data_params->subevent_params)) { + return ESP_ERR_NOT_ALLOWED; + } + + if ((subevent_data_params->num_subevents_with_data > 0x0F) || (!subevent_data_params->num_subevents_with_data)) { + return ESP_ERR_NOT_ALLOWED; + } + + for (uint8_t i = 0; i < subevent_data_params->num_subevents_with_data; i++) + { + if (subevent_data_params->subevent_params[i].subevent_data_len && (subevent_data_params->subevent_params[i].subevent_data == NULL)) { + return ESP_ERR_NOT_ALLOWED; + } + } + + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_PA_SUBEVT_DATA; + + arg.per_adv_subevent_data_params.adv_handle = subevent_data_params->adv_handle; + arg.per_adv_subevent_data_params.num_subevents_with_data = subevent_data_params->num_subevents_with_data; + arg.per_adv_subevent_data_params.subevent_params = subevent_data_params->subevent_params; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, btc_gap_ble_arg_deep_free) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_set_periodic_adv_response_data(esp_ble_per_adv_response_data_params *rsp_data_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!rsp_data_params) { + return ESP_ERR_NOT_ALLOWED; + } + + if ((rsp_data_params->response_data == NULL) && rsp_data_params->response_data_len) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_PA_RSP_DATA; + + arg.per_adv_response_data_params.sync_handle = rsp_data_params->sync_handle; + arg.per_adv_response_data_params.request_event = rsp_data_params->request_event; + arg.per_adv_response_data_params.request_subevent = rsp_data_params->request_subevent; + arg.per_adv_response_data_params.response_subevent = rsp_data_params->response_subevent; + arg.per_adv_response_data_params.response_slot = rsp_data_params->response_slot; + arg.per_adv_response_data_params.response_data_len = rsp_data_params->response_data_len; + arg.per_adv_response_data_params.response_data = rsp_data_params->response_data; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, btc_gap_ble_arg_deep_free) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_set_periodic_sync_subevent(esp_ble_per_sync_subevent_params *sync_subevent_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!sync_subevent_params) { + return ESP_ERR_NOT_ALLOWED; + } + + if ((sync_subevent_params->subevent == NULL) && sync_subevent_params->num_subevents_to_sync) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_PA_SYNC_SUBEVT; + + arg.per_sync_subevent_params.sync_handle = sync_subevent_params->sync_handle; + arg.per_sync_subevent_params.periodic_adv_properties = sync_subevent_params->periodic_adv_properties; + arg.per_sync_subevent_params.num_subevents_to_sync = sync_subevent_params->num_subevents_to_sync; + arg.per_sync_subevent_params.subevent = sync_subevent_params->subevent; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, btc_gap_ble_arg_deep_free) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +esp_err_t esp_ble_cs_read_local_supported_capabilities(void) +{ + btc_msg_t msg = {0}; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_READ_LOCAL_SUPPORTED_CAPS; + + return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_read_remote_supported_capabilities(uint16_t conn_handle) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_READ_REMOTE_SUPPORTED_CAPS; + + arg.cs_read_remote_supp_caps.conn_handle = conn_handle; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_write_cached_remote_supported_capabilities(esp_ble_cs_write_cached_remote_supp_caps_params *cached_remote_supp_caps_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg = {0}; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!cached_remote_supp_caps_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPS; + + arg.cs_write_cached_remote_supp_caps.conn_handle = cached_remote_supp_caps_params->conn_handle; + arg.cs_write_cached_remote_supp_caps.num_config_supported = cached_remote_supp_caps_params->num_config_supported; + arg.cs_write_cached_remote_supp_caps.max_consecutive_proc_supported = cached_remote_supp_caps_params->max_consecutive_proc_supported; + arg.cs_write_cached_remote_supp_caps.num_ant_supported = cached_remote_supp_caps_params->num_ant_supported; + arg.cs_write_cached_remote_supp_caps.max_ant_paths_supported = cached_remote_supp_caps_params->max_ant_paths_supported; + arg.cs_write_cached_remote_supp_caps.modes_supported = cached_remote_supp_caps_params->modes_supported; + arg.cs_write_cached_remote_supp_caps.rtt_capability = cached_remote_supp_caps_params->rtt_capability; + arg.cs_write_cached_remote_supp_caps.rtt_aa_only_n = cached_remote_supp_caps_params->rtt_aa_only_n; + arg.cs_write_cached_remote_supp_caps.rtt_sounding_n = cached_remote_supp_caps_params->rtt_sounding_n; + arg.cs_write_cached_remote_supp_caps.rtt_random_payload_n = cached_remote_supp_caps_params->rtt_random_payload_n; + arg.cs_write_cached_remote_supp_caps.NADM_sounding_capability = cached_remote_supp_caps_params->NADM_sounding_capability; + arg.cs_write_cached_remote_supp_caps.NADM_random_capability = cached_remote_supp_caps_params->NADM_random_capability; + arg.cs_write_cached_remote_supp_caps.subfeatures_supported = cached_remote_supp_caps_params->subfeatures_supported; + arg.cs_write_cached_remote_supp_caps.T_IP1_times_supported = cached_remote_supp_caps_params->T_IP1_times_supported; + arg.cs_write_cached_remote_supp_caps.T_IP2_times_supported = cached_remote_supp_caps_params->T_IP2_times_supported; + arg.cs_write_cached_remote_supp_caps.T_FCS_times_supported = cached_remote_supp_caps_params->T_FCS_times_supported; + arg.cs_write_cached_remote_supp_caps.T_PM_times_supported = cached_remote_supp_caps_params->T_PM_times_supported; + arg.cs_write_cached_remote_supp_caps.T_SW_times_supported = cached_remote_supp_caps_params->T_SW_times_supported; + arg.cs_write_cached_remote_supp_caps.TX_SNR_capability = cached_remote_supp_caps_params->TX_SNR_capability; + if (cached_remote_supp_caps_params->initiator_role_supported) { + arg.cs_write_cached_remote_supp_caps.roles_supported |= ESP_BLE_CS_INITIATOR_ROLE_SUPPORTED; + } + if (cached_remote_supp_caps_params->reflector_role_supported) { + arg.cs_write_cached_remote_supp_caps.roles_supported |= ESP_BLE_CS_REFLECTOR_ROLE_SUPPORTED; + } + if (cached_remote_supp_caps_params->cs_sync_2m_phy_supported) { + arg.cs_write_cached_remote_supp_caps.cs_sync_phys_supported |= ESP_BLE_CS_SYNC_PHYS_2M_SUPPORTED; + } + if (cached_remote_supp_caps_params->cs_sync_2m_2bt_phy_supported) { + arg.cs_write_cached_remote_supp_caps.cs_sync_phys_supported |= ESP_BLE_CS_SYNC_PHYS_2M_2BT_SUPPORTED; + } + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_security_enable(uint16_t conn_handle) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_SECURITY_ENABLE; + + arg.cs_security_enable.conn_handle = conn_handle; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_set_default_settings(esp_ble_cs_set_default_settings_params *default_setting_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg = {0}; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!default_setting_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_SET_DEFAULT_SETTINGS; + + arg.cs_set_default_settings_params.conn_handle = default_setting_params->conn_handle; + arg.cs_set_default_settings_params.cs_sync_ant_selection = default_setting_params->cs_sync_ant_selection; + arg.cs_set_default_settings_params.max_tx_power = default_setting_params->max_tx_power; + if (default_setting_params->initiator_role_enable) { + arg.cs_set_default_settings_params.role_enable |= ESP_BLE_CS_INITIATOR_ROLE_ENABLED; + } + if (default_setting_params->reflector_role_enable) { + arg.cs_set_default_settings_params.role_enable |= ESP_BLE_CS_REFLECTOR_ROLE_ENABLED; + } + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_read_remote_fae_table(uint16_t conn_handle) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_READ_REMOTE_FAE_TABLE; + + arg.cs_read_remote_tab.conn_handle = conn_handle; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_write_cached_remote_fae_table(esp_ble_cs_write_cached_remote_fae_table_params *write_cached_remote_fae_tab_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg = {0}; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!write_cached_remote_fae_tab_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_WRITE_CACHED_REMOTE_FAE_TABLE; + + arg.cs_write_cached_remote_fae_table_params.conn_handle = write_cached_remote_fae_tab_params->conn_handle; + memcpy(arg.cs_write_cached_remote_fae_table_params.remote_fae_table, write_cached_remote_fae_tab_params->remote_fae_table, sizeof(arg.cs_write_cached_remote_fae_table_params.remote_fae_table)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_create_config(esp_ble_cs_create_config_params *create_config_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg = {0}; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!create_config_params) { + return ESP_ERR_NOT_ALLOWED; + } + + arg.cs_create_config_params.conn_handle = create_config_params->conn_handle; + arg.cs_create_config_params.config_id = create_config_params->config_id; + arg.cs_create_config_params.create_context = create_config_params->create_context; + arg.cs_create_config_params.main_mode_type = create_config_params->main_mode_type; + arg.cs_create_config_params.sub_mode_type = create_config_params->sub_mode_type; + arg.cs_create_config_params.min_main_mode_steps = create_config_params->min_main_mode_steps; + arg.cs_create_config_params.max_main_mode_steps = create_config_params->max_main_mode_steps; + arg.cs_create_config_params.main_mode_repetition = create_config_params->main_mode_repetition; + arg.cs_create_config_params.mode_0_steps = create_config_params->mode_0_steps; + arg.cs_create_config_params.role = create_config_params->role; + arg.cs_create_config_params.rtt_type = create_config_params->rtt_type; + arg.cs_create_config_params.cs_sync_phy = create_config_params->cs_sync_phy; + memcpy(arg.cs_create_config_params.channel_map, create_config_params->channel_map, sizeof(arg.cs_create_config_params.channel_map)); + arg.cs_create_config_params.channel_map_repetition = create_config_params->channel_map_repetition; + arg.cs_create_config_params.channel_selection_type = create_config_params->channel_selection_type; + arg.cs_create_config_params.ch3c_shape = create_config_params->ch3c_shape; + arg.cs_create_config_params.ch3c_jump = create_config_params->ch3c_jump; + arg.cs_create_config_params.reserved = create_config_params->reserved; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_CREATE_CONFIG; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_remove_config(esp_ble_cs_remove_config_params *remove_config_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!remove_config_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_REMOVE_CONFIG; + + arg.cs_remove_config_params.conn_handle = remove_config_params->conn_handle; + arg.cs_remove_config_params.config_id = remove_config_params->config_id; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_set_channel_classification(esp_ble_cs_set_channel_class_params *channel_class_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!channel_class_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_SET_CAHNNEL_CLASSIFICATION; + + memcpy(arg.cs_set_channel_class_params.channel_class, channel_class_params->channel_class, sizeof(arg.cs_set_channel_class_params)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_set_procedure_params(esp_ble_cs_set_proc_params *procedure_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!procedure_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_SET_PROCEDURE_PARAMS; + + arg.cs_set_procedure_params.conn_handle = procedure_params->conn_handle; + arg.cs_set_procedure_params.config_id = procedure_params->config_id; + arg.cs_set_procedure_params.max_procedure_len = procedure_params->max_procedure_len; + arg.cs_set_procedure_params.min_procedure_interval = procedure_params->min_procedure_interval; + arg.cs_set_procedure_params.max_procedure_interval = procedure_params->max_procedure_interval; + arg.cs_set_procedure_params.max_procedure_count = procedure_params->max_procedure_count; + arg.cs_set_procedure_params.min_subevent_len = (procedure_params->min_subevent_len & 0x00FFFFFF); + arg.cs_set_procedure_params.max_subevent_len = (procedure_params->max_subevent_len & 0x00FFFFFF); + arg.cs_set_procedure_params.tone_ant_config_selection = procedure_params->tone_ant_config_selection; + arg.cs_set_procedure_params.phy = procedure_params->phy; + arg.cs_set_procedure_params.tx_power_delta = procedure_params->tx_power_delta; + arg.cs_set_procedure_params.preferred_peer_antenna = procedure_params->preferred_peer_antenna; + arg.cs_set_procedure_params.SNR_control_initiator = procedure_params->SNR_control_initiator; + arg.cs_set_procedure_params.SNR_control_reflector = procedure_params->SNR_control_reflector; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cs_procedure_enable(esp_ble_cs_procedure_enable_params *procedure_enable_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!procedure_enable_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_CS_PROCEDURE_ENABLE; + + arg.cs_procedure_enable_params.conn_handle = procedure_enable_params->conn_handle; + arg.cs_procedure_enable_params.config_id = procedure_enable_params->config_id; + arg.cs_procedure_enable_params.enable = procedure_enable_params->enable; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +#endif diff --git a/components/bt/host/bluedroid/api/esp_gattc_api.c b/components/bt/host/bluedroid/api/esp_gattc_api.c index 00c6a96e0b..f54deb8ea2 100644 --- a/components/bt/host/bluedroid/api/esp_gattc_api.c +++ b/components/bt/host/bluedroid/api/esp_gattc_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -88,6 +88,11 @@ esp_err_t esp_ble_gattc_enh_open(esp_gatt_if_t gattc_if, esp_ble_gatt_creat_conn arg.open.remote_addr_type = creat_conn_params->remote_addr_type; arg.open.is_direct = creat_conn_params->is_direct; arg.open.is_aux= creat_conn_params->is_aux; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + arg.open.is_pawr_synced = false; + arg.open.adv_handle = 0xFF; + arg.open.subevent = 0xFF; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) arg.open.own_addr_type = creat_conn_params->own_addr_type; arg.open.phy_mask = creat_conn_params->phy_mask; @@ -206,6 +211,106 @@ esp_err_t esp_ble_gattc_aux_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bd } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +esp_err_t esp_ble_gattc_aux_open_with_pawr_synced(esp_gatt_if_t gattc_if, esp_ble_gatt_pawr_conn_params_t *pawr_conn_params) +{ + btc_msg_t msg = {0}; + btc_ble_gattc_args_t arg; + const esp_ble_conn_params_t *conn_params; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (!pawr_conn_params) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GATTC; + msg.act = BTC_GATTC_ACT_OPEN; + arg.open.gattc_if = gattc_if; + memcpy(arg.open.remote_bda, pawr_conn_params->remote_bda, ESP_BD_ADDR_LEN); + arg.open.remote_addr_type = pawr_conn_params->remote_addr_type; + arg.open.is_direct = true; + arg.open.is_aux = true; + arg.open.is_pawr_synced = true; + arg.open.adv_handle = pawr_conn_params->adv_handle; + arg.open.subevent = pawr_conn_params->subevent; + arg.open.own_addr_type = pawr_conn_params->own_addr_type; + arg.open.phy_mask = pawr_conn_params->phy_mask; + + if (pawr_conn_params->phy_mask & ESP_BLE_PHY_1M_PREF_MASK) { + if (!pawr_conn_params->phy_1m_conn_params) { + return ESP_ERR_INVALID_ARG; + } + + conn_params = pawr_conn_params->phy_1m_conn_params; + if (ESP_BLE_IS_VALID_PARAM(conn_params->interval_min, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->interval_max, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) && + (conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) && + ((conn_params->supervision_timeout * 10) >= ((1 + conn_params->latency) * ((conn_params->interval_max * 5) >> 1))) && + (conn_params->interval_min <= conn_params->interval_max)) { + memcpy(&arg.open.phy_1m_conn_params, conn_params, sizeof(esp_ble_conn_params_t)); + } else { + LOG_ERROR("%s, invalid 1M PHY connection params: min_int = %d, max_int = %d, latency = %d, timeout = %d", __func__, + conn_params->interval_min, + conn_params->interval_max, + conn_params->latency, + conn_params->supervision_timeout); + return ESP_ERR_INVALID_ARG; + } + } + + if (pawr_conn_params->phy_mask & ESP_BLE_PHY_2M_PREF_MASK) { + if (!pawr_conn_params->phy_2m_conn_params) { + return ESP_ERR_INVALID_ARG; + } + + conn_params = pawr_conn_params->phy_2m_conn_params; + if (ESP_BLE_IS_VALID_PARAM(conn_params->interval_min, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->interval_max, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) && + (conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) && + ((conn_params->supervision_timeout * 10) >= ((1 + conn_params->latency) * ((conn_params->interval_max * 5) >> 1))) && + (conn_params->interval_min <= conn_params->interval_max)) { + memcpy(&arg.open.phy_2m_conn_params, conn_params, sizeof(esp_ble_conn_params_t)); + } else { + LOG_ERROR("%s, invalid 2M PHY connection params: min_int = %d, max_int = %d, latency = %d, timeout = %d", __func__, + conn_params->interval_min, + conn_params->interval_max, + conn_params->latency, + conn_params->supervision_timeout); + return ESP_ERR_INVALID_ARG; + } + } + + if (pawr_conn_params->phy_mask & ESP_BLE_PHY_CODED_PREF_MASK) { + if (!pawr_conn_params->phy_coded_conn_params) { + return ESP_ERR_INVALID_ARG; + } + + conn_params = pawr_conn_params->phy_coded_conn_params; + if (ESP_BLE_IS_VALID_PARAM(conn_params->interval_min, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->interval_max, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) && + (conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) && + ((conn_params->supervision_timeout * 10) >= ((1 + conn_params->latency) * ((conn_params->interval_max * 5) >> 1))) && + (conn_params->interval_min <= conn_params->interval_max)) { + memcpy(&arg.open.phy_coded_conn_params, conn_params, sizeof(esp_ble_conn_params_t)); + } else { + LOG_ERROR("%s, invalid Coded PHY connection params: min_int = %d, max_int = %d, latency = %d, timeout = %d", __func__, + conn_params->interval_min, + conn_params->interval_max, + conn_params->latency, + conn_params->supervision_timeout); + return ESP_ERR_INVALID_ARG; + } + } + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + esp_err_t esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id) { btc_msg_t msg = {0}; diff --git a/components/bt/host/bluedroid/api/include/api/esp_a2dp_api.h b/components/bt/host/bluedroid/api/include/api/esp_a2dp_api.h index 71d3d597e9..24f6aef8f1 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_a2dp_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_a2dp_api.h @@ -19,56 +19,44 @@ extern "C" { typedef uint16_t esp_a2d_conn_hdl_t; /*!< Connection handle, associate with specific device that connected */ -/** - * @brief Media codec types supported by A2DP. - */ +/* Media codec types supported by A2DP. */ #define ESP_A2D_MCT_SBC (0) /*!< SBC */ #define ESP_A2D_MCT_M12 (0x01) /*!< MPEG-1, 2 Audio */ #define ESP_A2D_MCT_M24 (0x02) /*!< MPEG-2, 4 AAC */ #define ESP_A2D_MCT_ATRAC (0x04) /*!< ATRAC family */ #define ESP_A2D_MCT_NON_A2DP (0xff) /*!< NON-A2DP */ -typedef uint8_t esp_a2d_mct_t; +typedef uint8_t esp_a2d_mct_t; /*!< Media codec type of A2DP */ -/** - * @brief Protocol service capabilities. This value is a mask. - */ +/* Protocol service capabilities. This value is a mask. */ #define ESP_A2D_PSC_DELAY_RPT (1<<0) /*!< Delay Report */ -typedef uint16_t esp_a2d_psc_t; +typedef uint16_t esp_a2d_psc_t; /*!< Protocol service capabilities type */ -/** - * @brief A2DP SBC sampling frequency bit mask in CIE - */ +/* A2DP SBC sampling frequency bit mask in CIE */ #define ESP_A2D_SBC_CIE_SF_16K (0x8) /*!< SBC sampling frequency 16kHz */ #define ESP_A2D_SBC_CIE_SF_32K (0x4) /*!< SBC sampling frequency 32kHz */ #define ESP_A2D_SBC_CIE_SF_44K (0x2) /*!< SBC sampling frequency 44.1kHz */ #define ESP_A2D_SBC_CIE_SF_48K (0x1) /*!< SBC sampling frequency 48kHz */ -/** - * @brief A2DP SBC channel mode bit mask in CIE - */ +/* A2DP SBC channel mode bit mask in CIE */ #define ESP_A2D_SBC_CIE_CH_MODE_MONO (0x8) /*!< SBC channel mode Mono */ #define ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL (0x4) /*!< SBC channel mode Dual Channel */ #define ESP_A2D_SBC_CIE_CH_MODE_STEREO (0x2) /*!< SBC channel mode Stereo */ -#define ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO (0x1) /*!< SBC channel mode Stereo */ +#define ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO (0x1) /*!< SBC channel mode Joint Stereo */ -/** - * @brief A2DP SBC block length bit mask in CIE - */ +/* A2DP SBC block length bit mask in CIE */ #define ESP_A2D_SBC_CIE_BLOCK_LEN_4 (0x8) /*!< SBC block length 4 */ #define ESP_A2D_SBC_CIE_BLOCK_LEN_8 (0x4) /*!< SBC block length 8 */ #define ESP_A2D_SBC_CIE_BLOCK_LEN_12 (0x2) /*!< SBC block length 12 */ #define ESP_A2D_SBC_CIE_BLOCK_LEN_16 (0x1) /*!< SBC block length 16 */ -/** - * @brief A2DP SBC number of subbands bit mask in CIE - */ +/* A2DP SBC number of subbands bit mask in CIE */ #define ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 (0x2) /*!< SBC number of subbands 4 */ #define ESP_A2D_SBC_CIE_NUM_SUBBANDS_8 (0x1) /*!< SBC number of subbands 8 */ -/** - * @brief A2DP SBC allocation method bit mask in CIE - */ -#define ESP_A2D_SBC_CIE_ALLOC_MTHD_SRN (0x2) /*!< SBC allocation method SNR */ +/* A2DP SBC allocation method bit mask in CIE */ +#define ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR (0x2) /*!< SBC allocation method SNR */ +/*!< @deprecated Renamed to ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR */ +#define ESP_A2D_SBC_CIE_ALLOC_MTHD_SRN _Pragma("GCC warning \"'ESP_A2D_SBC_CIE_ALLOC_MTHD_SRN' macro is deprecated, use 'ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR'\"") ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR #define ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS (0x1) /*!< SBC allocation method Loudness */ /** @@ -136,10 +124,10 @@ typedef struct { */ typedef struct { esp_a2d_mct_t type; /*!< A2DP media codec type */ -#define ESP_A2D_CIE_LEN_SBC (4) -#define ESP_A2D_CIE_LEN_M12 (4) -#define ESP_A2D_CIE_LEN_M24 (6) -#define ESP_A2D_CIE_LEN_ATRAC (7) +#define ESP_A2D_CIE_LEN_SBC (4) /*!< SBC cie length */ +#define ESP_A2D_CIE_LEN_M12 (4) /*!< MPEG-1,2 cie length */ +#define ESP_A2D_CIE_LEN_M24 (6) /*!< MPEG-2,4 AAC cie length */ +#define ESP_A2D_CIE_LEN_ATRAC (7) /*!< ATRAC family cie length */ union { uint8_t sbc[ESP_A2D_CIE_LEN_SBC] __attribute__((deprecated)); /*!< SBC codec capabilities, deprecated, use sbc_info instead */ uint8_t m12[ESP_A2D_CIE_LEN_M12] __attribute__((deprecated)); /*!< MPEG-1,2 audio codec capabilities, deprecated, use m12_info instead */ @@ -206,7 +194,7 @@ typedef enum { */ typedef enum { ESP_A2D_DEINIT_SUCCESS = 0, /*!< A2DP profile deinit successful event */ - ESP_A2D_INIT_SUCCESS /*!< A2DP profile deinit successful event */ + ESP_A2D_INIT_SUCCESS /*!< A2DP profile init successful event */ } esp_a2d_init_state_t; /** @@ -245,7 +233,7 @@ typedef enum { ESP_A2D_AUDIO_CFG_EVT, /*!< audio codec is configured */ ESP_A2D_MEDIA_CTRL_ACK_EVT, /*!< acknowledge event in response to media control commands */ ESP_A2D_PROF_STATE_EVT, /*!< indicate a2dp init&deinit complete */ - ESP_A2D_SEP_REG_STATE_EVT, /*!< indicate a2dp steam endpoint register status */ + ESP_A2D_SEP_REG_STATE_EVT, /*!< indicate a2dp stream endpoint register status */ ESP_A2D_SNK_PSC_CFG_EVT, /*!< protocol service capabilities configured,only used for A2DP SINK */ ESP_A2D_SNK_SET_DELAY_VALUE_EVT, /*!< indicate a2dp sink set delay report value complete, only used for A2DP SINK */ ESP_A2D_SNK_GET_DELAY_VALUE_EVT, /*!< indicate a2dp sink get delay report value complete, only used for A2DP SINK */ @@ -353,9 +341,9 @@ typedef union { /** * @brief A2DP profile callback function type * - * @param event : Event type + * @param[in] event : Event type * - * @param param : Pointer to callback parameter + * @param[in] param : Pointer to callback parameter */ typedef void (* esp_a2d_cb_t)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); @@ -602,7 +590,7 @@ esp_err_t esp_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mc esp_err_t esp_a2d_source_deinit(void); /** - * @brief Send a audio buff with encoded audio data to sink, the audio data len shall not bigger than + * @brief Send an audio buffer with encoded audio data to sink. The audio data length shall not be bigger than * audio connection mtu (retrieved from ESP_A2D_CONNECTION_STATE_EVT). if the return value is * ESP_OK, then the audio buff is consumed, otherwise, audio buff can be reused by user. * diff --git a/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h b/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h index 6fae9c1b29..90570411e2 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,9 +18,9 @@ extern "C" { #define ESP_AVRC_TRANS_LABEL_MAX 15 /*!< max transaction label */ -#define ESP_AVRC_CA_IMAGE_HANDLE_LEN 7 /* The image handle length is fixed to 7, specified by Basic Image Profile */ -#define ESP_AVRC_CA_MTU_MIN 255 /* Minimal MTU can be used in Cover Art OBEX connection */ -#define ESP_AVRC_CA_MTU_MAX 1691 /* Maximum MTU can be used in Cover Art OBEX connection */ +#define ESP_AVRC_CA_IMAGE_HANDLE_LEN 7 /*!< The image handle length is fixed to 7, specified by Basic Image Profile */ +#define ESP_AVRC_CA_MTU_MIN 255 /*!< Minimal MTU can be used in Cover Art OBEX connection */ +#define ESP_AVRC_CA_MTU_MAX 1691 /*!< Maximum MTU can be used in Cover Art OBEX connection */ /// AVRC feature bit mask typedef enum { @@ -113,7 +113,7 @@ typedef enum { typedef enum { ESP_AVRC_PSTH_FILTER_ALLOWED_CMD = 0, /*!< all of the PASSTHROUGH commands that can possibly be used, immutable */ ESP_AVRC_PSTH_FILTER_SUPPORTED_CMD = 1, /*!< PASSTHROUGH commands selectively supported according to the current configuration */ - ESP_AVRC_PSTH_FILTER_SUPPORT_MAX, + ESP_AVRC_PSTH_FILTER_SUPPORT_MAX, /*!< Maximum value for PASSTHROUGH command filter */ } esp_avrc_psth_filter_t; /// AVRC passthrough command bit mask @@ -121,6 +121,7 @@ typedef struct { uint16_t bits[8]; /*!< bit mask representation of PASSTHROUGH commands */ } esp_avrc_psth_bit_mask_t; +/// AVRC operation code bit mask typedef enum { ESP_AVRC_BIT_MASK_OP_TEST = 0, /*!< operation code to test a specific bit */ ESP_AVRC_BIT_MASK_OP_SET = 1, /*!< operation code to set a specific bit */ @@ -186,14 +187,14 @@ typedef enum { ESP_AVRC_RN_ADDRESSED_PLAYER_CHANGE = 0x0b, /*!< the addressed player changed */ ESP_AVRC_RN_UIDS_CHANGE = 0x0c, /*!< UIDs changed */ ESP_AVRC_RN_VOLUME_CHANGE = 0x0d, /*!< volume changed locally on TG */ - ESP_AVRC_RN_MAX_EVT + ESP_AVRC_RN_MAX_EVT /*!< maximum value for notification event */ } esp_avrc_rn_event_ids_t; /// AVRC target notification event notification capability typedef enum { ESP_AVRC_RN_CAP_ALLOWED_EVT = 0, /*!< all of the notification events that can possibly be supported, immutable */ ESP_AVRC_RN_CAP_SUPPORTED_EVT = 1, /*!< notification events selectively supported according to the current configuration */ - ESP_AVRC_RN_CAP_MAX, + ESP_AVRC_RN_CAP_MAX, /*!< maximum value for the notification event capability */ } esp_avrc_rn_evt_cap_t; /// AVRC target notification event capability bit mask @@ -213,7 +214,7 @@ typedef enum { ESP_AVRC_PS_REPEAT_MODE = 0x02, /*!< repeat mode */ ESP_AVRC_PS_SHUFFLE_MODE = 0x03, /*!< shuffle mode */ ESP_AVRC_PS_SCAN_MODE = 0x04, /*!< scan mode on or off */ - ESP_AVRC_PS_MAX_ATTR + ESP_AVRC_PS_MAX_ATTR /*!< Maximum value for player setting attribute ids*/ } esp_avrc_ps_attr_ids_t; /// AVRC equalizer modes @@ -232,9 +233,9 @@ typedef enum { /// AVRC shuffle modes typedef enum { - ESP_AVRC_PS_SHUFFLE_OFF = 0x1, /*, Terminate all held or set UDUB("busy") to a waiting call */ - ESP_HF_CHLD_TYPE_REL_ACC, /*!< <1>, Terminate all active calls and accepts a waiting/held call */ - ESP_HF_CHLD_TYPE_HOLD_ACC, /*!< <2>, Hold all active calls and accepts a waiting/held call */ + ESP_HF_CHLD_TYPE_REL_ACC, /*!< <1>, Terminate all active calls and accept a waiting/held call */ + ESP_HF_CHLD_TYPE_HOLD_ACC, /*!< <2>, Hold all active calls and accept a waiting/held call */ ESP_HF_CHLD_TYPE_MERGE, /*!< <3>, Add all held calls to a conference */ - ESP_HF_CHLD_TYPE_MERGE_DETACH, /*!< <4>, connect the two calls and disconnects the subscriber from both calls */ - ESP_HF_CHLD_TYPE_REL_X, /*!< <1x>, releases specified calls only */ + ESP_HF_CHLD_TYPE_MERGE_DETACH, /*!< <4>, connect the two calls and disconnect the subscriber from both calls */ + ESP_HF_CHLD_TYPE_REL_X, /*!< <1x>, release specified calls only */ ESP_HF_CHLD_TYPE_PRIV_X, /*!< <2x>, request private consultation mode with specified call */ } esp_hf_chld_type_t; @@ -220,8 +221,8 @@ typedef enum { /* AT response code - OK/Error */ typedef enum { - ESP_HF_AT_RESPONSE_ERROR = 0, - ESP_HF_AT_RESPONSE_OK + ESP_HF_AT_RESPONSE_ERROR = 0, /*!< error in the AT command response */ + ESP_HF_AT_RESPONSE_OK /*!< successful AT command response */ } esp_hf_at_response_t; /// Extended Audio Gateway Error Result Code Response @@ -242,7 +243,7 @@ typedef enum { ESP_HF_CME_MEMORY_FULL = 20, /*!< memory full */ ESP_HF_CME_INVALID_INDEX = 21, /*!< invalid index */ ESP_HF_CME_MEMORY_FAILURE = 23, /*!< memory failure */ - ESP_HF_CME_TEXT_STRING_TOO_LONG = 24, /*!< test string too long */ + ESP_HF_CME_TEXT_STRING_TOO_LONG = 24, /*!< text string too long */ ESP_HF_CME_INVALID_CHARACTERS_IN_TEXT_STRING = 25, /*!< invalid characters in text string */ ESP_HF_CME_DIAL_STRING_TOO_LONG = 26, /*!< dial string too long*/ ESP_HF_CME_INVALID_CHARACTERS_IN_DIAL_STRING = 27, /*!< invalid characters in dial string */ diff --git a/components/bt/host/bluedroid/api/include/api/esp_hidd_api.h b/components/bt/host/bluedroid/api/include/api/esp_hidd_api.h index f16bbcb0fa..2348e752d5 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hidd_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hidd_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 * @@ -16,7 +16,7 @@ extern "C" { #endif -/// subclass of hid device +/* subclass of hid device */ #define ESP_HID_CLASS_UNKNOWN (0x00<<2) /*!< unknown HID device subclass */ #define ESP_HID_CLASS_JOS (0x01<<2) /*!< joystick */ #define ESP_HID_CLASS_GPD (0x02<<2) /*!< game pad */ @@ -57,9 +57,9 @@ typedef enum { */ typedef enum { ESP_HIDD_CONN_STATE_CONNECTED, /*!< HID connection established */ - ESP_HIDD_CONN_STATE_CONNECTING, /*!< connection to remote Bluetooth device */ + ESP_HIDD_CONN_STATE_CONNECTING, /*!< connecting to remote Bluetooth device */ ESP_HIDD_CONN_STATE_DISCONNECTED, /*!< connection released */ - ESP_HIDD_CONN_STATE_DISCONNECTING, /*!< disconnecting to remote Bluetooth device*/ + ESP_HIDD_CONN_STATE_DISCONNECTING, /*!< disconnecting from remote Bluetooth device*/ ESP_HIDD_CONN_STATE_UNKNOWN, /*!< unknown connection state */ } esp_hidd_connection_state_t; @@ -116,32 +116,35 @@ typedef struct { * @brief HID device callback function events */ typedef enum { - ESP_HIDD_INIT_EVT = 0, /*!< When HID device is initialized, the event comes */ - ESP_HIDD_DEINIT_EVT, /*!< When HID device is deinitialized, the event comes */ - ESP_HIDD_REGISTER_APP_EVT, /*!< When HID device application registered, the event comes */ - ESP_HIDD_UNREGISTER_APP_EVT, /*!< When HID device application unregistered, the event comes */ - ESP_HIDD_OPEN_EVT, /*!< When HID device connection to host opened, the event comes */ - ESP_HIDD_CLOSE_EVT, /*!< When HID device connection to host closed, the event comes */ - ESP_HIDD_SEND_REPORT_EVT, /*!< When HID device send report to lower layer, the event comes */ - ESP_HIDD_REPORT_ERR_EVT, /*!< When HID device report handshanke error to lower layer, the event comes */ - ESP_HIDD_GET_REPORT_EVT, /*!< When HID device receives GET_REPORT request from host, the event comes */ - ESP_HIDD_SET_REPORT_EVT, /*!< When HID device receives SET_REPORT request from host, the event comes */ - ESP_HIDD_SET_PROTOCOL_EVT, /*!< When HID device receives SET_PROTOCOL request from host, the event comes */ - ESP_HIDD_INTR_DATA_EVT, /*!< When HID device receives DATA from host on intr, the event comes */ - ESP_HIDD_VC_UNPLUG_EVT, /*!< When HID device initiates Virtual Cable Unplug, the event comes */ - ESP_HIDD_API_ERR_EVT /*!< When HID device has API error, the event comes */ + ESP_HIDD_INIT_EVT = 0, /*!< HID device initialized. */ + ESP_HIDD_DEINIT_EVT, /*!< HID device deinitialized. */ + ESP_HIDD_REGISTER_APP_EVT, /*!< HID device application registered. */ + ESP_HIDD_UNREGISTER_APP_EVT, /*!< HID device application unregistered. */ + ESP_HIDD_OPEN_EVT, /*!< HID device connection to host opened. */ + ESP_HIDD_CLOSE_EVT, /*!< HID device connection to host closed. */ + ESP_HIDD_SEND_REPORT_EVT, /*!< HID device sent report to lower layer. */ + ESP_HIDD_REPORT_ERR_EVT, /*!< HID device reported handshake error to lower layer. */ + ESP_HIDD_GET_REPORT_EVT, /*!< HID device received GET_REPORT request from host. */ + ESP_HIDD_SET_REPORT_EVT, /*!< HID device received SET_REPORT request from host. */ + ESP_HIDD_SET_PROTOCOL_EVT, /*!< HID device received SET_PROTOCOL request from host. */ + ESP_HIDD_INTR_DATA_EVT, /*!< HID device received DATA from host on interrupt channel. */ + ESP_HIDD_VC_UNPLUG_EVT, /*!< HID device initiated Virtual Cable Unplug. */ + ESP_HIDD_API_ERR_EVT /*!< HID device had API error. */ } esp_hidd_cb_event_t; +/** + * @brief HID device status + */ typedef enum { - ESP_HIDD_SUCCESS, - ESP_HIDD_ERROR, /*!< general ESP HD error */ + ESP_HIDD_SUCCESS, /*!< successful */ + ESP_HIDD_ERROR, /*!< general ESP HID error */ ESP_HIDD_NO_RES, /*!< out of system resources */ ESP_HIDD_BUSY, /*!< Temporarily can not handle this request. */ ESP_HIDD_NO_DATA, /*!< No data. */ - ESP_HIDD_NEED_INIT, /*!< HIDD module shall init first */ - ESP_HIDD_NEED_DEINIT, /*!< HIDD module shall deinit first */ - ESP_HIDD_NEED_REG, /*!< HIDD module shall register first */ - ESP_HIDD_NEED_DEREG, /*!< HIDD module shall deregister first */ + ESP_HIDD_NEED_INIT, /*!< HIDD module must be initialized first. */ + ESP_HIDD_NEED_DEINIT, /*!< HIDD module must be deinitialized first. */ + ESP_HIDD_NEED_REG, /*!< HIDD module must be registered first. */ + ESP_HIDD_NEED_DEREG, /*!< HIDD module must be deregistered first. */ ESP_HIDD_NO_CONNECTION, /*!< connection may have been closed */ } esp_hidd_status_t; @@ -270,8 +273,8 @@ typedef union { /** * @brief HID device callback function type. - * @param event: Event type - * @param param: Point to callback parameter, currently is union type + * @param[in] event: Event type + * @param[in] param: Point to callback parameter, currently is union type */ typedef void (*esp_hd_cb_t)(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param); diff --git a/components/bt/host/bluedroid/api/include/api/esp_hidh_api.h b/components/bt/host/bluedroid/api/include/api/esp_hidh_api.h index 51a0d43f7b..e23416c211 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hidh_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hidh_api.h @@ -52,7 +52,7 @@ typedef enum { ESP_HIDH_BUSY, /*!< vendor-defined: temporarily can not handle this request */ ESP_HIDH_NO_DATA, /*!< vendor-defined: no data. */ ESP_HIDH_NEED_INIT, /*!< vendor-defined: HIDH module shall initialize first */ - ESP_HIDH_NEED_DEINIT, /*!< vendor-defined: HIDH module shall de-deinitialize first */ + ESP_HIDH_NEED_DEINIT, /*!< vendor-defined: HIDH module shall deinitialize first */ ESP_HIDH_NO_CONNECTION, /*!< vendor-defined: connection may have been closed */ } esp_hidh_status_t; @@ -309,8 +309,8 @@ typedef union { /** * @brief HID host callback function type - * @param event: Event type - * @param param: Point to callback parameter, currently is union type + * @param[in] event: Event type + * @param[in] param: Point to callback parameter, currently is union type */ typedef void (*esp_hh_cb_t)(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param); diff --git a/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h b/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h index 982cbdaa85..faa13ccdc5 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,17 +28,18 @@ typedef enum { ESP_BT_L2CAP_NO_SERVER, /*!< No server */ } esp_bt_l2cap_status_t; -/** - * @brief Security Setting Mask. Use these three mask mode: - * 1. ESP_BT_L2CAP_SEC_NONE - * 2. ESP_BT_L2CAP_SEC_AUTHENTICATE - * 3. (ESP_BT_L2CAP_SEC_ENCRYPT|ESP_BT_L2CAP_SEC_AUTHENTICATE) +/* + * Security setting mask for L2CAP. + * - Use one of the following mask modes: + * 1. `ESP_BT_L2CAP_SEC_NONE` + * 2. `ESP_BT_L2CAP_SEC_AUTHENTICATE` + * 3. (`ESP_BT_L2CAP_SEC_ENCRYPT` | `ESP_BT_L2CAP_SEC_AUTHENTICATE`) */ #define ESP_BT_L2CAP_SEC_NONE 0x0000 /*!< No security */ #define ESP_BT_L2CAP_SEC_AUTHORIZE 0x0001 /*!< Authorization required */ #define ESP_BT_L2CAP_SEC_AUTHENTICATE 0x0012 /*!< Authentication required */ #define ESP_BT_L2CAP_SEC_ENCRYPT 0x0024 /*!< Encryption required */ -typedef uint32_t esp_bt_l2cap_cntl_flags_t; +typedef uint32_t esp_bt_l2cap_cntl_flags_t; /*!< L2CAP control flags type */ /** * @brief L2CAP status parameters @@ -146,8 +147,8 @@ typedef union { /** * @brief L2CAP callback function type. * - * @param event: Event type - * @param param: Point to callback parameter, currently is union type + * @param[in] event: Event type + * @param[in] param: Point to callback parameter, currently is union type */ typedef void (* esp_bt_l2cap_cb_t)(esp_bt_l2cap_cb_event_t event, esp_bt_l2cap_cb_param_t *param); @@ -203,11 +204,12 @@ esp_err_t esp_bt_l2cap_deinit(void); esp_err_t esp_bt_l2cap_connect(esp_bt_l2cap_cntl_flags_t cntl_flag, uint16_t remote_psm, esp_bd_addr_t peer_bd_addr); /** - * @brief This function create a L2CAP server and starts listening for an - * L2CAP connection request from a remote Bluetooth device. - * When the server is started successfully, the callback is called with ESP_BT_L2CAP_START_EVT. - * When the connection is established, the callback is called with ESP_BT_L2CAP_OPEN_EVT. - * This function must be called after esp_bt_l2cap_init() successful and before esp_bt_l2cap_deinit(). +* @brief Create an L2CAP server and start listening for connection requests. + * + * @note + * - When the server is started successfully, the callback is called with `ESP_BT_L2CAP_START_EVT`. + * - When the connection is established, the callback is called with `ESP_BT_L2CAP_OPEN_EVT`. + * - This function must be called after `esp_bt_l2cap_init()` and before `esp_bt_l2cap_deinit()`. * * @param[in] cntl_flag: Lower 16-bit security settings mask. * @param[in] local_psm: Dynamic PSM. diff --git a/components/bt/host/bluedroid/api/include/api/esp_sdp_api.h b/components/bt/host/bluedroid/api/include/api/esp_sdp_api.h index 5c74851f31..4045f914e9 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_sdp_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_sdp_api.h @@ -25,9 +25,13 @@ extern "C" { #define ESP_SDP_UUID_SAP 0x112D /*!< SIM Access Profile UUID */ #define ESP_SDP_UUID_DIP 0x1200 /*!< Device Identification Profile UUID */ +/// Build a Bluetooth UUID16 #define ESP_SDP_BUILD_BT_UUID16(uuid16_val) \ (esp_bt_uuid_t) { .len = ESP_UUID_LEN_16, .uuid = {.uuid16 = (uint16_t)(uuid16_val),}, } +/** + * @brief SDP status parameters + */ typedef enum { ESP_SDP_SUCCESS = 0, /*!< Successful operation. */ ESP_SDP_FAILURE, /*!< Generic failure. */ @@ -233,8 +237,8 @@ typedef union { /** * @brief SDP callback function type. * - * @param event: Event type - * @param param: Point to callback parameter, currently is union type + * @param[in] event: Event type + * @param[in] param: Point to callback parameter, currently is union type */ typedef void (* esp_sdp_cb_t)(esp_sdp_cb_event_t event, esp_sdp_cb_param_t *param); @@ -275,7 +279,7 @@ esp_err_t esp_sdp_init(void); esp_err_t esp_sdp_deinit(void); /** - * @brief This function is called to performs service discovery for the services provided by the given peer device. + * @brief Perform service discovery for the services provided by the given peer device. * When the operation is completed, the callback function will be called with ESP_SDP_SEARCH_COMP_EVT. * This function must be called after esp_sdp_init() successful and before esp_sdp_deinit(). * @@ -302,7 +306,7 @@ esp_err_t esp_sdp_search_record(esp_bd_addr_t bd_addr, esp_bt_uuid_t uuid); esp_err_t esp_sdp_create_record(esp_bluetooth_sdp_record_t *record); /** - * @brief This function is called to remove a SDP record. + * @brief Remove an SDP record. * When the operation is completed, the callback function will be called with ESP_SDP_REMOVE_RECORD_COMP_EVT. * This function must be called after esp_sdp_init() successful and before esp_sdp_deinit(). * diff --git a/components/bt/host/bluedroid/api/include/api/esp_spp_api.h b/components/bt/host/bluedroid/api/include/api/esp_spp_api.h index e6cdf2fc69..f8a9c52403 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_spp_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_spp_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -42,15 +42,18 @@ Due to certain limitations, do not use these mask modes: 2. ESP_SPP_SEC_MODE4_LEVEL4 3. ESP_SPP_SEC_MITM */ -#define ESP_SPP_SEC_NONE 0x0000 /*!< No security. relate to BTA_SEC_NONE in bta/bta_api.h */ -#define ESP_SPP_SEC_AUTHORIZE 0x0001 /*!< Authorization required (only needed for out going connection ) relate to BTA_SEC_AUTHORIZE in bta/bta_api.h*/ -#define ESP_SPP_SEC_AUTHENTICATE 0x0012 /*!< Authentication required. relate to BTA_SEC_AUTHENTICATE in bta/bta_api.h*/ -#define ESP_SPP_SEC_ENCRYPT 0x0024 /*!< Encryption required. relate to BTA_SEC_ENCRYPT in bta/bta_api.h*/ -#define ESP_SPP_SEC_MODE4_LEVEL4 0x0040 /*!< Mode 4 level 4 service, i.e. incoming/outgoing MITM and P-256 encryption relate to BTA_SEC_MODE4_LEVEL4 in bta/bta_api.h*/ -#define ESP_SPP_SEC_MITM 0x3000 /*!< Man-In-The_Middle protection relate to BTA_SEC_MITM in bta/bta_api.h*/ -#define ESP_SPP_SEC_IN_16_DIGITS 0x4000 /*!< Min 16 digit for pin code relate to BTA_SEC_IN_16_DIGITS in bta/bta_api.h*/ -typedef uint16_t esp_spp_sec_t; +#define ESP_SPP_SEC_NONE 0x0000 /*!< No security. */ +#define ESP_SPP_SEC_AUTHORIZE 0x0001 /*!< Authorization required (only needed for out going connection ) */ +#define ESP_SPP_SEC_AUTHENTICATE 0x0012 /*!< Authentication required. */ +#define ESP_SPP_SEC_ENCRYPT 0x0024 /*!< Encryption required. */ +#define ESP_SPP_SEC_MODE4_LEVEL4 0x0040 /*!< Mode 4 level 4 service, i.e. incoming/outgoing MITM and P-256 encryption. */ +#define ESP_SPP_SEC_MITM 0x3000 /*!< Man-In-The-Middle protection. */ +#define ESP_SPP_SEC_IN_16_DIGITS 0x4000 /*!< Min 16 digit for pin code. */ +typedef uint16_t esp_spp_sec_t; /*!< SPP security type */ +/** + * @brief SPP status type. + */ typedef enum { ESP_SPP_SUCCESS = 0, /*!< Successful operation. */ ESP_SPP_FAILURE, /*!< Generic failure. */ @@ -63,11 +66,17 @@ typedef enum { ESP_SPP_NO_SERVER, /*!< No SPP server */ } esp_spp_status_t; +/** + * @brief SPP role type. + */ typedef enum { ESP_SPP_ROLE_MASTER = 0, /*!< Role: master */ ESP_SPP_ROLE_SLAVE = 1, /*!< Role: slave */ } esp_spp_role_t; +/** + * @brief SPP mode type. + */ typedef enum { ESP_SPP_MODE_CB = 0, /*!< When data is coming, a callback will come with data */ ESP_SPP_MODE_VFS = 1, /*!< Use VFS to write/read data */ @@ -318,7 +327,7 @@ esp_err_t esp_spp_deinit(void); /** - * @brief This function is called to performs service discovery for the services provided by the given peer device. + * @brief Perform service discovery for the services provided by the given peer device. * When the operation is completed, the callback function will be called with ESP_SPP_DISCOVERY_COMP_EVT. * This function must be called after esp_spp_init()/esp_spp_enhanced_init() successful and before esp_spp_deinit(). * diff --git a/components/bt/host/bluedroid/bta/av/bta_av_main.c b/components/bt/host/bluedroid/bta/av/bta_av_main.c index 7ccd3423a4..cf634f2525 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_main.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_main.c @@ -763,7 +763,7 @@ static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data) sep_reg.seid = p_data->api_reg_sep.seid; sep_reg.reg_state = BTA_AV_FAIL; - if (index > BTA_AV_MAX_SEPS || p_data->hdr.layer_specific != BTA_AV_CHNL_AUDIO) { + if (index >= BTA_AV_MAX_SEPS || p_data->hdr.layer_specific != BTA_AV_CHNL_AUDIO) { (*bta_av_cb.p_cback)(BTA_AV_SEP_REG_EVT, (tBTA_AV *)&sep_reg); APPL_TRACE_WARNING("%s invalid parameter: seid %d, ch %d", __FUNCTION__, index, p_data->hdr.layer_specific); return; @@ -815,6 +815,7 @@ static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data) p_scb->seps[index].codec_type = codec_type; p_scb->seps[index].tsep = cs.tsep; p_scb->seps[index].p_app_data_cback = p_data->api_reg_sep.p_data_cback; + sep_reg.reg_state = BTA_AV_SUCCESS; } else { APPL_TRACE_WARNING("%s fail to create sep", __FUNCTION__); break; @@ -826,7 +827,6 @@ static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data) } } - sep_reg.reg_state = BTA_AV_SUCCESS; (*bta_av_cb.p_cback)(BTA_AV_SEP_REG_EVT, (tBTA_AV *)&sep_reg); #endif } diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index fd7d665acc..4f6f496a52 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -49,9 +49,10 @@ #if (BT_CONTROLLER_INCLUDED == TRUE) #include "esp_bt.h" #endif - +#if (CLASSIC_BT_INCLUDED == TRUE) static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir); static void bta_dm_inq_cmpl_cb (void *p_result); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc, BD_NAME bd_name); static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name); #if (SDP_INCLUDED == TRUE) @@ -70,14 +71,16 @@ static UINT8 bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_ static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, int result); #endif ///SMP_INCLUDED == TRUE static void bta_dm_local_name_cback(const BD_ADDR bd_addr); +#if (CLASSIC_BT_INCLUDED == TRUE) static BOOLEAN bta_dm_check_av(UINT16 event); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data); static void bta_dm_acl_link_stat_cback(tBTM_ACL_LINK_STAT_EVENT_DATA *p_data); -static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr); #if (CLASSIC_BT_INCLUDED == TRUE) +static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr); static void bta_dm_encryption_change_cback(BD_ADDR bd_addr, UINT8 enc_mode); static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data); /* Extended Inquiry Response */ @@ -90,8 +93,12 @@ static void bta_dm_eir_search_services( tBTM_INQ_RESULTS *p_result, #endif ///SDP_INCLUDED == TRUE static void bta_dm_search_timer_cback (TIMER_LIST_ENT *p_tle); static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle); +#if (CLASSIC_BT_INCLUDED == TRUE) static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) static void bta_dm_adjust_roles(BOOLEAN delay_role_switch); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (SDP_INCLUDED == TRUE || SMP_INCLUDED == TRUE) static char *bta_dm_get_remname(void); #endif ///SDP_INCLUDED == TRUE || SMP_INCLUDED == TRUE @@ -120,10 +127,6 @@ static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data); extern tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void); #endif -#if BLE_VND_INCLUDED == TRUE -static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result); -#endif - #ifndef BTA_DM_BLE_ADV_CHNL_MAP #define BTA_DM_BLE_ADV_CHNL_MAP (BTM_BLE_ADV_CHNL_37|BTM_BLE_ADV_CHNL_38|BTM_BLE_ADV_CHNL_39) #endif @@ -132,12 +135,17 @@ static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result); static BOOLEAN bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr); #endif ///SMP_INCLUDED == TRUE #if (BLE_INCLUDED == TRUE) -static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir); -static void bta_dm_observe_cmpl_cb(void *p_result); -static void bta_dm_observe_discard_cb (uint32_t num_dis); +#if (BLE_42_SCAN_EN == TRUE) +static void bta_dm_scan_results_cb(tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir); +static void bta_dm_scan_cmpl_cb(void *p_result); +static void bta_dm_scan_discard_cb (uint32_t num_dis); +#endif // (BLE_42_SCAN_EN == TRUE) #endif ///BLE_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8 *p_uuid128); static void bta_dm_disable_timer_cback(TIMER_LIST_ENT *p_tle); @@ -480,8 +488,12 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status ) #endif /* hw is ready, go on with BTA DM initialization */ memset(&bta_dm_search_cb, 0x00, sizeof(bta_dm_search_cb)); +#if (CLASSIC_BT_INCLUDED == TRUE) memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs)); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB)); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) memcpy(dev_class, p_bta_dm_cfg->dev_class, sizeof(dev_class)); #if CLASSIC_BT_INCLUDED BTM_SetDeviceClass (dev_class); @@ -517,30 +529,34 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status ) BTM_RegBusyLevelNotif (bta_dm_bl_change_cback, NULL, BTM_BL_UPDATE_MASK | BTM_BL_ROLE_CHG_MASK); BTM_RegAclLinkStatNotif (bta_dm_acl_link_stat_cback); -#if BLE_VND_INCLUDED == TRUE - BTM_BleReadControllerFeatures (bta_dm_ctrl_features_rd_cmpl_cback); -#endif - /* Earlier, we used to invoke BTM_ReadLocalAddr which was just copying the bd_addr from the control block and invoking the callback which was sending the DM_ENABLE_EVT. But then we have a few HCI commands being invoked above which were still in progress when the ENABLE_EVT was sent. So modified this to fetch the local name which forces the DM_ENABLE_EVT to be sent only after all the init steps are complete */ +#if (CLASSIC_BT_INCLUDED == TRUE) BTM_ReadLocalDeviceNameFromController((tBTM_CMPL_CB *)bta_dm_local_name_cback); bta_sys_rm_register((tBTA_SYS_CONN_CBACK *)bta_dm_rm_cback); - +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if (BTA_DM_PM_INCLUDED == TRUE) /* initialize bluetooth low power manager */ bta_dm_init_pm(); #endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ - +#if (CLASSIC_BT_INCLUDED == TRUE) bta_sys_policy_register((tBTA_SYS_CONN_CBACK *)bta_dm_policy_cback); +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) bta_dm_gattc_register(); #endif +#if (CLASSIC_BT_INCLUDED == TRUE) + // do nothing +#else + bta_dm_local_name_cback(NULL); +#endif + } else { APPL_TRACE_DEBUG(" --- ignored event"); } @@ -589,7 +605,9 @@ void bta_dm_disable (tBTA_DM_MSG *p_data) #endif #if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE +#if (GATT_BG_CONN_DEV == TRUE) BTM_BleClearBgConnDev(); +#endif // (GATT_BG_CONN_DEV == TRUE) #endif if (BTM_GetNumAclLinks() == 0) { @@ -615,13 +633,6 @@ void bta_dm_disable (tBTA_DM_MSG *p_data) btm_ble_resolving_list_cleanup (); //by TH, because cmn_ble_vsc_cb.max_filter has something mistake as btm_ble_adv_filter_cleanup #endif -#if BLE_INCLUDED == TRUE -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - // btm_ble_multi_adv_init is called when the host is enabled, so btm_ble_multi_adv_cleanup is called when the host is disabled. - btm_ble_multi_adv_cleanup(); -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -#endif - } /******************************************************************************* @@ -664,8 +675,9 @@ static void bta_dm_disable_timer_cback (TIMER_LIST_ENT *p_tle) } } else { bta_dm_cb.disabling = FALSE; - +#if (CLASSIC_BT_INCLUDED == TRUE) bta_sys_remove_uuid(UUID_SERVCLASS_PNP_INFORMATION); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL); } } @@ -995,18 +1007,6 @@ void bta_dm_clear_white_list(tBTA_DM_MSG *p_data) BTM_BleClearWhitelist(p_data->white_list.update_wl_cb); #endif } -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -void bta_dm_ble_read_adv_tx_power(tBTA_DM_MSG *p_data) -{ -#if (BLE_INCLUDED == TRUE) - if (p_data->read_tx_power.read_tx_power_cb != NULL) { - BTM_BleReadAdvTxPower(p_data->read_tx_power.read_tx_power_cb); - } else { - APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); - } -#endif ///BLE_INCLUDED == TRUE -} -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) void bta_dm_read_rssi(tBTA_DM_MSG *p_data) { @@ -1239,85 +1239,6 @@ void bta_dm_add_device (tBTA_DM_MSG *p_data) } } -#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_close_acl -** -** Description This function forces to close the connection to a remote device -** and optionally remove the device from security database if -** required. -**** -*******************************************************************************/ -void bta_dm_close_acl(tBTA_DM_MSG *p_data) -{ - tBTA_DM_API_REMOVE_ACL *p_remove_acl = &p_data->remove_acl; - UINT8 index; - - APPL_TRACE_DEBUG("bta_dm_close_acl"); - - if (BTM_IsAclConnectionUp(p_remove_acl->bd_addr, p_remove_acl->transport)) { - for (index = 0; index < bta_dm_cb.device_list.count; index ++) { - if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, p_remove_acl->bd_addr)) { - break; - } - } - if (index != bta_dm_cb.device_list.count) { - if (p_remove_acl->remove_dev) { - bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE; - } - } else { - APPL_TRACE_ERROR("unknown device, remove ACL failed"); - } - /* Disconnect the ACL link */ - btm_remove_acl(p_remove_acl->bd_addr, p_remove_acl->transport); - } - /* if to remove the device from security database ? do it now */ - else if (p_remove_acl->remove_dev) { - if (!BTM_SecDeleteDevice(p_remove_acl->bd_addr, p_remove_acl->transport)) { - APPL_TRACE_ERROR("delete device from security database failed."); - } -#if (BLE_INCLUDED == TRUE && GATTC_INCLUDED == TRUE) - /* need to remove all pending background connection if any */ - BTA_GATTC_CancelOpen(0, p_remove_acl->bd_addr, FALSE); -#endif - } - /* otherwise, no action needed */ - -} -#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) - -#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_remove_all_acl -** -** Description This function forces to close all the ACL links specified by link type -**** -*******************************************************************************/ -void bta_dm_remove_all_acl(tBTA_DM_MSG *p_data) -{ - const tBTA_DM_LINK_TYPE link_type = p_data->remove_all_acl.link_type; - tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; - - APPL_TRACE_DEBUG("%s link type = %d", __func__, link_type); - - for (UINT8 i = 0; i < bta_dm_cb.device_list.count; i++) { - BD_ADDR addr = {0}; - bdcpy(addr, bta_dm_cb.device_list.peer_device[i].peer_bdaddr); -#if defined (BLE_INCLUDED) && (BLE_INCLUDED == TRUE) - transport = bta_dm_cb.device_list.peer_device[i].transport; -#endif - if ((link_type == BTA_DM_LINK_TYPE_ALL) || - ((link_type == BTA_DM_LINK_TYPE_LE) && (transport == BT_TRANSPORT_LE)) || - ((link_type == BTA_DM_LINK_TYPE_BR_EDR) && (transport == BT_TRANSPORT_BR_EDR))) { - /* Disconnect the ACL link */ - btm_remove_acl(addr, transport); - } - } -} -#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) - /******************************************************************************* ** ** Function bta_dm_bond @@ -1445,6 +1366,7 @@ void bta_dm_pin_reply (tBTA_DM_MSG *p_data) } #endif ///SMP_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_policy_cback @@ -1510,7 +1432,7 @@ static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app break; } } - +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_confirm @@ -1673,7 +1595,9 @@ void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data) *******************************************************************************/ void bta_dm_search_start (tBTA_DM_MSG *p_data) { +#if (CLASSIC_BT_INCLUDED == TRUE) tBTM_INQUIRY_CMPL result; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->search.num_uuid); @@ -1682,12 +1606,13 @@ void bta_dm_search_start (tBTA_DM_MSG *p_data) APPL_TRACE_DEBUG("%s avoid_scatter=%d", __func__, p_bta_dm_cfg->avoid_scatter); +#if (CLASSIC_BT_INCLUDED == TRUE) if (p_bta_dm_cfg->avoid_scatter && (p_data->search.rs_res == BTA_DM_RS_NONE) && bta_dm_check_av(BTA_DM_API_SEARCH_EVT)) { memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH)); return; } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) BTM_ClearInqDb(NULL); /* save search params */ bta_dm_search_cb.p_search_cback = p_data->search.p_cback; @@ -1710,6 +1635,7 @@ void bta_dm_search_start (tBTA_DM_MSG *p_data) memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len); } #endif +#if (CLASSIC_BT_INCLUDED == TRUE) result.status = BTM_StartInquiry( (tBTM_INQ_PARMS *)&p_data->search.inq_params, bta_dm_inq_results_cb, (tBTM_CMPL_CB *) bta_dm_inq_cmpl_cb); @@ -1719,6 +1645,7 @@ void bta_dm_search_start (tBTA_DM_MSG *p_data) result.num_resp = 0; bta_dm_inq_cmpl_cb ((void *)&result); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } /******************************************************************************* @@ -2869,6 +2796,7 @@ static void bta_dm_sdp_callback (UINT16 sdp_status) } } #endif ///SDP_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_inq_results_cb @@ -2957,6 +2885,7 @@ static void bta_dm_inq_cmpl_cb (void *p_result) } } } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -3527,11 +3456,13 @@ static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data) p_msg->busy_level = p_data->update.busy_level; p_msg->busy_level_flags = p_data->update.busy_level_flags; break; +#if (CLASSIC_BT_INCLUDED == TRUE) case BTM_BL_ROLE_CHG_EVT: p_msg->new_role = p_data->role_chg.new_role; p_msg->hci_status = p_data->role_chg.hci_status; bdcpy(p_msg->bd_addr, p_data->role_chg.p_bda); break; +#endif // (CLASSIC_BT_INCLUDED == TRUE) case BTM_BL_COLLISION_EVT: bdcpy(p_msg->bd_addr, p_data->conn.p_bda); break; @@ -3583,6 +3514,7 @@ static void bta_dm_acl_link_stat_cback(tBTM_ACL_LINK_STAT_EVENT_DATA *p_data) } } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_rs_cback @@ -3651,6 +3583,7 @@ static BOOLEAN bta_dm_check_av(UINT16 event) } return switching; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -3670,10 +3603,11 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data) tBTA_DM_SEC conn; BOOLEAN is_new = p_data->acl_change.is_new; BD_ADDR_PTR p_bda = p_data->acl_change.bd_addr; - BOOLEAN need_policy_change = FALSE; BOOLEAN issue_unpair_cb = FALSE; - +#if (CLASSIC_BT_INCLUDED == TRUE) + BOOLEAN need_policy_change = FALSE; tBTA_DM_PEER_DEVICE *p_dev; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) memset(&conn, 0, sizeof(tBTA_DM_SEC)); switch (p_data->acl_change.event) { @@ -3684,7 +3618,7 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data) bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn); } return; - +#if (CLASSIC_BT_INCLUDED == TRUE) case BTM_BL_ROLE_CHG_EVT: /* role change event */ p_dev = bta_dm_find_peer_device(p_bda); if (p_dev) { @@ -3720,14 +3654,15 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data) } } return; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } - +#if (CLASSIC_BT_INCLUDED == TRUE) /* Collision report from Stack: Notify profiles */ if (p_data->acl_change.event == BTM_BL_COLLISION_EVT) { bta_sys_notify_collision (p_bda); return; } - +#endif // (CLASSIC_BT_INCLUDED == TRUE) if (is_new) { for (i = 0; i < bta_dm_cb.device_list.count; i++) { if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda) @@ -3857,7 +3792,9 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data) } } +#if (CLASSIC_BT_INCLUDED == TRUE) bta_dm_adjust_roles(TRUE); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } /******************************************************************************* @@ -3894,6 +3831,7 @@ static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle) } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_rm_cback @@ -3934,7 +3872,7 @@ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, } } } - +#if (CLASSIC_BT_INCLUDED == TRUE) if ((BTA_ID_AV == id) || (BTA_ID_AVK == id)) { if ( status == BTA_SYS_CONN_BUSY) { if (p_dev) { @@ -3963,6 +3901,7 @@ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, if ((status != BTA_SYS_CONN_BUSY) && (status != BTA_SYS_CONN_IDLE)) { bta_dm_adjust_roles(FALSE); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } /******************************************************************************* @@ -3980,6 +3919,7 @@ static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle) APPL_TRACE_EVENT("bta_dm_delay_role_switch_cback: initiating Delayed RS"); bta_dm_adjust_roles (FALSE); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -4023,7 +3963,7 @@ static BOOLEAN bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr) } #endif ///SMP_INCLUDED == TRUE - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_adjust_roles @@ -4107,6 +4047,7 @@ static void bta_dm_adjust_roles(BOOLEAN delay_role_switch) } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -4639,62 +4580,6 @@ void bta_dm_eir_update_uuid(tBT_UUID uuid, BOOLEAN adding) } #endif -#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_enable_test_mode -** -** Description enable test mode -** -** -** Returns void -** -*******************************************************************************/ -void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data) -{ - UNUSED(p_data); - BTM_EnableTestMode(); -} - -/******************************************************************************* -** -** Function bta_dm_disable_test_mode -** -** Description disable test mode -** -** -** Returns void -** -*******************************************************************************/ -void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data) -{ - UNUSED(p_data); - BTM_DeviceReset(NULL); -} -#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) - -#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_execute_callback -** -** Description Just execute a generic call back in the context of the BTU/BTA tack -** -** -** Returns void -** -*******************************************************************************/ -void bta_dm_execute_callback(tBTA_DM_MSG *p_data) -{ - /* sanity check */ - if (p_data->exec_cback.p_exec_cback == NULL) { - return; - } - - p_data->exec_cback.p_exec_cback(p_data->exec_cback.p_param); -} -#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) - /******************************************************************************* ** ** Function bta_dm_encrypt_cback @@ -4809,9 +4694,10 @@ BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr) #endif /* BTA_HD_INCLUDED == TRUE */ #if (BLE_INCLUDED == TRUE) +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** -** Function bta_dm_observe_results_cb +** Function bta_dm_scan_results_cb ** ** Description Callback for BLE Observe result ** @@ -4819,7 +4705,7 @@ BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr) ** Returns void ** *******************************************************************************/ -static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir) +static void bta_dm_scan_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir) { tBTA_DM_SEARCH result; tBTM_INQ_INFO *p_inq_info; @@ -4859,7 +4745,7 @@ static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir) /******************************************************************************* ** -** Function bta_dm_observe_cmpl_cb +** Function bta_dm_scan_cmpl_cb ** ** Description Callback for BLE Observe complete ** @@ -4867,11 +4753,11 @@ static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir) ** Returns void ** *******************************************************************************/ -static void bta_dm_observe_cmpl_cb (void *p_result) +static void bta_dm_scan_cmpl_cb (void *p_result) { tBTA_DM_SEARCH data; - APPL_TRACE_DEBUG("bta_dm_observe_cmpl_cb"); + APPL_TRACE_DEBUG("bta_dm_scan_cmpl_cb"); data.inq_cmpl.num_resps = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp; if (bta_dm_search_cb.p_scan_cback) { @@ -4881,7 +4767,7 @@ static void bta_dm_observe_cmpl_cb (void *p_result) /******************************************************************************* ** -** Function bta_dm_observe_discard_cb +** Function bta_dm_scan_discard_cb ** ** Description Callback for BLE Observe lost ** @@ -4889,17 +4775,18 @@ static void bta_dm_observe_cmpl_cb (void *p_result) ** Returns void ** *******************************************************************************/ -static void bta_dm_observe_discard_cb (uint32_t num_dis) +static void bta_dm_scan_discard_cb (uint32_t num_dis) { tBTA_DM_SEARCH data; - APPL_TRACE_DEBUG("bta_dm_observe_discard_cb"); + APPL_TRACE_DEBUG("bta_dm_scan_discard_cb"); data.inq_dis.num_dis = num_dis; if (bta_dm_search_cb.p_scan_cback) { bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_DISCARD_NUM_EVT, &data); } } +#endif // (BLE_42_SCAN_EN == TRUE) #if (SMP_INCLUDED == TRUE) /******************************************************************************* @@ -5218,26 +5105,6 @@ void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data) p_data->ble_set_conn_params.slave_latency, p_data->ble_set_conn_params.supervision_tout); } -#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_set_conn_scan_params -** -** Description This function sets BLE scan parameters. -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_set_scan_params(tBTA_DM_MSG *p_data) -{ - BTM_BleSetScanParams(p_data->ble_set_scan_params.client_if, - p_data->ble_set_scan_params.scan_int, - p_data->ble_set_scan_params.scan_window, - p_data->ble_set_scan_params.scan_mode, - p_data->ble_set_scan_params.scan_param_setup_cback); -} -#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) - #if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** @@ -5272,23 +5139,6 @@ void bta_dm_ble_set_scan_fil_params(tBTA_DM_MSG *p_data) } #endif // #if (BLE_42_SCAN_EN == TRUE) -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_set_conn_scan_params -** -** Description This function set the preferred connection scan parameters. -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data) -{ - BTM_BleSetConnScanParams(p_data->ble_set_conn_scan_params.scan_int, - p_data->ble_set_conn_scan_params.scan_window); -} -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) - /******************************************************************************* ** ** Function bta_dm_ble_update_conn_params @@ -5355,28 +5205,6 @@ void bta_dm_ble_clear_rand_address(tBTA_DM_MSG *p_data) BTM_BleClearRandAddress(); } -#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_stop_advertising -** -** Description This function stop the BLE avdertising for the device. -** -** Parameters: void -** Explanation: This function added by Yulong at 2016/10/19 -*******************************************************************************/ -void bta_dm_ble_stop_advertising(tBTA_DM_MSG *p_data) -{ - if (p_data->hdr.event != BTA_DM_API_BLE_STOP_ADV_EVT) { - APPL_TRACE_ERROR("Invalid BTA event,can't stop the BLE adverting\n"); - } -#if (BLE_42_ADV_EN == TRUE) - btm_ble_stop_adv(); -#endif // #if (BLE_42_ADV_EN == TRUE) -} -#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) - - #if BLE_PRIVACY_SPT == TRUE /******************************************************************************* ** @@ -5406,48 +5234,23 @@ void bta_dm_ble_config_local_icon (tBTA_DM_MSG *p_data) BTM_BleConfigLocalIcon (p_data->ble_local_icon.icon); } -#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) /******************************************************************************* ** -** Function bta_dm_ble_observe +** Function bta_dm_ble_set_key_material ** -** Description This function set the preferred connection scan parameters. +** Description This function sets the Encrypted Data Key Material. ** -** Parameters: ** *******************************************************************************/ -void bta_dm_ble_observe (tBTA_DM_MSG *p_data) +void bta_dm_ble_set_key_material (tBTA_DM_MSG *p_data) { - tBTM_STATUS status; - if (p_data->ble_observe.start) { - /*Save the callback to be called when a scan results are available */ - bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback; - - if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration, - bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb)) != BTM_CMD_STARTED) { - APPL_TRACE_WARNING(" %s start observe failed. status=0x%x\n", __FUNCTION__, status); - } - - if (p_data->ble_observe.p_start_scan_cback) { - status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE); - p_data->ble_observe.p_start_scan_cback(status); - } - } else { - bta_dm_search_cb.p_scan_cback = NULL; - status = BTM_BleObserve(FALSE, 0, NULL, NULL); - - if (status != BTM_CMD_STARTED){ - APPL_TRACE_WARNING(" %s stop observe failed, status=0x%x\n", __FUNCTION__, status); - } - - if (p_data->ble_observe.p_stop_scan_cback) { - status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE); - p_data->ble_observe.p_stop_scan_cback(status); - } - } + BTM_BleSetKeyMaterial (p_data->ble_key_material.session_key, + p_data->ble_key_material.iv); } -#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) +#endif +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_scan @@ -5465,7 +5268,7 @@ void bta_dm_ble_scan (tBTA_DM_MSG *p_data) bta_dm_search_cb.p_scan_cback = p_data->ble_scan.p_cback; if ((status = BTM_BleScan(TRUE, p_data->ble_scan.duration, - bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb, bta_dm_observe_discard_cb)) != BTM_CMD_STARTED) { + bta_dm_scan_results_cb, bta_dm_scan_cmpl_cb, bta_dm_scan_discard_cb)) != BTM_CMD_STARTED) { APPL_TRACE_WARNING(" %s start scan failed. status=0x%x\n", __FUNCTION__, status); } @@ -5485,12 +5288,14 @@ void bta_dm_ble_scan (tBTA_DM_MSG *p_data) status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE); p_data->ble_scan.p_stop_scan_cback(status); } - +#if (BLE_TOPOLOGY_CHECK == TRUE) // reset BLE scan link state when stop scan btm_ble_clear_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); btm_ble_clear_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); +#endif // (BLE_TOPOLOGY_CHECK == TRUE) } } +#endif // (BLE_42_SCAN_EN == TRUE) #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* @@ -5532,6 +5337,7 @@ void bta_dm_ble_set_adv_params_all (tBTA_DM_MSG *p_data) } #endif // #if (BLE_42_ADV_EN == TRUE) +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) /******************************************************************************* ** ** Function bta_dm_ble_update_duplicate_exceptional_list @@ -5547,6 +5353,7 @@ void bta_dm_ble_update_duplicate_exceptional_list(tBTA_DM_MSG *p_data) p_data->ble_duplicate_exceptional_list.device_info, p_data->ble_duplicate_exceptional_list.exceptional_list_cb); } +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* @@ -5700,14 +5507,14 @@ void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data) #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** -** Function bta_dm_ble_broadcast +** Function bta_dm_ble_advstop ** ** Description Starts or stops LE broadcasts ** ** Parameters: ** *******************************************************************************/ -void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data) +void bta_dm_ble_advstop (tBTA_DM_MSG *p_data) { tBTA_STATUS status = BTA_FAILURE; BOOLEAN start = p_data->ble_observe.start; @@ -5725,116 +5532,6 @@ void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data) } #endif // #if (BLE_42_ADV_EN == TRUE) -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_multi_adv_enb -** -** Description This function enables a single advertising instance -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data) -{ - tBTM_STATUS btm_status = 0; - - bta_dm_cb.p_multi_adv_cback = p_data->ble_multi_adv_enb.p_cback; - if (BTM_BleMaxMultiAdvInstanceCount() > 0 && NULL != p_data->ble_multi_adv_enb.p_ref) { - btm_status = BTM_BleEnableAdvInstance((tBTM_BLE_ADV_PARAMS *) - p_data->ble_multi_adv_enb.p_params, - p_data->ble_multi_adv_enb.p_cback, - p_data->ble_multi_adv_enb.p_ref); - } - - if (BTM_CMD_STARTED != btm_status) { - bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_ENB_EVT, 0xFF, - p_data->ble_multi_adv_enb.p_ref, BTA_FAILURE); - } -} -/******************************************************************************* -** -** Function bta_dm_ble_multi_adv_param_upd -** -** Description This function updates multiple advertising instance parameters -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data) -{ - tBTM_STATUS btm_status = 0; - void *p_ref = NULL; - - if (BTM_BleMaxMultiAdvInstanceCount() > 0 && p_data->ble_multi_adv_param.inst_id > 0 - && p_data->ble_multi_adv_param.inst_id < BTM_BleMaxMultiAdvInstanceCount()) { - btm_status = BTM_BleUpdateAdvInstParam(p_data->ble_multi_adv_param.inst_id, - (tBTM_BLE_ADV_PARAMS *)p_data->ble_multi_adv_param.p_params); - } - - if (BTM_CMD_STARTED != btm_status) { - p_ref = btm_ble_multi_adv_get_ref(p_data->ble_multi_adv_param.inst_id); - bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_PARAM_EVT, - p_data->ble_multi_adv_param.inst_id, p_ref, BTA_FAILURE); - } -} -/******************************************************************************* -** -** Function bta_dm_ble_multi_adv_data -** -** Description This function write multiple advertising instance adv data -** or scan response data -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data) -{ - tBTM_STATUS btm_status = 0; - void *p_ref = NULL; - - if (BTM_BleMaxMultiAdvInstanceCount() > 0 && p_data->ble_multi_adv_data.inst_id > 0 - && p_data->ble_multi_adv_data.inst_id < BTM_BleMaxMultiAdvInstanceCount()) { - btm_status = BTM_BleCfgAdvInstData(p_data->ble_multi_adv_data.inst_id, - p_data->ble_multi_adv_data.is_scan_rsp, - p_data->ble_multi_adv_data.data_mask, - (tBTM_BLE_ADV_DATA *)p_data->ble_multi_adv_data.p_data); - } - - if (BTM_CMD_STARTED != btm_status) { - p_ref = btm_ble_multi_adv_get_ref(p_data->ble_multi_adv_data.inst_id); - bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_DATA_EVT, - p_data->ble_multi_adv_data.inst_id, p_ref, BTA_FAILURE); - } - -} -/******************************************************************************* -** -** Function btm_dm_ble_multi_adv_disable -** -** Description This function disable a single adv instance -** -** Parameters: -** -*******************************************************************************/ -void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data) -{ - tBTM_STATUS btm_status = 0; - void *p_ref = NULL; - - if (BTM_BleMaxMultiAdvInstanceCount() > 0 && p_data->ble_multi_adv_disable.inst_id > 0 - && p_data->ble_multi_adv_disable.inst_id < BTM_BleMaxMultiAdvInstanceCount()) { - btm_status = BTM_BleDisableAdvInstance(p_data->ble_multi_adv_disable.inst_id); - } - - if (BTM_CMD_STARTED != btm_status) { - p_ref = btm_ble_multi_adv_get_ref(p_data->ble_multi_adv_disable.inst_id); - bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_DISABLE_EVT, - p_data->ble_multi_adv_disable.inst_id, p_ref, BTA_FAILURE); - } -} -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - #if (BLE_42_DTM_TEST_EN == TRUE) void bta_dm_ble_gap_dtm_tx_start(tBTA_DM_MSG *p_data) { @@ -6347,388 +6044,105 @@ void bta_dm_ble_set_host_feature(tBTA_DM_MSG *p_data) } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_setup_storage -** -** Description This function configures up the storage parameters for ADV batch scanning -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_setup_storage (tBTA_DM_MSG *p_data) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +void bta_dm_api_set_periodic_adv_subevt_data(tBTA_DM_MSG *p_data) { - tBTM_STATUS btm_status = 0; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 != cmn_ble_vsc_cb.tot_scan_results_strg) { - btm_status = BTM_BleSetStorageConfig(p_data->ble_set_storage.batch_scan_full_max, - p_data->ble_set_storage.batch_scan_trunc_max, - p_data->ble_set_storage.batch_scan_notify_threshold, - p_data->ble_set_storage.p_setup_cback, - p_data->ble_set_storage.p_thres_cback, - p_data->ble_set_storage.p_read_rep_cback, - p_data->ble_set_storage.ref_value); - } - - if (BTM_CMD_STARTED != btm_status) { - bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, p_data->ble_set_storage.ref_value, - btm_status); - } -} -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) - -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_enable_batch_scan -** -** Description This function sets up the parameters and enables batch scan -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_enable_batch_scan (tBTA_DM_MSG *p_data) -{ - tBTM_STATUS btm_status = 0; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 != cmn_ble_vsc_cb.tot_scan_results_strg) { - btm_status = BTM_BleEnableBatchScan(p_data->ble_enable_scan.scan_mode, - p_data->ble_enable_scan.scan_int, - p_data->ble_enable_scan.scan_window, - p_data->ble_enable_scan.discard_rule, - p_data->ble_enable_scan.addr_type, - p_data->ble_enable_scan.ref_value); - } - - if (BTM_CMD_STARTED != btm_status) { - bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_ENABLE_EVT, p_data->ble_enable_scan.ref_value, - btm_status); - } + BTM_BleSetPaSubeventData(p_data->pa_subevt_data.adv_handle, p_data->pa_subevt_data.num_subevents_with_data, (uint8_t *)(p_data->pa_subevt_data.subevent_params)); } -/******************************************************************************* -** -** Function bta_dm_ble_disable_batch_scan -** -** Description This function disables the batch scan -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_disable_batch_scan (tBTA_DM_MSG *p_data) +void bta_dm_api_set_periodic_adv_response_data(tBTA_DM_MSG *p_data) { - UNUSED(p_data); - tBTM_STATUS btm_status = 0; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 != cmn_ble_vsc_cb.tot_scan_results_strg) { - btm_status = BTM_BleDisableBatchScan(p_data->ble_disable_scan.ref_value); - } - - if (BTM_CMD_STARTED != btm_status) { - bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_DISABLE_EVT, p_data->ble_enable_scan.ref_value, - btm_status); - } -} -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) - -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_read_scan_reports -** -** Description This function reads the batch scan reports -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_read_scan_reports(tBTA_DM_MSG *p_data) -{ - tBTM_STATUS btm_status = 0; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 != cmn_ble_vsc_cb.tot_scan_results_strg) { - btm_status = BTM_BleReadScanReports(p_data->ble_read_reports.scan_type, - p_data->ble_read_reports.ref_value); - } - - if (BTM_CMD_STARTED != btm_status) { - bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_READ_REPTS_EVT, p_data->ble_enable_scan.ref_value, - btm_status); - } -} -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -/******************************************************************************* -** -** Function bta_dm_ble_track_advertiser -** -** Description This function tracks the specific advertiser -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_track_advertiser(tBTA_DM_MSG *p_data) -{ - tBTM_STATUS btm_status = 0; - BD_ADDR bda; - memset(&bda, 0 , sizeof(BD_ADDR)); - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - tBTA_DM_BLE_TRACK_ADV_DATA track_adv_data; - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 != cmn_ble_vsc_cb.tot_scan_results_strg) { - btm_status = BTM_BleTrackAdvertiser((tBTM_BLE_TRACK_ADV_CBACK *) - p_data->ble_track_advert.p_track_adv_cback, - p_data->ble_track_advert.ref_value); - } - - if (BTM_CMD_STARTED != btm_status) { - memset(&track_adv_data, 0, sizeof(tBTA_DM_BLE_TRACK_ADV_DATA)); - track_adv_data.advertiser_info_present = NO_ADV_INFO_PRESENT; /* Indicates failure */ - track_adv_data.client_if = (UINT8)p_data->ble_track_advert.ref_value; - p_data->ble_track_advert.p_track_adv_cback(&track_adv_data); - } -} -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -/******************************************************************************* -** -** Function bta_ble_scan_setup_cb -** -** Description Handle the setup callback from BTM layer and forward it to app layer -** -** Parameters: -** -*******************************************************************************/ -void bta_ble_scan_setup_cb(tBTM_BLE_BATCH_SCAN_EVT evt, tBTM_BLE_REF_VALUE ref_value, - tBTM_STATUS status) -{ - tBTA_BLE_BATCH_SCAN_EVT bta_evt = 0; - - APPL_TRACE_DEBUG("bta_ble_scan_setup_cb : evt: %d, ref_value: %d, status:%d", evt, - ref_value, status); - - switch (evt) { - case BTM_BLE_BATCH_SCAN_ENABLE_EVT: - bta_evt = BTA_BLE_BATCH_SCAN_ENB_EVT; - break; - case BTM_BLE_BATCH_SCAN_CFG_STRG_EVT: - bta_evt = BTA_BLE_BATCH_SCAN_CFG_STRG_EVT; - break; - case BTM_BLE_BATCH_SCAN_DISABLE_EVT: - bta_evt = BTA_BLE_BATCH_SCAN_DIS_EVT; - break; - case BTM_BLE_BATCH_SCAN_PARAM_EVT: - bta_evt = BTA_BLE_BATCH_SCAN_PARAM_EVT; - break; - default: - break; - } - - if (NULL != bta_dm_cb.p_setup_cback) { - bta_dm_cb.p_setup_cback(bta_evt, ref_value, status); - } + BTM_BleSetPaResponseData(p_data->pa_rsp_data.sync_handle, p_data->pa_rsp_data.request_event, p_data->pa_rsp_data.request_subevent, + p_data->pa_rsp_data.rsp_subevent, p_data->pa_rsp_data.rsp_slot, p_data->pa_rsp_data.rsp_data_len, + p_data->pa_rsp_data.rsp_data); } - -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE -/******************************************************************************* -** -** Function bta_ble_scan_pf_cmpl -** -** Description ADV payload filtering operation complete callback -** -** -** Returns TRUE if handled, otherwise FALSE. -** -*******************************************************************************/ -static void bta_ble_scan_cfg_cmpl(tBTM_BLE_PF_ACTION action, tBTM_BLE_SCAN_COND_OP cfg_op, - tBTM_BLE_PF_AVBL_SPACE avbl_space, tBTM_STATUS status, - tBTM_BLE_REF_VALUE ref_value) +void bta_dm_api_set_periodic_sync_subevt(tBTA_DM_MSG *p_data) { - tBTA_STATUS st = (status == BTM_SUCCESS) ? BTA_SUCCESS : BTA_FAILURE; + BTM_BleSetPaSyncSubevt(p_data->pa_sync_subevt.sync_handle, p_data->pa_sync_subevt.periodic_adv_properties, p_data->pa_sync_subevt.num_subevents_to_sync, p_data->pa_sync_subevt.subevent); +} +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) - APPL_TRACE_DEBUG("bta_ble_scan_cfg_cmpl: %d, %d, %d, %d", action, cfg_op, avbl_space, status); - - if (bta_dm_cb.p_scan_filt_cfg_cback) { - bta_dm_cb.p_scan_filt_cfg_cback(action, cfg_op, avbl_space, st, ref_value); - } +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void bta_dm_api_cs_read_local_supported_caps(tBTA_DM_MSG *p_data) +{ + BTM_BleCSReadLocalSuppCaps(); } -/******************************************************************************* -** -** Function bta_dm_cfg_filter_cond -** -** Description This function configure adv payload filtering condition -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data) +void bta_dm_api_cs_read_remote_supported_caps(tBTA_DM_MSG *p_data) { - tBTM_STATUS st = BTM_MODE_UNSUPPORTED; - tBTA_STATUS status = BTA_FAILURE; - - tBTM_BLE_VSC_CB cmn_vsc_cb; - - APPL_TRACE_DEBUG("bta_dm_cfg_filter_cond"); - BTM_BleGetVendorCapabilities(&cmn_vsc_cb); - if (0 != cmn_vsc_cb.filter_support) { - if ((st = BTM_BleCfgFilterCondition(p_data->ble_cfg_filter_cond.action, - p_data->ble_cfg_filter_cond.cond_type, - (tBTM_BLE_PF_FILT_INDEX)p_data->ble_cfg_filter_cond.filt_index, - (tBTM_BLE_PF_COND_PARAM *)p_data->ble_cfg_filter_cond.p_cond_param, - bta_ble_scan_cfg_cmpl, p_data->ble_cfg_filter_cond.ref_value)) - == BTM_CMD_STARTED) { - bta_dm_cb.p_scan_filt_cfg_cback = p_data->ble_cfg_filter_cond.p_filt_cfg_cback; - return; - } - } - - if (p_data->ble_cfg_filter_cond.p_filt_cfg_cback) { - p_data->ble_cfg_filter_cond.p_filt_cfg_cback(BTA_DM_BLE_PF_CONFIG_EVT, - p_data->ble_cfg_filter_cond.cond_type, 0, status, - p_data->ble_cfg_filter_cond.ref_value); - } - return; + BTM_BleCSReadRemoteSuppCaps(p_data->read_remote_supp_caps.conn_handle); } -/******************************************************************************* -** -** Function bta_dm_enable_scan_filter -** -** Description This function enable/disable adv payload filtering condition -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_enable_scan_filter(tBTA_DM_MSG *p_data) +void bta_dm_api_cs_write_cached_remote_supported_caps(tBTA_DM_MSG *p_data) { - tBTM_STATUS st = BTM_MODE_UNSUPPORTED; - tBTA_STATUS status = BTA_FAILURE; - - tBTM_BLE_VSC_CB cmn_vsc_cb; - APPL_TRACE_DEBUG("bta_dm_enable_scan_filter"); - BTM_BleGetVendorCapabilities(&cmn_vsc_cb); - - if (0 != cmn_vsc_cb.filter_support) { - if ((st = BTM_BleEnableDisableFilterFeature(p_data->ble_enable_scan_filt.action, - p_data->ble_enable_scan_filt.p_filt_status_cback, - (tBTM_BLE_REF_VALUE)p_data->ble_enable_scan_filt.ref_value)) == BTM_CMD_STARTED) { - bta_dm_cb.p_scan_filt_status_cback = p_data->ble_enable_scan_filt.p_filt_status_cback; - } - return; - } - - if (p_data->ble_enable_scan_filt.p_filt_status_cback) { - p_data->ble_enable_scan_filt.p_filt_status_cback (BTA_DM_BLE_PF_ENABLE_EVT, - p_data->ble_enable_scan_filt.ref_value, status); - } - + tBTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPP_CAPS *p = &p_data->write_cached_remote_caps; + BTM_BleGapWriteCachedRemoteSupportedCaps(p->conn_handle, p->num_config_supported, p->max_consecutive_proc_supported, + p->num_ant_supported, p->max_ant_paths_supported, p->roles_supported, + p->modes_supported, p->rtt_capability, p->rtt_aa_only_n, + p->rtt_sounding_n, p->rtt_random_payload_n, p->NADM_sounding_capability, + p->NADM_random_capability, p->cs_sync_phys_supported, p->subfeatures_supported, + p->T_IP1_times_supported, p->T_IP2_times_supported, p->T_FCS_times_supported, + p->T_PM_times_supported, p->T_SW_times_supported, p->TX_SNR_capability); } -/******************************************************************************* -** -** Function bta_dm_scan_filter_param_setup -** -** Description This function sets up scan filter params -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_scan_filter_param_setup (tBTA_DM_MSG *p_data) +void bta_dm_api_cs_security_enable(tBTA_DM_MSG *p_data) { - tBTM_STATUS st = BTM_MODE_UNSUPPORTED; - tBTA_STATUS status = BTA_FAILURE; - - tBTM_BLE_VSC_CB cmn_vsc_cb; - - APPL_TRACE_DEBUG("bta_dm_scan_filter_param_setup"); - BTM_BleGetVendorCapabilities(&cmn_vsc_cb); - if (0 != cmn_vsc_cb.filter_support) { - if ((st = BTM_BleAdvFilterParamSetup(p_data->ble_scan_filt_param_setup.action, - p_data->ble_scan_filt_param_setup.filt_index, - (tBTM_BLE_PF_FILT_PARAMS *)&p_data->ble_scan_filt_param_setup.filt_params, - p_data->ble_scan_filt_param_setup.p_target, - p_data->ble_scan_filt_param_setup.p_filt_param_cback, - p_data->ble_scan_filt_param_setup.ref_value)) == BTM_CMD_STARTED) { - bta_dm_cb.p_scan_filt_param_cback = p_data->ble_scan_filt_param_setup.p_filt_param_cback; - return; - } - } - - if (p_data->ble_scan_filt_param_setup.p_filt_param_cback) { - p_data->ble_scan_filt_param_setup.p_filt_param_cback (BTA_DM_BLE_PF_ENABLE_EVT, 0, - p_data->ble_scan_filt_param_setup.ref_value, status); - } - - return; -} -#endif - -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) -/******************************************************************************* -** -** Function bta_ble_enable_scan_cmpl -** -** Description ADV payload filtering enable / disable complete callback -** -** -** Returns None -** -*******************************************************************************/ -static void bta_ble_energy_info_cmpl(tBTM_BLE_TX_TIME_MS tx_time, - tBTM_BLE_RX_TIME_MS rx_time, - tBTM_BLE_IDLE_TIME_MS idle_time, - tBTM_BLE_ENERGY_USED energy_used, - tBTM_STATUS status) -{ - tBTA_STATUS st = (status == BTM_SUCCESS) ? BTA_SUCCESS : BTA_FAILURE; - tBTA_DM_CONTRL_STATE ctrl_state = 0; -#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) - if (BTA_SUCCESS == st) { - ctrl_state = bta_dm_pm_obtain_controller_state(); - } -#endif - if (bta_dm_cb.p_energy_info_cback) { - bta_dm_cb.p_energy_info_cback(tx_time, rx_time, idle_time, energy_used, ctrl_state, st); - } + BTM_BleGapCsSecurityEnable(p_data->security_enable.conn_handle); } -/******************************************************************************* -** -** Function bta_dm_ble_get_energy_info -** -** Description This function obtains the energy info -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data) +void bta_dm_api_cs_set_default_settings(tBTA_DM_MSG *p_data) { - tBTM_STATUS btm_status = 0; - - bta_dm_cb.p_energy_info_cback = p_data->ble_energy_info.p_energy_info_cback; - btm_status = BTM_BleGetEnergyInfo(bta_ble_energy_info_cmpl); - if (BTM_CMD_STARTED != btm_status) { - bta_ble_energy_info_cmpl(0, 0, 0, 0, btm_status); - } + BTM_BleGapCsSetDefaultSetting(p_data->set_default_setting_params.conn_handle, p_data->set_default_setting_params.role_enable, + p_data->set_default_setting_params.cs_sync_ant_selection, p_data->set_default_setting_params.max_tx_power); } -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) + +void bta_dm_api_cs_read_remote_fae_table(tBTA_DM_MSG *p_data) +{ + BTM_BleGapCsReadRemoteFaeTable(p_data->read_remote_tab.conn_handle); +} + +void bta_dm_api_cs_write_cached_remote_fae_table(tBTA_DM_MSG *p_data) +{ + BTM_BleGapWriteCachedRemoteFaeTable(p_data->write_cached_remote_fae_tab_params.conn_handle, p_data->write_cached_remote_fae_tab_params.remote_fae_table); +} + +void bta_dm_api_cs_create_config(tBTA_DM_MSG *p_data) +{ + tBTA_DM_API_CS_CREATE_CONFIG_PARAMS *p = &p_data->create_config_params; + BTM_BleGapCsCreateConfig(p->conn_handle, p->config_id, p->create_context, + p->main_mode_type, p->sub_mode_type, p->min_main_mode_steps, + p->max_main_mode_steps, p->main_mode_repetition, p->mode_0_steps, + p->role, p->rtt_type, p->cs_sync_phy, &p->channel_map[0], + p->channel_map_repetition, p->channel_selection_type, p->ch3c_shape, + p->ch3c_jump, p->reserved); +} + +void bta_dm_api_cs_remove_config(tBTA_DM_MSG *p_data) +{ + BTM_BleGapCsRemoveConfig(p_data->remove_config_params.conn_handle, p_data->remove_config_params.config_id); +} + +void bta_dm_api_cs_set_channel_classification(tBTA_DM_MSG *p_data) +{ + BTM_BleGapCsSetChannelClass(p_data->set_channel_class_params.channel_class); +} +void bta_dm_api_cs_set_procedure_params(tBTA_DM_MSG *p_data) +{ + tBTA_DM_API_CS_SET_PROC_PARAMS *p = &p_data->set_proc_params; + BTM_BleGapCsSetProcPatams(p->conn_handle, p->config_id, p->max_procedure_len, + p->min_procedure_interval, p->max_procedure_interval, + p->max_procedure_count, p->min_subevent_len, + p->max_subevent_len, p->tone_ant_config_selection, + p->phy, p->tx_power_delta, p->preferred_peer_antenna, + p->SNR_control_initiator, p->SNR_control_reflector); +} + +void bta_dm_api_cs_procedure_enable(tBTA_DM_MSG *p_data) +{ + BTM_BleGapCsProcEnable(p_data->proc_enable_params.conn_handle, p_data->proc_enable_params.config_id, p_data->proc_enable_params.enable); +} +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) #if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) #ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT @@ -6942,7 +6356,7 @@ void btm_dm_start_gatt_discovery (BD_ADDR bd_addr) } else { //TODO need to add addr_type in future BTA_GATTC_Enh_Open(bta_dm_search_cb.client_if, bd_addr, BLE_ADDR_UNKNOWN_TYPE, TRUE, - BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, 0, NULL, NULL, NULL); + BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, false, 0xFF, 0xFF, 0, NULL, NULL, NULL); } } @@ -7064,28 +6478,4 @@ static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) #endif /* #if (GATTC_INCLUDED == TRUE) */ #endif /* BTA_GATT_INCLUDED */ -#if BLE_VND_INCLUDED == TRUE -/******************************************************************************* -** -** Function bta_dm_ctrl_features_rd_cmpl_cback -** -** Description callback to handle controller feature read complete -** -** Parameters: -** -*******************************************************************************/ -static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result) -{ - APPL_TRACE_DEBUG("%s status = %d ", __FUNCTION__, result); - if (result == BTM_SUCCESS) { - if (bta_dm_cb.p_sec_cback) { - bta_dm_cb.p_sec_cback(BTA_DM_LE_FEATURES_READ, NULL); - } - } else { - APPL_TRACE_ERROR("%s Ctrl BLE feature read failed: status :%d", __FUNCTION__, result); - } - -} -#endif /* BLE_VND_INCLUDED */ - #endif /* BLE_INCLUDED */ diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c index 08510894e6..aaf0d8864f 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -73,8 +73,10 @@ tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback) bta_sys_register (BTA_ID_DM, &bta_dm_reg ); bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg ); +#if (CLASSIC_BT_INCLUDED == TRUE) /* if UUID list is not provided as static data */ bta_sys_eir_register(bta_dm_eir_update_uuid); +#endif // (CLASSIC_BT_INCLUDED == TRUE) if ((p_msg = (tBTA_DM_API_ENABLE *) osi_malloc(sizeof(tBTA_DM_API_ENABLE))) != NULL) { p_msg->hdr.event = BTA_DM_API_ENABLE_EVT; @@ -110,53 +112,6 @@ tBTA_STATUS BTA_DisableBluetooth(void) return BTA_SUCCESS; } -#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) -/******************************************************************************* -** -** Function BTA_EnableTestMode -** -** Description Enables bluetooth device under test mode -** -** -** Returns tBTA_STATUS -** -*******************************************************************************/ -tBTA_STATUS BTA_EnableTestMode(void) -{ - BT_HDR *p_msg; - - APPL_TRACE_API("BTA_EnableTestMode"); - - if ((p_msg = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { - p_msg->event = BTA_DM_API_ENABLE_TEST_MODE_EVT; - bta_sys_sendmsg(p_msg); - return BTA_SUCCESS; - } - return BTA_FAILURE; -} - -/******************************************************************************* -** -** Function BTA_DisableTestMode -** -** Description Disable bluetooth device under test mode -** -** -** Returns None -** -*******************************************************************************/ -void BTA_DisableTestMode(void) -{ - BT_HDR *p_msg; - - APPL_TRACE_API("BTA_DisableTestMode"); - - if ((p_msg = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { - p_msg->event = BTA_DM_API_DISABLE_TEST_MODE_EVT; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) /******************************************************************************* ** @@ -540,18 +495,6 @@ void BTA_DmClearWhiteList(tBTA_UPDATE_WHITELIST_CBACK *update_wl_cb) } } -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb) -{ - tBTA_DM_API_READ_ADV_TX_POWER *p_msg; - if ((p_msg = (tBTA_DM_API_READ_ADV_TX_POWER *)osi_malloc(sizeof(tBTA_DM_API_READ_ADV_TX_POWER))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_READ_ADV_TX_POWER_EVT; - p_msg->read_tx_power_cb = cmpl_cb; - bta_sys_sendmsg(p_msg); - } -} -#endif // BLE_HOST_READ_TX_POWER_EN - void BTA_DmBleReadChannelMap(BD_ADDR remote_device, tBTA_CMPL_CB *p_callback) { if (!remote_device || !p_callback) { @@ -1222,31 +1165,6 @@ tBTA_STATUS BTA_DmRemoveLocalDiRecord(UINT32 handle) } #endif ///SDP_INCLUDED == TRUE -#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) -/******************************************************************************* -** -** Function bta_dmexecutecallback -** -** Description This function will request BTA to execute a call back in the context of BTU task -** This API was named in lower case because it is only intended -** for the internal customers(like BTIF). -** -** Returns void -** -*******************************************************************************/ -void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK *p_callback, void *p_param) -{ - tBTA_DM_API_EXECUTE_CBACK *p_msg; - - if ((p_msg = (tBTA_DM_API_EXECUTE_CBACK *) osi_malloc(sizeof(tBTA_DM_API_EXECUTE_CBACK))) != NULL) { - p_msg->hdr.event = BTA_DM_API_EXECUTE_CBACK_EVT; - p_msg->p_param = p_param; - p_msg->p_exec_cback = p_callback; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) - /******************************************************************************* ** ** Function BTA_DmAddBleKey @@ -1456,69 +1374,6 @@ void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr, #endif } -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmSetBleConnScanParams -** -** Description This function is called to set scan parameters used in -** BLE connection request -** -** Parameters: scan_interval - scan interval -** scan_window - scan window -** -** Returns void -** -*******************************************************************************/ -void BTA_DmSetBleConnScanParams(UINT32 scan_interval, UINT32 scan_window) -{ - tBTA_DM_API_BLE_SCAN_PARAMS *p_msg; - if ((p_msg = (tBTA_DM_API_BLE_SCAN_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_BLE_SCAN_PARAMS))) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SCAN_PARAMS)); - p_msg->hdr.event = BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT; - p_msg->scan_int = scan_interval; - p_msg->scan_window = scan_window; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) - -#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) -/******************************************************************************* -** -** Function BTA_DmSetBleScanParams -** -** Description This function is called to set scan parameters -** -** Parameters: client_if - Client IF -** scan_interval - scan interval -** scan_window - scan window -** scan_mode - scan mode -** scan_param_setup_status_cback - Set scan param status callback -** -** Returns void -** -*******************************************************************************/ -void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval, - UINT32 scan_window, tBLE_SCAN_MODE scan_mode, - tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback) -{ - tBTA_DM_API_BLE_SCAN_PARAMS *p_msg; - - if ((p_msg = (tBTA_DM_API_BLE_SCAN_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_BLE_SCAN_PARAMS))) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SCAN_PARAMS)); - p_msg->hdr.event = BTA_DM_API_BLE_SCAN_PARAM_EVT; - p_msg->client_if = client_if; - p_msg->scan_int = scan_interval; - p_msg->scan_window = scan_window; - p_msg->scan_mode = scan_mode; - p_msg->scan_param_setup_cback = scan_param_setup_cback; - - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) - #if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** @@ -1725,6 +1580,7 @@ void BTA_DmBleSetScanRspRaw (UINT8 *p_raw_scan_rsp, UINT32 raw_scan_rsp_len, } #endif // #if (BLE_42_ADV_EN == TRUE) +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) /******************************************************************************* ** ** Function BTA_DmUpdateDuplicateExceptionalList @@ -1752,165 +1608,7 @@ void BTA_DmUpdateDuplicateExceptionalList(UINT8 subcode, UINT32 type, BD_ADDR de bta_sys_sendmsg(p_msg); } } -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleSetStorageParams -** -** Description This function is called to override the BTA scan response. -** -** Parameters batch_scan_full_max -Max storage space (in %) allocated to full scanning -** batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning -** batch_scan_notify_threshold -Setup notification level based on total space -** p_setup_cback - Setup callback pointer -** p_thres_cback - Threshold callback pointer -** p_rep_cback - Reports callback pointer -** ref_value - Ref value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleSetStorageParams(UINT8 batch_scan_full_max, - UINT8 batch_scan_trunc_max, - UINT8 batch_scan_notify_threshold, - tBTA_BLE_SCAN_SETUP_CBACK *p_setup_cback, - tBTA_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback, - tBTA_BLE_SCAN_REP_CBACK *p_rep_cback, - tBTA_DM_BLE_REF_VALUE ref_value) -{ - tBTA_DM_API_SET_STORAGE_CONFIG *p_msg; - bta_dm_cb.p_setup_cback = p_setup_cback; - if ((p_msg = (tBTA_DM_API_SET_STORAGE_CONFIG *) - osi_malloc(sizeof(tBTA_DM_API_SET_STORAGE_CONFIG))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_SETUP_STORAGE_EVT; - p_msg->p_setup_cback = bta_ble_scan_setup_cb; - p_msg->p_thres_cback = p_thres_cback; - p_msg->p_read_rep_cback = p_rep_cback; - p_msg->ref_value = ref_value; - p_msg->batch_scan_full_max = batch_scan_full_max; - p_msg->batch_scan_trunc_max = batch_scan_trunc_max; - p_msg->batch_scan_notify_threshold = batch_scan_notify_threshold; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) - -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleEnableBatchScan -** -** Description This function is called to enable the batch scan -** -** Parameters scan_mode -Batch scan mode -** scan_interval - Scan interval -** scan_window - Scan window -** discard_rule -Discard rules -** addr_type - Address type -** ref_value - Reference value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleEnableBatchScan(tBTA_BLE_BATCH_SCAN_MODE scan_mode, - UINT32 scan_interval, UINT32 scan_window, - tBTA_BLE_DISCARD_RULE discard_rule, - tBLE_ADDR_TYPE addr_type, - tBTA_DM_BLE_REF_VALUE ref_value) -{ - tBTA_DM_API_ENABLE_SCAN *p_msg; - - if ((p_msg = (tBTA_DM_API_ENABLE_SCAN *) osi_malloc(sizeof(tBTA_DM_API_ENABLE_SCAN))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT; - p_msg->scan_mode = scan_mode; - p_msg->scan_int = scan_interval; - p_msg->scan_window = scan_window; - p_msg->discard_rule = discard_rule; - p_msg->addr_type = addr_type; - p_msg->ref_value = ref_value; - bta_sys_sendmsg(p_msg); - } -} - -/******************************************************************************* -** -** Function BTA_DmBleDisableBatchScan -** -** Description This function is called to disable the batch scan -** -** Parameters ref_value - Reference value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleDisableBatchScan(tBTA_DM_BLE_REF_VALUE ref_value) -{ - tBTA_DM_API_DISABLE_SCAN *p_msg; - - if ((p_msg = (tBTA_DM_API_DISABLE_SCAN *) - osi_malloc(sizeof(tBTA_DM_API_DISABLE_SCAN))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT; - p_msg->ref_value = ref_value; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) - -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleReadScanReports -** -** Description This function is called to read scan reports -** -** Parameters scan_type -Batch scan mode -** ref_value - Reference value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleReadScanReports(tBTA_BLE_BATCH_SCAN_MODE scan_type, - tBTA_DM_BLE_REF_VALUE ref_value) -{ - tBTA_DM_API_READ_SCAN_REPORTS *p_msg; - - if ((p_msg = (tBTA_DM_API_READ_SCAN_REPORTS *) - osi_malloc(sizeof(tBTA_DM_API_READ_SCAN_REPORTS))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT; - p_msg->scan_type = scan_type; - p_msg->ref_value = ref_value; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleTrackAdvertiser -** -** Description This function is called to track advertiser -** -** Parameters ref_value - Reference value -** p_track_adv_cback - Track ADV callback -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value, - tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback) -{ - tBTA_DM_API_TRACK_ADVERTISER *p_msg; - - if ((p_msg = (tBTA_DM_API_TRACK_ADVERTISER *) - osi_malloc(sizeof(tBTA_DM_API_TRACK_ADVERTISER))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_TRACK_ADVERTISER_EVT; - p_msg->p_track_adv_cback = p_track_adv_cback; - p_msg->ref_value = ref_value; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) #endif @@ -1921,25 +1619,25 @@ extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value, #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** -** Function BTA_DmBleBroadcast +** Function BTA_DmBleAdvStop ** ** Description This function starts or stops LE broadcasting. ** -** Parameters start: start or stop broadcast. +** Parameters start: always be false. ** ** Returns None ** *******************************************************************************/ -extern void BTA_DmBleBroadcast (BOOLEAN start, tBTA_START_STOP_ADV_CMPL_CBACK *p_start_stop_adv_cb) +extern void BTA_DmBleAdvStop (BOOLEAN start, tBTA_START_STOP_ADV_CMPL_CBACK *p_start_stop_adv_cb) { tBTA_DM_API_BLE_OBSERVE *p_msg; - APPL_TRACE_API("BTA_DmBleBroadcast: start = %d \n", start); + APPL_TRACE_API("BTA_DmBleAdvStop: start = %d \n", start); if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) osi_malloc(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL) { memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE)); - p_msg->hdr.event = BTA_DM_API_BLE_BROADCAST_EVT; + p_msg->hdr.event = BTA_DM_API_BLE_ADVSTOP_EVT; p_msg->start = start; if (start == FALSE){ p_msg->p_stop_adv_cback= p_start_stop_adv_cb; @@ -1951,6 +1649,8 @@ extern void BTA_DmBleBroadcast (BOOLEAN start, tBTA_START_STOP_ADV_CMPL_CBACK *p #endif // #if (BLE_42_ADV_EN == TRUE) #endif + +#if (BLE_GATT_BGCONN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleSetBgConnType @@ -1981,6 +1681,7 @@ void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_ } #endif } +#endif// (BLE_GATT_BGCONN == TRUE) /******************************************************************************* ** @@ -2223,389 +1924,40 @@ void BTA_DmBleConfigLocalIcon(uint16_t icon) } } -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) /******************************************************************************* ** -** Function BTA_BleEnableAdvInstance +** Function BTA_DmBleSetKeyMaterial ** -** Description This function enable a Multi-ADV instance with the specified -** adv parameters +** Description Set the Encrypted Data Key Material in GAP service ** -** Parameters p_params: pointer to the adv parameter structure. -** p_cback: callback function associated to this adv instance. -** p_ref: reference data pointer to this adv instance. -** -** Returns BTA_SUCCESS if command started successfully; otherwise failure. -** -*******************************************************************************/ -void BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params, - tBTA_BLE_MULTI_ADV_CBACK *p_cback, - void *p_ref) -{ - ///This function just used for vendor debug - tBTA_DM_API_BLE_MULTI_ADV_ENB *p_msg; - UINT16 len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB); - - APPL_TRACE_API ("BTA_BleEnableAdvInstance"); - - if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_ENB *) osi_malloc(len)) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB)); - - p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_ENB_EVT; - p_msg->p_cback = (void *)p_cback; - if (p_params != NULL) { - p_msg->p_params = (void *)(p_msg + 1); - memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS)); - } - p_msg->p_ref = p_ref; - - bta_sys_sendmsg(p_msg); - } -} - -/******************************************************************************* -** -** Function BTA_BleUpdateAdvInstParam -** -** Description This function update a Multi-ADV instance with the specified -** adv parameters. -** -** Parameters inst_id: Adv instance to update the parameter. -** p_params: pointer to the adv parameter structure. -** -** Returns BTA_SUCCESS if command started successfully; otherwise failure. -** -*******************************************************************************/ -void BTA_BleUpdateAdvInstParam (UINT8 inst_id, tBTA_BLE_ADV_PARAMS *p_params) -{ - ///This function just used for vendor debug - tBTA_DM_API_BLE_MULTI_ADV_PARAM *p_msg; - UINT16 len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM); - - APPL_TRACE_API ("BTA_BleUpdateAdvInstParam"); - if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_PARAM *) osi_malloc(len)) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM)); - p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT; - p_msg->inst_id = inst_id; - p_msg->p_params = (void *)(p_msg + 1); - memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS)); - - bta_sys_sendmsg(p_msg); - } -} - -/******************************************************************************* -** -** Function BTA_BleCfgAdvInstData -** -** Description This function configure a Multi-ADV instance with the specified -** adv data or scan response data. -** -** Parameter inst_id: Adv instance to configure the adv data or scan response. -** is_scan_rsp: is the data scan response or adv data. -** data_mask: adv data type as bit mask. -** p_data: pointer to the ADV data structure tBTA_BLE_ADV_DATA. This -** memory space can not be freed until BTA_BLE_MULTI_ADV_DATA_EVT -** is sent to application. -** -** Returns BTA_SUCCESS if command started successfully; otherwise failure. -** -*******************************************************************************/ -void BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp, - tBTA_BLE_AD_MASK data_mask, - tBTA_BLE_ADV_DATA *p_data) -{ - ///This function just used for vendor debug - tBTA_DM_API_BLE_MULTI_ADV_DATA *p_msg; - UINT16 len = sizeof(tBTA_DM_API_BLE_MULTI_ADV_DATA) ; - - APPL_TRACE_API ("BTA_BleCfgAdvInstData"); - - if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DATA *) osi_malloc(len)) != NULL) { - memset(p_msg, 0, len); - p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_DATA_EVT; - p_msg->inst_id = inst_id; - p_msg->is_scan_rsp = is_scan_rsp; - p_msg->data_mask = data_mask; - p_msg->p_data = p_data; - - bta_sys_sendmsg(p_msg); - } -} - -/******************************************************************************* -** -** Function BTA_BleDisableAdvInstance -** -** Description This function disable a Multi-ADV instance. -** -** Parameter inst_id: instance ID to disable. -** -** Returns BTA_SUCCESS if command started successfully; otherwise failure. -** -*******************************************************************************/ -void BTA_BleDisableAdvInstance (UINT8 inst_id) //this function just used for vendor debug -{ - tBTA_DM_API_BLE_MULTI_ADV_DISABLE *p_msg; - - APPL_TRACE_API ("BTA_BleDisableAdvInstance: %d", inst_id); - if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DISABLE *) - osi_malloc(sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE))) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE)); - p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT; - p_msg->inst_id = inst_id; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - -/******************************************************************************* -** -** Function BTA_DmBleCfgFilterCondition -** -** Description This function is called to configure the adv data payload filter -** condition. -** -** Parameters action: to read/write/clear -** cond_type: filter condition type -** filt_index - Filter index -** p_cond: filter condition parameter -** p_cmpl_back - Command completed callback -** ref_value - Reference value +** Parameters: session_key - 16-byte session key (must not be NULL) +** iv - 8-byte initialization vector (must not be NULL) ** ** Returns void ** *******************************************************************************/ -void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action, - tBTA_DM_BLE_PF_COND_TYPE cond_type, - tBTA_DM_BLE_PF_FILT_INDEX filt_index, - tBTA_DM_BLE_PF_COND_PARAM *p_cond, - tBTA_DM_BLE_PF_CFG_CBACK *p_cmpl_cback, - tBTA_DM_BLE_REF_VALUE ref_value) +void BTA_DmBleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv) { -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE - tBTA_DM_API_CFG_FILTER_COND *p_msg; - APPL_TRACE_API ("BTA_DmBleCfgFilterCondition: %d, %d", action, cond_type); + tBTA_DM_API_KEY_MATERIAL *p_msg; - UINT16 len = sizeof(tBTA_DM_API_CFG_FILTER_COND) + - sizeof(tBTA_DM_BLE_PF_COND_PARAM); - UINT8 *p; - - if (NULL != p_cond) { - switch (cond_type) { - case BTA_DM_BLE_PF_SRVC_DATA_PATTERN: - case BTA_DM_BLE_PF_MANU_DATA: - /* Length of pattern and pattern mask and other elements in */ - /* tBTA_DM_BLE_PF_MANU_COND */ - len += ((p_cond->manu_data.data_len) * 2) + - sizeof(UINT16) + sizeof(UINT16) + sizeof(UINT8); - break; - - case BTA_DM_BLE_PF_LOCAL_NAME: - len += ((p_cond->local_name.data_len) + sizeof(UINT8)); - break; - - case BTM_BLE_PF_SRVC_UUID: - case BTM_BLE_PF_SRVC_SOL_UUID: - len += sizeof(tBLE_BD_ADDR) + sizeof(tBTA_DM_BLE_PF_COND_MASK); - break; - - default: - break; - } + if (session_key == NULL || iv == NULL) { + APPL_TRACE_ERROR("%s: NULL pointer parameter", __func__); + return; } - if ((p_msg = (tBTA_DM_API_CFG_FILTER_COND *) osi_malloc(len)) != NULL) { - memset (p_msg, 0, len); - - p_msg->hdr.event = BTA_DM_API_CFG_FILTER_COND_EVT; - p_msg->action = action; - p_msg->cond_type = cond_type; - p_msg->filt_index = filt_index; - p_msg->p_filt_cfg_cback = p_cmpl_cback; - p_msg->ref_value = ref_value; - if (p_cond) { - p_msg->p_cond_param = (tBTA_DM_BLE_PF_COND_PARAM *)(p_msg + 1); - memcpy(p_msg->p_cond_param, p_cond, sizeof(tBTA_DM_BLE_PF_COND_PARAM)); - - p = (UINT8 *)(p_msg->p_cond_param + 1); - - if (cond_type == BTA_DM_BLE_PF_SRVC_DATA_PATTERN || - cond_type == BTA_DM_BLE_PF_MANU_DATA) { - p_msg->p_cond_param->manu_data.p_pattern = p; - p_msg->p_cond_param->manu_data.data_len = p_cond->manu_data.data_len; - memcpy(p_msg->p_cond_param->manu_data.p_pattern, p_cond->manu_data.p_pattern, - p_cond->manu_data.data_len); - p += p_cond->manu_data.data_len; - - if (cond_type == BTA_DM_BLE_PF_MANU_DATA) { - p_msg->p_cond_param->manu_data.company_id_mask = - p_cond->manu_data.company_id_mask; - if ( p_cond->manu_data.p_pattern_mask != NULL) { - p_msg->p_cond_param->manu_data.p_pattern_mask = p; - memcpy(p_msg->p_cond_param->manu_data.p_pattern_mask, - p_cond->manu_data.p_pattern_mask, p_cond->manu_data.data_len); - } - } - } else if (cond_type == BTA_DM_BLE_PF_LOCAL_NAME) { - p_msg->p_cond_param->local_name.p_data = p; - p_msg->p_cond_param->local_name.data_len = - p_cond->local_name.data_len; - memcpy(p_msg->p_cond_param->local_name.p_data, - p_cond->local_name.p_data, p_cond->local_name.data_len); - } else if ((cond_type == BTM_BLE_PF_SRVC_UUID - || cond_type == BTM_BLE_PF_SRVC_SOL_UUID)) { - if (p_cond->srvc_uuid.p_target_addr != NULL) { - p_msg->p_cond_param->srvc_uuid.p_target_addr = (tBLE_BD_ADDR *)(p); - p_msg->p_cond_param->srvc_uuid.p_target_addr->type = - p_cond->srvc_uuid.p_target_addr->type; - memcpy(p_msg->p_cond_param->srvc_uuid.p_target_addr->bda, - p_cond->srvc_uuid.p_target_addr->bda, BD_ADDR_LEN); - p = (UINT8 *)( p_msg->p_cond_param->srvc_uuid.p_target_addr + 1); - } - if (p_cond->srvc_uuid.p_uuid_mask) { - p_msg->p_cond_param->srvc_uuid.p_uuid_mask = (tBTA_DM_BLE_PF_COND_MASK *)p; - memcpy(p_msg->p_cond_param->srvc_uuid.p_uuid_mask, - p_cond->srvc_uuid.p_uuid_mask, sizeof(tBTA_DM_BLE_PF_COND_MASK)); - } - } - } + if ((p_msg = (tBTA_DM_API_KEY_MATERIAL *) osi_malloc(sizeof(tBTA_DM_API_KEY_MATERIAL))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_KEY_MATERIAL)); + p_msg->hdr.event = BTA_DM_API_KEY_MATERIAL_EVT; + memcpy(p_msg->session_key, session_key, 16); + memcpy(p_msg->iv, iv, 8); bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s: failed to allocate memory", __func__); } -#else - UNUSED(action); - UNUSED(cond_type); - UNUSED(filt_index); - UNUSED(p_cond); - UNUSED(p_cmpl_cback); - UNUSED(ref_value); +} #endif -} - -/******************************************************************************* -** -** Function BTA_DmBleScanFilterSetup -** -** Description This function is called to setup the adv data payload filter param -** -** Parameters p_target: enable the filter condition on a target device; if NULL -** filt_index - Filter index -** p_filt_params -Filter parameters -** ref_value - Reference value -** action - Add, delete or clear -** p_cmpl_back - Command completed callback -** -** Returns void -** -*******************************************************************************/ -void BTA_DmBleScanFilterSetup(UINT8 action, tBTA_DM_BLE_PF_FILT_INDEX filt_index, - tBTA_DM_BLE_PF_FILT_PARAMS *p_filt_params, - tBLE_BD_ADDR *p_target, - tBTA_DM_BLE_PF_PARAM_CBACK *p_cmpl_cback, - tBTA_DM_BLE_REF_VALUE ref_value) -{ -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE - tBTA_DM_API_SCAN_FILTER_PARAM_SETUP *p_msg; - APPL_TRACE_API ("BTA_DmBleScanFilterSetup: %d", action); - - UINT16 len = sizeof(tBTA_DM_API_SCAN_FILTER_PARAM_SETUP) + sizeof(tBLE_BD_ADDR); - - if ((p_msg = (tBTA_DM_API_SCAN_FILTER_PARAM_SETUP *) osi_malloc(len)) != NULL) { - memset (p_msg, 0, len); - - p_msg->hdr.event = BTA_DM_API_SCAN_FILTER_SETUP_EVT; - p_msg->action = action; - p_msg->filt_index = filt_index; - if (p_filt_params) { - memcpy(&p_msg->filt_params, p_filt_params, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS)); - } - p_msg->p_filt_param_cback = p_cmpl_cback; - p_msg->ref_value = ref_value; - - if (p_target) { - p_msg->p_target = (tBLE_BD_ADDR *)(p_msg + 1); - memcpy(p_msg->p_target, p_target, sizeof(tBLE_BD_ADDR)); - } - - bta_sys_sendmsg(p_msg); - } -#else - UNUSED(action); - UNUSED(filt_index); - UNUSED(p_filt_params); - UNUSED(p_target); - UNUSED(p_cmpl_cback); - UNUSED(ref_value); -#endif -} - -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleGetEnergyInfo -** -** Description This function is called to obtain the energy info -** -** Parameters p_cmpl_cback - Command complete callback -** -** Returns void -** -*******************************************************************************/ -void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK *p_cmpl_cback) -{ - tBTA_DM_API_ENERGY_INFO *p_msg; - APPL_TRACE_API ("BTA_DmBleGetEnergyInfo"); - - UINT16 len = sizeof(tBTA_DM_API_ENERGY_INFO) + sizeof(tBLE_BD_ADDR); - - if ((p_msg = (tBTA_DM_API_ENERGY_INFO *) osi_malloc(len)) != NULL) { - memset (p_msg, 0, len); - p_msg->hdr.event = BTA_DM_API_BLE_ENERGY_INFO_EVT; - p_msg->p_energy_info_cback = p_cmpl_cback; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) - -/******************************************************************************* -** -** Function BTA_DmEnableScanFilter -** -** Description This function is called to enable the adv data payload filter -** -** Parameters action - enable or disable the APCF feature -** p_cmpl_cback - Command completed callback -** ref_value - Reference value -** -** Returns void -** -*******************************************************************************/ -void BTA_DmEnableScanFilter(UINT8 action, tBTA_DM_BLE_PF_STATUS_CBACK *p_cmpl_cback, - tBTA_DM_BLE_REF_VALUE ref_value) -{ -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE - tBTA_DM_API_ENABLE_SCAN_FILTER *p_msg; - APPL_TRACE_API ("BTA_DmEnableScanFilter: %d\n", action); - - UINT16 len = sizeof(tBTA_DM_API_ENABLE_SCAN_FILTER) + sizeof(tBLE_BD_ADDR); - - if ((p_msg = (tBTA_DM_API_ENABLE_SCAN_FILTER *) osi_malloc(len)) != NULL) { - memset (p_msg, 0, len); - - p_msg->hdr.event = BTA_DM_API_SCAN_FILTER_ENABLE_EVT; - p_msg->action = action; - p_msg->ref_value = ref_value; - p_msg->p_filt_status_cback = p_cmpl_cback; - - bta_sys_sendmsg(p_msg); - } -#else - UNUSED(action); - UNUSED(p_cmpl_cback); - UNUSED(ref_value); -#endif -} /******************************************************************************* ** @@ -2796,83 +2148,7 @@ void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_DM_ENCR } #endif ///SMP_INCLUDED == TRUE -#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmCloseACL -** -** Description This function force to close an ACL connection and remove the -** device from the security database list of known devices. -** -** Parameters: bd_addr - Address of the peer device -** remove_dev - remove device or not after link down -** -** Returns void -** -*******************************************************************************/ -void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transport) -{ - tBTA_DM_API_REMOVE_ACL *p_msg; - - APPL_TRACE_API("BTA_DmCloseACL"); - - if ((p_msg = (tBTA_DM_API_REMOVE_ACL *) osi_malloc(sizeof(tBTA_DM_API_REMOVE_ACL))) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_REMOVE_ACL)); - - p_msg->hdr.event = BTA_DM_API_REMOVE_ACL_EVT; - - memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN); - p_msg->remove_dev = remove_dev; - p_msg->transport = transport; - - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) - #if BLE_INCLUDED == TRUE -#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleObserve -** -** Description This procedure keep the device listening for advertising -** events from a broadcast device. -** -** Parameters start: start or stop observe. -** -** Returns void - -** -** Returns void. -** -*******************************************************************************/ -extern void BTA_DmBleObserve(BOOLEAN start, UINT32 duration, - tBTA_DM_SEARCH_CBACK *p_results_cb, - tBTA_START_STOP_SCAN_CMPL_CBACK *p_start_stop_scan_cb) -{ - tBTA_DM_API_BLE_OBSERVE *p_msg; - - APPL_TRACE_API("BTA_DmBleObserve:start = %d ", start); - - if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) osi_malloc(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE)); - - p_msg->hdr.event = BTA_DM_API_BLE_OBSERVE_EVT; - p_msg->start = start; - p_msg->duration = duration; - p_msg->p_cback = p_results_cb; - if (start){ - p_msg->p_start_scan_cback = p_start_stop_scan_cb; - } - else { - p_msg->p_stop_scan_cback = p_start_stop_scan_cb; - } - - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) #if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* @@ -2917,33 +2193,6 @@ extern void BTA_DmBleScan(BOOLEAN start, UINT32 duration, } #endif // #if (BLE_42_SCAN_EN == TRUE) -#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleStopAdvertising -** -** Description This function set the random address for the APP -** -** Parameters void -** -** Returns void -** -** -*******************************************************************************/ -extern void BTA_DmBleStopAdvertising(void) -{ - BT_HDR *p_msg; - - APPL_TRACE_API("BTA_DmBleStopAdvertising\n"); - - if ((p_msg = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { - memset(p_msg, 0, sizeof(BT_HDR)); - p_msg->event = BTA_DM_API_BLE_STOP_ADV_EVT; - bta_sys_sendmsg(p_msg); - } -} -#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) - /******************************************************************************* ** ** Function BTA_DmSetRandAddress @@ -3169,6 +2418,217 @@ void BTA_DmBleGapSetHostFeature(uint16_t bit_num, uint8_t bit_val) } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +void BTA_DmBleGapSetPASubevtData(uint8_t adv_handle, uint8_t num_subevents_with_data, uint8_t *subevent_params) +{ + tBTA_DM_API_BLE_PA_SUBEVENT_DATA *p_msg; + tBTA_BLE_SUBEVENT_PARAMS *p_subevent_params = (tBTA_BLE_SUBEVENT_PARAMS*)subevent_params; + + if ((p_msg = (tBTA_DM_API_BLE_PA_SUBEVENT_DATA *)osi_malloc(sizeof(tBTA_DM_API_BLE_PA_SUBEVENT_DATA) + num_subevents_with_data * sizeof(tBTA_DM_API_BLE_SUBEVENT_PARAMS))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SET_PA_SUBEVT_DATA; + p_msg->adv_handle = adv_handle; + p_msg->num_subevents_with_data = num_subevents_with_data; + p_msg->subevent_params = (tBTA_DM_API_BLE_SUBEVENT_PARAMS *)(p_msg + 1); + for (uint8_t i = 0; i < num_subevents_with_data; i++) + { + p_msg->subevent_params[i].subevent = p_subevent_params[i].subevent; + p_msg->subevent_params[i].response_slot_start = p_subevent_params[i].response_slot_start; + p_msg->subevent_params[i].response_slot_count = p_subevent_params[i].response_slot_count; + p_msg->subevent_params[i].subevent_data_len = p_subevent_params[i].subevent_data_len; + memcpy(&(p_msg->subevent_params[i].subevent_data), p_subevent_params[i].subevent_data, p_subevent_params[i].subevent_data_len); + } + + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSetPeriodicAdvRspData(uint16_t sync_handle, uint16_t request_event, uint8_t request_subevent, + uint8_t rsp_subevent, uint8_t rsp_slot, uint8_t rsp_data_len, uint8_t *rsp_data) +{ + tBTA_DM_API_BLE_PA_RSP_DATA *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_PA_RSP_DATA *)osi_malloc(sizeof(tBTA_DM_API_BLE_PA_RSP_DATA) + rsp_data_len)) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SET_PA_RSP_DATA; + p_msg->sync_handle = sync_handle; + p_msg->request_event = request_event; + p_msg->request_subevent = request_subevent; + p_msg->rsp_subevent = rsp_subevent; + p_msg->rsp_slot = rsp_slot; + p_msg->rsp_data_len = rsp_data_len; + p_msg->rsp_data = (UINT8 *)(p_msg + 1); + if (rsp_data_len && rsp_data) { + memcpy(p_msg->rsp_data, rsp_data, rsp_data_len); + } else if (rsp_data_len) { + APPL_TRACE_ERROR("%s rsp_data is NULL", __func__); + } + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSetPeriodicSyncSubevt(uint16_t sync_handle, uint16_t periodic_adv_properties, uint8_t num_subevents_to_sync, uint8_t *subevent) +{ + tBTA_DM_API_BLE_PA_SYNC_SUBEVT *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_PA_SYNC_SUBEVT *)osi_malloc(sizeof(tBTA_DM_API_BLE_PA_SYNC_SUBEVT) + num_subevents_to_sync)) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SET_PA_SYNC_SUBEVT; + p_msg->sync_handle = sync_handle; + p_msg->periodic_adv_properties = periodic_adv_properties; + p_msg->num_subevents_to_sync = num_subevents_to_sync; + p_msg->subevent = (UINT8 *)(p_msg + 1); + if (num_subevents_to_sync && subevent) { + memcpy(p_msg->subevent, subevent, num_subevents_to_sync); + } else if (num_subevents_to_sync) { + APPL_TRACE_ERROR("%s subevent is NULL", __func__); + } + bta_sys_sendmsg(p_msg); + } +} + +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void BTA_DmBleGapReadLocalSupportedCaps(void) +{ + tBTA_DM_API_CS_READ_LOCAL_SUPP_CAPS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_READ_LOCAL_SUPP_CAPS *)osi_malloc(sizeof(tBTA_DM_API_CS_READ_LOCAL_SUPP_CAPS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_READ_LOCAL_SUPPORTED_CAPS; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapReadRemoteSupportedCaps(uint16_t conn_handle) +{ + tBTA_DM_API_CS_READ_REMOTE_SUPP_CAPS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_READ_REMOTE_SUPP_CAPS *)osi_malloc(sizeof(tBTA_DM_API_CS_READ_REMOTE_SUPP_CAPS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_READ_REMOTE_SUPPORTED_CAPS; + p_msg->conn_handle = conn_handle; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapWriteCachedRemoteSupportedCaps(tBTA_DM_CS_WRITE_CACHED_REMOTE_SUPP_CAPS *write_cachedremote_supp_caps) +{ + tBTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPP_CAPS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPP_CAPS *)osi_malloc(sizeof(tBTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPP_CAPS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPS; + memcpy(&p_msg->conn_handle, &write_cachedremote_supp_caps->conn_handle, sizeof(tBTA_DM_CS_WRITE_CACHED_REMOTE_SUPP_CAPS)); + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapCsSecurityEnable(uint16_t conn_handle) +{ + tBTA_DM_API_CS_SECURITY_ENABLE *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_SECURITY_ENABLE *)osi_malloc(sizeof(tBTA_DM_API_CS_SECURITY_ENABLE))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_SECURITY_ENABLE; + p_msg->conn_handle = conn_handle; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapCsSetDefaultSetting(uint16_t conn_handle, uint8_t role_enable, uint8_t cs_sync_ant_selection, int8_t max_tx_power) +{ + tBTA_DM_API_CS_SET_DEFAULT_SETTING_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_SET_DEFAULT_SETTING_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_CS_SET_DEFAULT_SETTING_PARAMS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_SET_DEFAULT_SETTINGS; + p_msg->conn_handle = conn_handle; + p_msg->role_enable = role_enable; + p_msg->cs_sync_ant_selection = cs_sync_ant_selection; + p_msg->max_tx_power = max_tx_power; + bta_sys_sendmsg(p_msg); + } +} +void BTA_DmBleGapCsReadRemoteFaeTable(uint16_t conn_handle) +{ + tBTA_DM_API_CS_READ_REMOTE_TAB *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_READ_REMOTE_TAB *)osi_malloc(sizeof(tBTA_DM_API_CS_READ_REMOTE_TAB))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_READ_REMOTE_FAE_TABLE; + p_msg->conn_handle = conn_handle; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapWriteCachedRemoteFaeTable(uint16_t conn_handle, uint8_t *remote_fae_table, uint8_t table_len) +{ + tBTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TABLE; + p_msg->conn_handle = conn_handle; + memcpy(&p_msg->remote_fae_table[0], remote_fae_table, table_len); + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapCsCreateConfig(tBTA_DM_CS_CREATE_CONFIG_PARAMS *create_config_params) +{ + tBTA_DM_API_CS_CREATE_CONFIG_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_CREATE_CONFIG_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_CS_CREATE_CONFIG_PARAMS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_CREATE_CONFIG; + memcpy(&p_msg->conn_handle, &create_config_params->conn_handle, sizeof(tBTA_DM_CS_CREATE_CONFIG_PARAMS)); + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapCsRemoveConfig(uint16_t conn_handle, uint8_t config_id) +{ + tBTA_DM_API_CS_REMOVE_CONFIG_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_REMOVE_CONFIG_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_CS_REMOVE_CONFIG_PARAMS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_REMOVE_CONFIG; + p_msg->conn_handle = conn_handle; + p_msg->config_id = config_id; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapCsSetChannelClass(uint8_t *channel_class, uint8_t channl_len) +{ + tBTA_DM_API_CS_SET_CHANNEL_CLASS_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_SET_CHANNEL_CLASS_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_CS_SET_CHANNEL_CLASS_PARAMS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_SET_CAHNNEL_CLASSIFICATION; + memcpy(&p_msg->channel_class[0], channel_class, channl_len); + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapCsSetProcPatams(tBTA_DM_CS_SET_PROC_PARAMS *set_proc_params) +{ + tBTA_DM_API_CS_SET_PROC_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_SET_PROC_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_CS_SET_PROC_PARAMS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_SET_PROCEDURE_PARAMS; + memcpy(&p_msg->conn_handle, &set_proc_params->conn_handle, sizeof(tBTA_DM_CS_SET_PROC_PARAMS)); + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapCsProcEnable(uint16_t conn_handle, uint8_t config_id, uint8_t enable) +{ + tBTA_DM_API_CS_PROC_ENABLE_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_CS_PROC_ENABLE_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_CS_PROC_ENABLE_PARAMS))) != NULL) { + p_msg->hdr.event = BTA_DM_API_CS_PROCEDURE_ENABLE; + p_msg->conn_handle = conn_handle; + p_msg->config_id = config_id; + p_msg->enable = enable; + bta_sys_sendmsg(p_msg); + } +} + +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + /******************************************************************************* ** ** Function BTA_VendorInit @@ -3183,38 +2643,6 @@ void BTA_VendorInit (void) APPL_TRACE_API("BTA_VendorInit"); } -/******************************************************************************* -** -** Function BTA_VendorCleanup -** -** Description This function frees up Broadcom specific VS specific dynamic memory -** -** Returns void -** -*******************************************************************************/ -void BTA_VendorCleanup (void) -{ - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - -#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE) - btm_ble_adv_filter_cleanup(); // when BLE_VND_INCLUDED is false, this function will be ignore, so move it out of "if" - -#if 0 //by TH, comment out temporarily - if (cmn_ble_vsc_cb.max_filter > 0) { - btm_ble_adv_filter_cleanup(); -#if BLE_PRIVACY_SPT == TRUE - btm_ble_resolving_list_cleanup (); -#endif - } -#endif - - if (cmn_ble_vsc_cb.tot_scan_results_strg > 0) { - btm_ble_batchscan_cleanup(); - } -#endif - -} #if (BLE_50_FEATURE_SUPPORT == TRUE) void BTA_DmBleGapReadPHY(BD_ADDR addr) { diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c index 9fe5e7696e..6d86d41be3 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -42,11 +42,15 @@ #if BTA_DYNAMIC_MEMORY == FALSE tBTA_DM_CB bta_dm_cb; tBTA_DM_SEARCH_CB bta_dm_search_cb; +#if (CLASSIC_BT_INCLUDED == TRUE) tBTA_DM_DI_CB bta_dm_di_cb; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #else tBTA_DM_CB *bta_dm_cb_ptr; tBTA_DM_SEARCH_CB *bta_dm_search_cb_ptr; -tBTA_DM_DI_CB *bta_dm_di_cb_ptr; +#if (CLASSIC_BT_INCLUDED == TRUE) + tBTA_DM_DI_CB *bta_dm_di_cb_ptr; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) SemaphoreHandle_t deinit_semaphore; #endif @@ -90,9 +94,6 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { #endif // #if (CLASSIC_BT_INCLUDED == TRUE) bta_dm_acl_change, /* BTA_DM_ACL_CHANGE_EVT */ bta_dm_add_device, /* BTA_DM_API_ADD_DEVICE_EVT */ -#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) - bta_dm_close_acl, /* BTA_DM_API_REMOVE_ACL_EVT */ -#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) #if (SMP_INCLUDED == TRUE) /* security API events */ bta_dm_bond, /* BTA_DM_API_BOND_EVT */ @@ -134,42 +135,28 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_ble_passkey_reply, /* BTA_DM_API_BLE_PASSKEY_REPLY_EVT */ bta_dm_ble_set_static_passkey, /* BTA_DM_API_BLE_SET_STATIC_PASSKEY_EVT */ bta_dm_ble_confirm_reply, /* BTA_DM_API_BLE_CONFIRM_REPLY_EVT */ - bta_dm_security_grant, + bta_dm_security_grant, /* BTA_DM_API_BLE_SEC_GRANT_EVT */ #endif ///SMP_INCLUDED == TRUE - bta_dm_ble_set_bg_conn_type, +#if (BLE_GATT_BGCONN == TRUE) + bta_dm_ble_set_bg_conn_type, /* BTA_DM_API_BLE_SET_BG_CONN_TYPE */ +#endif // (BLE_GATT_BGCONN == TRUE) bta_dm_ble_set_conn_params, /* BTA_DM_API_BLE_CONN_PARAM_EVT */ -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) - bta_dm_ble_set_conn_scan_params, /* BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT */ -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) - bta_dm_ble_set_scan_params, /* BTA_DM_API_BLE_SCAN_PARAM_EVT */ -#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) #if (BLE_42_SCAN_EN == TRUE) bta_dm_ble_set_scan_fil_params, /* BTA_DM_API_BLE_SCAN_FIL_PARAM_EVT */ #endif // #if (BLE_42_SCAN_EN == TRUE) -#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) - bta_dm_ble_observe, /* BTA_DM_API_BLE_OBSERVE_EVT */ -#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) #if (BLE_42_SCAN_EN == TRUE) bta_dm_ble_scan, /* BTA_DM_API_BLE_SCAN_EVT */ #endif // #if (BLE_42_SCAN_EN == TRUE) bta_dm_ble_update_conn_params, /* BTA_DM_API_UPDATE_CONN_PARAM_EVT */ - /* This handler function added by - Yulong at 2016/9/9 to support the - random address setting for the APP */ bta_dm_ble_set_rand_address, /* BTA_DM_API_SET_RAND_ADDR_EVT*/ bta_dm_ble_clear_rand_address, /* BTA_DM_API_CLEAR_RAND_ADDR_EVT */ - /* This handler function added by - Yulong at 2016/10/19 to support - stop the ble advertising setting - by the APP */ -#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) - bta_dm_ble_stop_advertising, /* BTA_DM_API_BLE_STOP_ADV_EVT */ -#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) #if BLE_PRIVACY_SPT == TRUE bta_dm_ble_config_local_privacy, /* BTA_DM_API_LOCAL_PRIVACY_EVT */ #endif bta_dm_ble_config_local_icon, /* BTA_DM_API_LOCAL_ICON_EVT */ +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + bta_dm_ble_set_key_material, /* BTA_DM_API_KEY_MATERIAL_EVT */ +#endif #if (BLE_42_ADV_EN == TRUE) bta_dm_ble_set_adv_params_all, /* BTA_DM_API_BLE_ADV_PARAM_All_EVT */ bta_dm_ble_set_adv_config, /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */ @@ -180,58 +167,20 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { /* New function to allow set raw scan response data to HCI */ bta_dm_ble_set_scan_rsp_raw, /* BTA_DM_API_BLE_SET_SCAN_RSP_RAW_EVT */ - bta_dm_ble_broadcast, /* BTA_DM_API_BLE_BROADCAST_EVT */ + bta_dm_ble_advstop, /* BTA_DM_API_BLE_ADVSTOP_EVT */ #endif // #if (BLE_42_ADV_EN == TRUE) bta_dm_ble_set_data_length, /* BTA_DM_API_SET_DATA_LENGTH_EVT */ -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE - bta_dm_cfg_filter_cond, /* BTA_DM_API_CFG_FILTER_COND_EVT */ - bta_dm_scan_filter_param_setup, /* BTA_DM_API_SCAN_FILTER_SETUP_EVT */ - bta_dm_enable_scan_filter, /* BTA_DM_API_SCAN_FILTER_ENABLE_EVT */ -#endif -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - bta_dm_ble_multi_adv_enb, /* BTA_DM_API_BLE_MULTI_ADV_ENB_EVT */ - bta_dm_ble_multi_adv_upd_param, /* BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT */ - bta_dm_ble_multi_adv_data, /* BTA_DM_API_BLE_MULTI_ADV_DATA_EVT */ - btm_dm_ble_multi_adv_disable, /* BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT */ -#endif // BLE_HOST_BLE_MULTI_ADV_EN -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) - bta_dm_ble_setup_storage, /* BTA_DM_API_BLE_SETUP_STORAGE_EVT */ -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) - bta_dm_ble_enable_batch_scan, /* BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT */ - bta_dm_ble_disable_batch_scan, /* BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT */ -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - bta_dm_ble_read_scan_reports, /* BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT */ -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - bta_dm_ble_track_advertiser, /* BTA_DM_API_BLE_TRACK_ADVERTISER_EVT */ -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) - bta_dm_ble_get_energy_info, /* BTA_DM_API_BLE_ENERGY_INFO_EVT */ -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) bta_dm_ble_disconnect, /* BTA_DM_API_BLE_DISCONNECT_EVT */ #endif -#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) - bta_dm_enable_test_mode, /* BTA_DM_API_ENABLE_TEST_MODE_EVT */ - bta_dm_disable_test_mode, /* BTA_DM_API_DISABLE_TEST_MODE_EVT */ -#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) -#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) - bta_dm_execute_callback, /* BTA_DM_API_EXECUTE_CBACK_EVT */ -#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) -#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) - bta_dm_remove_all_acl, /* BTA_DM_API_REMOVE_ALL_ACL_EVT */ -#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) bta_dm_remove_device, /* BTA_DM_API_REMOVE_DEVICE_EVT */ bta_dm_ble_set_channels, /* BTA_DM_API_BLE_SET_CHANNELS_EVT */ bta_dm_update_white_list, /* BTA_DM_API_UPDATE_WHITE_LIST_EVT */ bta_dm_clear_white_list, /* BTA_DM_API_CLEAR_WHITE_LIST_EVT */ -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) - bta_dm_ble_read_adv_tx_power, /* BTA_DM_API_BLE_READ_ADV_TX_POWER_EVT */ -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) bta_dm_read_rssi, /* BTA_DM_API_READ_RSSI_EVT */ #if BLE_INCLUDED == TRUE +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) bta_dm_ble_update_duplicate_exceptional_list,/* BTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_EVT */ +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) #endif #if (BLE_50_FEATURE_SUPPORT == TRUE) bta_dm_ble_gap_read_phy, /* BTA_DM_API_READ_PHY_EVT */ @@ -344,6 +293,25 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { #if (BLE_50_FEATURE_SUPPORT == TRUE) bta_dm_ble_set_host_feature, /* BTA_DM_API_SET_HOST_FEATURE_EVT */ #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + bta_dm_api_set_periodic_adv_subevt_data, /* BTA_DM_API_SET_PA_SUBEVT_DATA */ + bta_dm_api_set_periodic_adv_response_data, /* BTA_DM_API_SET_PA_RSP_DATA */ + bta_dm_api_set_periodic_sync_subevt, /* BTA_DM_API_SET_PA_SYNC_SUBEVT */ +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + bta_dm_api_cs_read_local_supported_caps, /* BTA_DM_API_CS_READ_LOCAL_SUPPORTED_CAPS */ + bta_dm_api_cs_read_remote_supported_caps, /* BTA_DM_API_CS_READ_REMOTE_SUPPORTED_CAPS */ + bta_dm_api_cs_write_cached_remote_supported_caps, /* BTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPS */ + bta_dm_api_cs_security_enable, /* BTA_DM_API_CS_SECURITY_ENABLE */ + bta_dm_api_cs_set_default_settings, /* BTA_DM_API_CS_SET_DEFAULT_SETTINGS */ + bta_dm_api_cs_read_remote_fae_table, /* BTA_DM_API_CS_READ_REMOTE_FAE_TABLE */ + bta_dm_api_cs_write_cached_remote_fae_table, /* BTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TABLE */ + bta_dm_api_cs_create_config, /* BTA_DM_API_CS_CREATE_CONFIG */ + bta_dm_api_cs_remove_config, /* BTA_DM_API_CS_REMOVE_CONFIG */ + bta_dm_api_cs_set_channel_classification, /* BTA_DM_API_CS_SET_CAHNNEL_CLASSIFICATION */ + bta_dm_api_cs_set_procedure_params, /* BTA_DM_API_CS_SET_PROCEDURE_PARAMS */ + bta_dm_api_cs_procedure_enable, /* BTA_DM_API_CS_PROCEDURE_ENABLE */ +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) }; @@ -550,11 +518,15 @@ void bta_dm_sm_deinit(void) { memset(&bta_dm_cb, 0, sizeof(tBTA_DM_CB)); memset(&bta_dm_search_cb, 0, sizeof(tBTA_DM_SEARCH_CB)); +#if (CLASSIC_BT_INCLUDED == TRUE) memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB)); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if BTA_DYNAMIC_MEMORY FREE_AND_RESET(bta_dm_cb_ptr); FREE_AND_RESET(bta_dm_search_cb_ptr); +#if (CLASSIC_BT_INCLUDED == TRUE) FREE_AND_RESET(bta_dm_di_cb_ptr); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif /* #if BTA_DYNAMIC_MEMORY */ } diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_pm.c b/components/bt/host/bluedroid/bta/dm/bta_dm_pm.c index 8167ddf9a6..35727779ee 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_pm.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_pm.c @@ -32,6 +32,8 @@ #include "stack/btm_api.h" #include "osi/allocator.h" +#if (CLASSIC_BT_INCLUDED == TRUE) + #if BTA_DYNAMIC_MEMORY == FALSE tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs; #else @@ -1171,3 +1173,5 @@ tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void) } #endif + +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index e724b37c3a..f4498b54da 100644 --- a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h @@ -80,9 +80,6 @@ enum { BTA_DM_ACL_CHANGE_EVT, BTA_DM_API_ADD_DEVICE_EVT, -#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) - BTA_DM_API_REMOVE_ACL_EVT, -#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) #if (SMP_INCLUDED == TRUE) /* security API events */ BTA_DM_API_BOND_EVT, @@ -126,22 +123,15 @@ enum { BTA_DM_API_BLE_CONFIRM_REPLY_EVT, BTA_DM_API_BLE_SEC_GRANT_EVT, #endif ///SMP_INCLUDED == TRUE +#if (BLE_GATT_BGCONN == TRUE) BTA_DM_API_BLE_SET_BG_CONN_TYPE, +#endif // (BLE_GATT_BGCONN == TRUE) BTA_DM_API_BLE_CONN_PARAM_EVT, -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) - BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT, -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) - BTA_DM_API_BLE_SCAN_PARAM_EVT, -#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) /*******This event added by Yulong at 2016/10/25 to support the scan filter setting for the APP******/ #if (BLE_42_SCAN_EN == TRUE) BTA_DM_API_BLE_SCAN_FIL_PARAM_EVT, #endif // #if (BLE_42_SCAN_EN == TRUE) -#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) - BTA_DM_API_BLE_OBSERVE_EVT, -#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) #if (BLE_42_SCAN_EN == TRUE) BTA_DM_API_BLE_SCAN_EVT, #endif // #if (BLE_42_SCAN_EN == TRUE) @@ -150,15 +140,13 @@ enum { support the random address setting for the APP******/ BTA_DM_API_SET_RAND_ADDR_EVT, BTA_DM_API_CLEAR_RAND_ADDR_EVT, - /*******This event added by Yulong at 2016/10/19 to - support stop the ble advertising setting by the APP******/ -#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) - BTA_DM_API_BLE_STOP_ADV_EVT, -#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) #if BLE_PRIVACY_SPT == TRUE BTA_DM_API_LOCAL_PRIVACY_EVT, #endif BTA_DM_API_LOCAL_ICON_EVT, +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + BTA_DM_API_KEY_MATERIAL_EVT, +#endif /*******This event added by Yulong at 2016/10/20 to support setting the ble advertising param by the APP******/ @@ -170,59 +158,22 @@ enum { BTA_DM_API_BLE_SET_SCAN_RSP_EVT, /* Add for set raw scan response data */ BTA_DM_API_BLE_SET_SCAN_RSP_RAW_EVT, - BTA_DM_API_BLE_BROADCAST_EVT, + BTA_DM_API_BLE_ADVSTOP_EVT, #endif // #if (BLE_42_ADV_EN == TRUE) BTA_DM_API_SET_DATA_LENGTH_EVT, -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE - BTA_DM_API_CFG_FILTER_COND_EVT, - BTA_DM_API_SCAN_FILTER_SETUP_EVT, - BTA_DM_API_SCAN_FILTER_ENABLE_EVT, -#endif -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - BTA_DM_API_BLE_MULTI_ADV_ENB_EVT, - BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT, - BTA_DM_API_BLE_MULTI_ADV_DATA_EVT, - BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT, -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) - BTA_DM_API_BLE_SETUP_STORAGE_EVT, -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) - BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT, - BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT, -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT, -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - BTA_DM_API_BLE_TRACK_ADVERTISER_EVT, -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) - BTA_DM_API_BLE_ENERGY_INFO_EVT, -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) + BTA_DM_API_BLE_DISCONNECT_EVT, #endif -#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) - BTA_DM_API_ENABLE_TEST_MODE_EVT, - BTA_DM_API_DISABLE_TEST_MODE_EVT, -#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) -#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) - BTA_DM_API_EXECUTE_CBACK_EVT, -#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) -#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) - BTA_DM_API_REMOVE_ALL_ACL_EVT, -#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) BTA_DM_API_REMOVE_DEVICE_EVT, BTA_DM_API_BLE_SET_CHANNELS_EVT, BTA_DM_API_UPDATE_WHITE_LIST_EVT, BTA_DM_API_CLEAR_WHITE_LIST_EVT, -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) - BTA_DM_API_BLE_READ_ADV_TX_POWER_EVT, -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) BTA_DM_API_READ_RSSI_EVT, #if BLE_INCLUDED == TRUE +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) BTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_EVT, +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) #endif #if (BLE_50_FEATURE_SUPPORT == TRUE) BTA_DM_API_READ_PHY_EVT, @@ -335,6 +286,25 @@ enum { #if (BLE_50_FEATURE_SUPPORT == TRUE) BTA_DM_API_SET_HOST_FEATURE_EVT, #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + BTA_DM_API_SET_PA_SUBEVT_DATA, + BTA_DM_API_SET_PA_RSP_DATA, + BTA_DM_API_SET_PA_SYNC_SUBEVT, +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + BTA_DM_API_CS_READ_LOCAL_SUPPORTED_CAPS, + BTA_DM_API_CS_READ_REMOTE_SUPPORTED_CAPS, + BTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPS, + BTA_DM_API_CS_SECURITY_ENABLE, + BTA_DM_API_CS_SET_DEFAULT_SETTINGS, + BTA_DM_API_CS_READ_REMOTE_FAE_TABLE, + BTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TABLE, + BTA_DM_API_CS_CREATE_CONFIG, + BTA_DM_API_CS_REMOVE_CONFIG, + BTA_DM_API_CS_SET_CAHNNEL_CLASSIFICATION, + BTA_DM_API_CS_SET_PROCEDURE_PARAMS, + BTA_DM_API_CS_PROCEDURE_ENABLE, +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) BTA_DM_MAX_EVT }; @@ -467,6 +437,7 @@ typedef struct { tBTA_UPDATE_WHITELIST_CBACK *update_wl_cb; }tBTA_DM_API_UPDATE_WHITE_LIST; +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) typedef struct { BT_HDR hdr; UINT8 subcode; @@ -474,13 +445,7 @@ typedef struct { BD_ADDR device_info; tBTA_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK *exceptional_list_cb; }tBTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST; - -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -typedef struct { - BT_HDR hdr; - tBTA_CMPL_CB *read_tx_power_cb; -}tBTA_DM_API_READ_ADV_TX_POWER; -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) #endif ///BLE_INCLUDED == TRUE @@ -743,15 +708,6 @@ typedef struct { UINT8 transport; } tBTA_DM_API_REMOVE_DEVICE; -#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) -/* data type for BTA_DM_API_EXECUTE_CBACK_EVT */ -typedef struct { - BT_HDR hdr; - void *p_param; - tBTA_DM_EXEC_CBACK *p_exec_cback; -} tBTA_DM_API_EXECUTE_CBACK; -#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) - /* data type for tBTA_DM_API_SET_ENCRYPTION */ typedef struct { BT_HDR hdr; @@ -834,6 +790,14 @@ typedef struct { uint16_t icon; } tBTA_DM_API_LOCAL_ICON; +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +typedef struct { + BT_HDR hdr; + uint8_t session_key[16]; + uint8_t iv[8]; +} tBTA_DM_API_KEY_MATERIAL; +#endif + /* set scan parameter for BLE connections */ typedef struct { BT_HDR hdr; @@ -856,15 +820,6 @@ typedef struct { tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback; } tBTA_DM_API_BLE_SCAN_FILTER_PARAMS; -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -/* set scan parameter for BLE connections */ -typedef struct { - BT_HDR hdr; - UINT16 scan_int; - UINT16 scan_window; -} tBTA_DM_API_BLE_CONN_SCAN_PARAMS; -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) - /* Data type for start/stop observe */ typedef struct { BT_HDR hdr; @@ -941,35 +896,6 @@ typedef struct { } tBTA_DM_API_BLE_FEATURE; -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -/* multi adv data structure */ -typedef struct { - BT_HDR hdr; - tBTA_BLE_MULTI_ADV_CBACK *p_cback; - void *p_ref; - tBTA_BLE_ADV_PARAMS *p_params; -} tBTA_DM_API_BLE_MULTI_ADV_ENB; - -typedef struct { - BT_HDR hdr; - UINT8 inst_id; - tBTA_BLE_ADV_PARAMS *p_params; -} tBTA_DM_API_BLE_MULTI_ADV_PARAM; - -typedef struct { - BT_HDR hdr; - UINT8 inst_id; - BOOLEAN is_scan_rsp; - tBTA_BLE_AD_MASK data_mask; - tBTA_BLE_ADV_DATA *p_data; -} tBTA_DM_API_BLE_MULTI_ADV_DATA; - -typedef struct { - BT_HDR hdr; - UINT8 inst_id; -} tBTA_DM_API_BLE_MULTI_ADV_DISABLE; -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - typedef struct { BT_HDR hdr; UINT32 data_mask; @@ -986,59 +912,6 @@ typedef struct { tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback; } tBTA_DM_API_SET_ADV_CONFIG_RAW; -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -typedef struct { - BT_HDR hdr; - UINT8 batch_scan_full_max; - UINT8 batch_scan_trunc_max; - UINT8 batch_scan_notify_threshold; - tBTA_BLE_SCAN_SETUP_CBACK *p_setup_cback; - tBTA_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback; - tBTA_BLE_SCAN_REP_CBACK *p_read_rep_cback; - tBTA_DM_BLE_REF_VALUE ref_value; -} tBTA_DM_API_SET_STORAGE_CONFIG; -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) - -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) -typedef struct { - BT_HDR hdr; - tBTA_BLE_BATCH_SCAN_MODE scan_mode; - UINT32 scan_int; - UINT32 scan_window; - tBTA_BLE_DISCARD_RULE discard_rule; - tBLE_ADDR_TYPE addr_type; - tBTA_DM_BLE_REF_VALUE ref_value; -} tBTA_DM_API_ENABLE_SCAN; - -typedef struct { - BT_HDR hdr; - tBTA_DM_BLE_REF_VALUE ref_value; -} tBTA_DM_API_DISABLE_SCAN; -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) - -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -typedef struct { - BT_HDR hdr; - tBTA_BLE_BATCH_SCAN_MODE scan_type; - tBTA_DM_BLE_REF_VALUE ref_value; -} tBTA_DM_API_READ_SCAN_REPORTS; -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -typedef struct { - BT_HDR hdr; - tBTA_DM_BLE_REF_VALUE ref_value; - tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback; -} tBTA_DM_API_TRACK_ADVERTISER; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) -typedef struct { - BT_HDR hdr; - tBTA_BLE_ENERGY_INFO_CBACK *p_energy_info_cback; -} tBTA_DM_API_ENERGY_INFO; -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) - typedef struct { BT_HDR hdr; BD_ADDR remote_bda; @@ -1156,28 +1029,169 @@ typedef struct { } tBTA_DM_API_SET_HOST_FEATURE; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + +typedef struct { + UINT8 subevent; + UINT8 response_slot_start; + UINT8 response_slot_count; + UINT8 subevent_data_len; + UINT8 *subevent_data; +} tBTA_BLE_SUBEVENT_PARAMS; + +typedef struct { + UINT8 subevent; + UINT8 response_slot_start; + UINT8 response_slot_count; + UINT8 subevent_data_len; + UINT8 subevent_data[251]; +} tBTA_DM_API_BLE_SUBEVENT_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT8 adv_handle; + UINT8 num_subevents_with_data; + tBTA_DM_API_BLE_SUBEVENT_PARAMS *subevent_params; +} tBTA_DM_API_BLE_PA_SUBEVENT_DATA; + +typedef struct { + BT_HDR hdr; + UINT16 sync_handle; + UINT16 request_event; + UINT8 request_subevent; + UINT8 rsp_subevent; + UINT8 rsp_slot; + UINT8 rsp_data_len; + UINT8 *rsp_data; +} tBTA_DM_API_BLE_PA_RSP_DATA; + +typedef struct { + BT_HDR hdr; + UINT16 sync_handle; + UINT16 periodic_adv_properties; + UINT8 num_subevents_to_sync; + UINT8 *subevent; +} tBTA_DM_API_BLE_PA_SYNC_SUBEVT; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +typedef struct { + BT_HDR hdr; +} tBTA_DM_API_CS_READ_LOCAL_SUPP_CAPS; +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; +} tBTA_DM_API_CS_READ_REMOTE_SUPP_CAPS; +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 num_config_supported; + UINT16 max_consecutive_proc_supported; + UINT8 num_ant_supported; + UINT8 max_ant_paths_supported; + UINT8 roles_supported; + UINT8 modes_supported; + UINT8 rtt_capability; + UINT8 rtt_aa_only_n; + UINT8 rtt_sounding_n; + UINT8 rtt_random_payload_n; + UINT16 NADM_sounding_capability; + UINT16 NADM_random_capability; + UINT8 cs_sync_phys_supported; + UINT16 subfeatures_supported; + UINT16 T_IP1_times_supported; + UINT16 T_IP2_times_supported; + UINT16 T_FCS_times_supported; + UINT16 T_PM_times_supported; + UINT8 T_SW_times_supported; + UINT8 TX_SNR_capability; +} tBTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPP_CAPS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; +} tBTA_DM_API_CS_SECURITY_ENABLE; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 role_enable; + UINT8 cs_sync_ant_selection; + INT8 max_tx_power; +} tBTA_DM_API_CS_SET_DEFAULT_SETTING_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; +} tBTA_DM_API_CS_READ_REMOTE_TAB; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 remote_fae_table[72]; +} tBTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 config_id; + UINT8 create_context; + UINT8 main_mode_type; + UINT8 sub_mode_type; + UINT8 min_main_mode_steps; + UINT8 max_main_mode_steps; + UINT8 main_mode_repetition; + UINT8 mode_0_steps; + UINT8 role; + UINT8 rtt_type; + UINT8 cs_sync_phy; + UINT8 channel_map[10]; + UINT8 channel_map_repetition; + UINT8 channel_selection_type; + UINT8 ch3c_shape; + UINT8 ch3c_jump; + UINT8 reserved; +} tBTA_DM_API_CS_CREATE_CONFIG_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 config_id; +} tBTA_DM_API_CS_REMOVE_CONFIG_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT8 channel_class[10]; +} tBTA_DM_API_CS_SET_CHANNEL_CLASS_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 config_id; + UINT16 max_procedure_len; + UINT16 min_procedure_interval; + UINT16 max_procedure_interval; + UINT16 max_procedure_count; + UINT32 min_subevent_len; + UINT32 max_subevent_len; + UINT8 tone_ant_config_selection; + UINT8 phy; + UINT8 tx_power_delta; + UINT8 preferred_peer_antenna; + UINT8 SNR_control_initiator; + UINT8 SNR_control_reflector; +} tBTA_DM_API_CS_SET_PROC_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 config_id; + UINT8 enable; +} tBTA_DM_API_CS_PROC_ENABLE_PARAMS; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + #endif /* BLE_INCLUDED */ -#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) -/* data type for BTA_DM_API_REMOVE_ACL_EVT */ -typedef struct { - BT_HDR hdr; - BD_ADDR bd_addr; - BOOLEAN remove_dev; - tBTA_TRANSPORT transport; - -} tBTA_DM_API_REMOVE_ACL; -#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) - -#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) -/* data type for BTA_DM_API_REMOVE_ALL_ACL_EVT */ -typedef struct { - BT_HDR hdr; - tBTA_DM_LINK_TYPE link_type; - -} tBTA_DM_API_REMOVE_ALL_ACL; -#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) - typedef struct { BT_HDR hdr; BD_ADDR bd_addr; @@ -1187,35 +1201,6 @@ typedef struct { UINT16 timeout; } tBTA_DM_API_UPDATE_CONN_PARAM; -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE -typedef struct { - BT_HDR hdr; - tBTA_DM_BLE_SCAN_COND_OP action; - tBTA_DM_BLE_PF_COND_TYPE cond_type; - tBTA_DM_BLE_PF_FILT_INDEX filt_index; - tBTA_DM_BLE_PF_COND_PARAM *p_cond_param; - tBTA_DM_BLE_PF_CFG_CBACK *p_filt_cfg_cback; - tBTA_DM_BLE_REF_VALUE ref_value; -} tBTA_DM_API_CFG_FILTER_COND; - -typedef struct { - BT_HDR hdr; - UINT8 action; - tBTA_DM_BLE_PF_STATUS_CBACK *p_filt_status_cback; - tBTA_DM_BLE_REF_VALUE ref_value; -} tBTA_DM_API_ENABLE_SCAN_FILTER; - -typedef struct { - BT_HDR hdr; - UINT8 action; - tBTA_DM_BLE_PF_FILT_INDEX filt_index; - tBTA_DM_BLE_PF_FILT_PARAMS filt_params; - tBLE_BD_ADDR *p_target; - tBTA_DM_BLE_PF_PARAM_CBACK *p_filt_param_cback; - tBTA_DM_BLE_REF_VALUE ref_value; -} tBTA_DM_API_SCAN_FILTER_PARAM_SETUP; -#endif - #if (BLE_50_DTM_TEST_EN == TRUE) typedef struct { BT_HDR hdr; @@ -1624,12 +1609,14 @@ typedef union { tBTA_DM_API_CFG_COEX_STATUS cfg_coex_status; #endif tBTA_DM_API_SEND_VENDOR_HCI_CMD vendor_hci_cmd; +#if CLASSIC_BT_INCLUDED tBTA_DM_API_CONFIG_EIR config_eir; tBTA_DM_API_SET_AFH_CHANNELS set_afh_channels; tBTA_DM_API_PAGE_TO_SET set_page_timeout; tBTA_DM_API_PAGE_TO_GET get_page_timeout; tBTA_DM_API_SET_ACL_PKT_TYPES set_acl_pkt_types; +#endif /* CLASSIC_BT_INCLUDED */ #if (ENC_KEY_SIZE_CTRL_MODE != ENC_KEY_SIZE_CTRL_MODE_NONE) tBTA_DM_API_SET_MIN_ENC_KEY_SIZE set_min_enc_key_size; #endif @@ -1640,9 +1627,6 @@ typedef union { #if (BLE_INCLUDED == TRUE) tBTA_DM_API_BLE_SET_CHANNELS ble_set_channels; tBTA_DM_API_UPDATE_WHITE_LIST white_list; -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) - tBTA_DM_API_READ_ADV_TX_POWER read_tx_power; -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) #endif ///BLE_INCLUDED == TRUE tBTA_DM_API_READ_RSSI rssi; @@ -1695,9 +1679,6 @@ typedef union { #endif /* #if (BTA_DM_QOS_INCLUDED == TRUE) */ tBTA_DM_API_DI_DISC di_disc; -#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) - tBTA_DM_API_EXECUTE_CBACK exec_cback; -#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) tBTA_DM_API_SET_ENCRYPTION set_encryption; #if BLE_INCLUDED == TRUE @@ -1708,59 +1689,28 @@ typedef union { tBTA_DM_API_BLE_SEC_GRANT ble_sec_grant; tBTA_DM_API_BLE_SET_BG_CONN_TYPE ble_set_bd_conn_type; tBTA_DM_API_BLE_CONN_PARAMS ble_set_conn_params; -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) - tBTA_DM_API_BLE_CONN_SCAN_PARAMS ble_set_conn_scan_params; -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) - tBTA_DM_API_BLE_SCAN_PARAMS ble_set_scan_params; -#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) tBTA_DM_API_BLE_SCAN_FILTER_PARAMS ble_set_scan_fil_params; tBTA_DM_API_BLE_OBSERVE ble_observe; tBTA_DM_API_BLE_SCAN ble_scan; tBTA_DM_API_ENABLE_PRIVACY ble_remote_privacy; tBTA_DM_API_LOCAL_PRIVACY ble_local_privacy; tBTA_DM_API_LOCAL_ICON ble_local_icon; +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + tBTA_DM_API_KEY_MATERIAL ble_key_material; +#endif tBTA_DM_API_BLE_ADV_PARAMS_ALL ble_set_adv_params_all; tBTA_DM_API_SET_ADV_CONFIG ble_set_adv_data; tBTA_DM_API_SET_ADV_CONFIG_RAW ble_set_adv_data_raw; -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE - tBTA_DM_API_SCAN_FILTER_PARAM_SETUP ble_scan_filt_param_setup; - tBTA_DM_API_CFG_FILTER_COND ble_cfg_filter_cond; - tBTA_DM_API_ENABLE_SCAN_FILTER ble_enable_scan_filt; -#endif tBTA_DM_API_UPDATE_CONN_PARAM ble_update_conn_params; tBTA_DM_API_BLE_SET_DATA_LENGTH ble_set_data_length; tBTA_DM_APT_SET_DEV_ADDR set_addr; tBTA_DM_APT_CLEAR_ADDR clear_addr; tBTA_DM_API_SET_RPA_TIMEOUT set_rpa_timeout; tBTA_DM_API_ADD_DEV_TO_RESOLVING_LIST add_dev_to_resolving_list; - -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - tBTA_DM_API_BLE_MULTI_ADV_ENB ble_multi_adv_enb; - tBTA_DM_API_BLE_MULTI_ADV_PARAM ble_multi_adv_param; - tBTA_DM_API_BLE_MULTI_ADV_DATA ble_multi_adv_data; - tBTA_DM_API_BLE_MULTI_ADV_DISABLE ble_multi_adv_disable; -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) - tBTA_DM_API_SET_STORAGE_CONFIG ble_set_storage; -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) - tBTA_DM_API_ENABLE_SCAN ble_enable_scan; -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - tBTA_DM_API_READ_SCAN_REPORTS ble_read_reports; -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) - tBTA_DM_API_DISABLE_SCAN ble_disable_scan; -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - tBTA_DM_API_TRACK_ADVERTISER ble_track_advert; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) - tBTA_DM_API_ENERGY_INFO ble_energy_info; -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) tBTA_DM_API_BLE_DISCONNECT ble_disconnect; +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) tBTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST ble_duplicate_exceptional_list; +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) #if (BLE_50_FEATURE_SUPPORT == TRUE) tBTA_DM_API_READ_PHY ble_read_phy; tBTA_DM_API_SET_PER_DEF_PHY ble_set_per_def_phy; @@ -1812,13 +1762,6 @@ typedef union { tBTA_DM_API_BLE_SET_CSA_SUPPORT ble_set_csa_support; tBTA_DM_API_BLE_SET_VENDOR_EVT_MASK ble_set_vendor_evt_mask; #endif -#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) - tBTA_DM_API_REMOVE_ACL remove_acl; -#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) -#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) - tBTA_DM_API_REMOVE_ALL_ACL remove_all_acl; -#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) - #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) tBTA_DM_API_BIG_CREATE big_creat; @@ -1876,6 +1819,25 @@ typedef union { #if (BLE_50_FEATURE_SUPPORT == TRUE) tBTA_DM_API_SET_HOST_FEATURE set_host_feat; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + tBTA_DM_API_BLE_PA_SUBEVENT_DATA pa_subevt_data; + tBTA_DM_API_BLE_PA_RSP_DATA pa_rsp_data; + tBTA_DM_API_BLE_PA_SYNC_SUBEVT pa_sync_subevt; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + tBTA_DM_API_CS_READ_LOCAL_SUPP_CAPS read_local_supp_caps; + tBTA_DM_API_CS_READ_REMOTE_SUPP_CAPS read_remote_supp_caps; + tBTA_DM_API_CS_WRITE_CACHED_REMOTE_SUPP_CAPS write_cached_remote_caps; + tBTA_DM_API_CS_SECURITY_ENABLE security_enable; + tBTA_DM_API_CS_SET_DEFAULT_SETTING_PARAMS set_default_setting_params; + tBTA_DM_API_CS_READ_REMOTE_TAB read_remote_tab; + tBTA_DM_API_CS_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS write_cached_remote_fae_tab_params; + tBTA_DM_API_CS_CREATE_CONFIG_PARAMS create_config_params; + tBTA_DM_API_CS_REMOVE_CONFIG_PARAMS remove_config_params; + tBTA_DM_API_CS_SET_CHANNEL_CLASS_PARAMS set_channel_class_params; + tBTA_DM_API_CS_SET_PROC_PARAMS set_proc_params; + tBTA_DM_API_CS_PROC_ENABLE_PARAMS proc_enable_params; +#endif } tBTA_DM_MSG; @@ -1984,24 +1946,9 @@ typedef struct { BOOLEAN is_bta_dm_active; tBTA_DM_ACTIVE_LINK device_list; tBTA_DM_SEC_CBACK *p_sec_cback; -#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) - tBTA_BLE_SCAN_SETUP_CBACK *p_setup_cback; - tBTA_DM_BLE_PF_CFG_CBACK *p_scan_filt_cfg_cback; - tBTA_DM_BLE_PF_STATUS_CBACK *p_scan_filt_status_cback; - tBTA_DM_BLE_PF_PARAM_CBACK *p_scan_filt_param_cback; -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - tBTA_BLE_MULTI_ADV_CBACK *p_multi_adv_cback; -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) - tBTA_BLE_ENERGY_INFO_CBACK *p_energy_info_cback; -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) -#endif UINT16 state; BOOLEAN disabling; TIMER_LIST_ENT disable_timer; - UINT32 wbt_sdp_handle; /* WIDCOMM Extensions SDP record handle */ - UINT8 wbt_scn; /* WIDCOMM Extensions SCN */ - UINT8 num_master_only; #if (BTA_DM_PM_INCLUDED == TRUE) UINT8 pm_id; tBTA_PM_TIMER pm_timer[BTA_DM_NUM_PM_TIMER]; @@ -2009,7 +1956,9 @@ typedef struct { UINT32 role_policy_mask; /* the bits set indicates the modules that wants to remove role switch from the default link policy */ UINT16 cur_policy; /* current default link policy */ UINT16 rs_event; /* the event waiting for role switch */ +#if (CLASSIC_BT_INCLUDED == TRUE) UINT8 cur_av_count; /* current AV connections */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) BOOLEAN disable_pair_mode; /* disable pair mode or not */ BOOLEAN conn_paired_only; /* allow connectable to paired device only or not */ tBTA_DM_API_SEARCH search_msg; @@ -2040,7 +1989,9 @@ typedef struct { tBTA_DM_ENCRYPT_CBACK *p_encrypt_cback; +#if (CLASSIC_BT_INCLUDED == TRUE) TIMER_LIST_ENT switch_delay_timer[BTA_DM_NUM_PEER_DEVICE]; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } tBTA_DM_CB; @@ -2210,8 +2161,10 @@ extern tBTA_DM_SEARCH_CB *bta_dm_search_cb_ptr; #if BTA_DYNAMIC_MEMORY == FALSE extern tBTA_DM_DI_CB bta_dm_di_cb; #else +#if (CLASSIC_BT_INCLUDED == TRUE) extern tBTA_DM_DI_CB *bta_dm_di_cb_ptr; #define bta_dm_di_cb (*bta_dm_di_cb_ptr) +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) extern SemaphoreHandle_t deinit_semaphore; #endif @@ -2288,9 +2241,6 @@ extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_params(tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_fil_params(tBTA_DM_MSG *p_data); -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -extern void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data); -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) #if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) extern void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data); #endif /* ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) */ @@ -2300,27 +2250,22 @@ extern void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data); extern void bta_dm_ble_disconnect (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_rand_address(tBTA_DM_MSG *p_data); extern void bta_dm_ble_clear_rand_address(tBTA_DM_MSG *p_data); -#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) -extern void bta_dm_ble_stop_advertising(tBTA_DM_MSG *p_data); -#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data); extern void bta_dm_ble_config_local_icon (tBTA_DM_MSG *p_data); +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +extern void bta_dm_ble_set_key_material (tBTA_DM_MSG *p_data); +#endif extern void bta_dm_ble_set_adv_params_all(tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_adv_config_raw (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_rsp_raw (tBTA_DM_MSG *p_data); -extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data); +extern void bta_dm_ble_advstop (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data); extern void bta_dm_ble_update_duplicate_exceptional_list(tBTA_DM_MSG *p_data); #if SMP_INCLUDED == TRUE extern void bta_dm_co_security_param_init(void); #endif -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE -extern void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data); -extern void bta_dm_scan_filter_param_setup (tBTA_DM_MSG *p_data); -extern void bta_dm_enable_scan_filter(tBTA_DM_MSG *p_data); -#endif extern void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data); @@ -2351,21 +2296,8 @@ extern void bta_dm_ble_gap_set_ext_scan_params(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_ext_scan(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_prefer_ext_conn_params(tBTA_DM_MSG *p_data); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -extern void bta_dm_ble_setup_storage(tBTA_DM_MSG *p_data); -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -extern void bta_dm_ble_enable_batch_scan(tBTA_DM_MSG *p_data); -extern void bta_dm_ble_disable_batch_scan(tBTA_DM_MSG *p_data); extern void bta_dm_ble_read_scan_reports(tBTA_DM_MSG *p_data); -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -extern void bta_dm_ble_track_advertiser(tBTA_DM_MSG *p_data); -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) -extern void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data); -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) - #endif extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data); extern void bta_dm_confirm(tBTA_DM_MSG *p_data); @@ -2428,7 +2360,6 @@ extern void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data); extern void bta_dm_execute_callback(tBTA_DM_MSG *p_data); -extern void bta_dm_remove_all_acl(tBTA_DM_MSG *p_data); #if (BLE_50_FEATURE_SUPPORT == TRUE) extern void bta_dm_ble_gap_read_phy(tBTA_DM_MSG *p_data); @@ -2543,4 +2474,23 @@ void bta_dm_api_subrate_request(tBTA_DM_MSG *p_data); #if (BLE_50_FEATURE_SUPPORT == TRUE) extern void bta_dm_ble_set_host_feature(tBTA_DM_MSG *p_data); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +void bta_dm_api_set_periodic_adv_subevt_data(tBTA_DM_MSG *p_data); +void bta_dm_api_set_periodic_adv_response_data(tBTA_DM_MSG *p_data); +void bta_dm_api_set_periodic_sync_subevt(tBTA_DM_MSG *p_data); +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void bta_dm_api_cs_read_local_supported_caps(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_read_remote_supported_caps(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_write_cached_remote_supported_caps(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_security_enable(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_set_default_settings(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_read_remote_fae_table(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_write_cached_remote_fae_table(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_create_config(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_remove_config(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_set_channel_classification(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_set_procedure_params(tBTA_DM_MSG *p_data); +void bta_dm_api_cs_procedure_enable(tBTA_DM_MSG *p_data); +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) #endif /* BTA_DM_INT_H */ diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c index f65dd43e7c..e808dc9f54 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -511,6 +511,10 @@ void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) tGATT_TCB *p_tcb; tBTM_SEC_DEV_REC *p_dev_rec = NULL; + BOOLEAN is_pawr_synced = FALSE; + UINT8 adv_handle = 0xFF; + UINT8 subevent = 0xFF; + if (!p_clcb || !p_data) { return; } @@ -545,10 +549,15 @@ void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) APPL_TRACE_ERROR("Unknown Device, setting rejected"); } } - +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + is_pawr_synced = p_data->api_conn.is_pawr_synced; + adv_handle = p_data->api_conn.adv_handle; + subevent = p_data->api_conn.subevent; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) /* open/hold a connection */ if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, p_data->api_conn.remote_addr_type, - TRUE, p_data->api_conn.transport, p_data->api_conn.is_aux)) { + TRUE, p_data->api_conn.transport, p_data->api_conn.is_aux, is_pawr_synced, + adv_handle, subevent)) { APPL_TRACE_ERROR("Connection open failure"); bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_OPEN_FAIL_EVT, p_data); @@ -585,7 +594,7 @@ void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg /* always call open to hold a connection */ if (!GATT_Connect(p_data->client_if, p_data->remote_bda, p_data->remote_addr_type, FALSE, - p_data->transport, p_data->is_aux)) { + p_data->transport, p_data->is_aux, FALSE, 0xFF, 0xFF)) { #if (!CONFIG_BT_STACK_NO_LOG) uint8_t *bda = (uint8_t *)p_data->remote_bda; #endif @@ -727,6 +736,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) #if (GATTC_CACHE_NVS == TRUE) p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD; if (bta_gattc_cache_load(p_clcb)) { + APPL_TRACE_DEBUG("%s found gattc cache", __func__); p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE; bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK); //register service change @@ -734,6 +744,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) } else #endif { /* cache is building */ + APPL_TRACE_DEBUG("%s cache not found, start discovery %u", __func__, bta_gattc_cb.auto_disc); if (bta_gattc_cb.auto_disc) { p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC; /* cache load failure, start discovery */ @@ -753,10 +764,12 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) } if (p_clcb->p_rcb) { +#if (CLASSIC_BT_INCLUDED == TRUE) /* there is no RM for GATT */ if (p_clcb->transport == BTA_TRANSPORT_BR_EDR) { bta_sys_conn_open(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) tBTA_GATT_STATUS status = BTA_GATT_OK; if (p_data && p_data->int_conn.already_connect) { //clear already_connect @@ -859,11 +872,11 @@ void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) cb_data.close.reason = p_clcb->reason; cb_data.close.status = p_clcb->status; bdcpy(cb_data.close.remote_bda, p_clcb->bda); - +#if (CLASSIC_BT_INCLUDED == TRUE) if (p_clcb->transport == BTA_TRANSPORT_BR_EDR) { bta_sys_conn_close( BTA_ID_GATTC , BTA_ALL_APP_ID, p_clcb->bda); } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT) { cb_data.close.status = GATT_Disconnect(p_data->hdr.layer_specific); } else if (p_data->hdr.event == BTA_GATTC_INT_DISCONN_EVT) { @@ -1327,11 +1340,13 @@ void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) != GATT_SUCCESS) { APPL_TRACE_ERROR("bta_gattc_confirm to handle [0x%04x] failed", handle); } else { +#if (CLASSIC_BT_INCLUDED == TRUE) /* if over BR_EDR, inform PM for mode change */ if (p_clcb->transport == BTA_TRANSPORT_BR_EDR) { bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda); bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } } /******************************************************************************* @@ -1847,6 +1862,8 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) UINT8 i; UNUSED(p_cb); + APPL_TRACE_DEBUG("%s", __func__); + if (p_srvc_cb != NULL) { /* try to find a CLCB */ if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0) { @@ -1965,6 +1982,8 @@ void bta_gattc_process_api_cache_clean(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_m tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_clean.remote_bda); UNUSED(p_cb); + APPL_TRACE_DEBUG("%s", __func__); + if (p_srvc_cb != NULL && p_srvc_cb->p_srvc_cache != NULL) { //mark it and delete the cache */ list_free(p_srvc_cb->p_srvc_cache); @@ -2187,13 +2206,13 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS APPL_TRACE_ERROR("bta_gattc_cmpl_cback unknown conn_id = %d, ignore data", conn_id); return; } - +#if (CLASSIC_BT_INCLUDED == TRUE) /* if over BR_EDR, inform PM for mode change */ if (p_clcb->transport == BTA_TRANSPORT_BR_EDR) { bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda); bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda); } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) bta_gattc_cmpl_sendmsg(conn_id, op, status, p_data); } diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c index 8ac0ec4c96..69738647ba 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c @@ -144,6 +144,7 @@ void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if) *******************************************************************************/ void BTA_GATTC_Enh_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_TYPE remote_addr_type, BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport, BOOLEAN is_aux, tBTA_ADDR_TYPE own_addr_type, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent, UINT8 phy_mask, tBTA_BLE_CONN_PARAMS *phy_1m_conn_params, tBTA_BLE_CONN_PARAMS *phy_2m_conn_params, tBTA_BLE_CONN_PARAMS *phy_coded_conn_params) { @@ -156,6 +157,11 @@ void BTA_GATTC_Enh_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_T p_buf->is_direct = is_direct; p_buf->transport = transport; p_buf->is_aux = is_aux; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + p_buf->is_pawr_synced = is_pawr_synced; + p_buf->adv_handle = adv_handle; + p_buf->subevent = subevent; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) p_buf->remote_addr_type = remote_addr_type; p_buf->own_addr_type = own_addr_type; p_buf->phy_mask = phy_mask; diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c index 8ec3a55dff..d6ca7bca47 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c @@ -444,6 +444,8 @@ void bta_gattc_co_cache_addr_init(void) void bta_gattc_co_cache_addr_deinit(void) { + APPL_TRACE_DEBUG("%s is_open=%d", __func__, cache_env->is_open); + if(!cache_env->is_open) { return; } @@ -553,7 +555,7 @@ void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, hash_key_t hash_key) memcpy(cache_env->cache_addr[new_index].addr, bd_addr, sizeof(BD_ADDR)); memcpy(cache_env->cache_addr[new_index].hash_key, hash_key, sizeof(hash_key_t)); cache_env->num_addr++; - APPL_TRACE_DEBUG("%s(), num = %d", __func__, cache_env->num_addr); + APPL_TRACE_DEBUG("%s bd_addr="MACSTR" num=%d", __func__, MAC2STR(bd_addr), cache_env->num_addr); } nvs_handle_t *fp = &cache_env->addr_fp; diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c index 18632d2dfa..6f3f3c0a4c 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c @@ -327,6 +327,8 @@ void bta_gattc_clcb_dealloc_by_conn_id(UINT16 conn_id) { tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); + APPL_TRACE_DEBUG("%s conn_id=%u p_clcb=%p", __func__, conn_id, p_clcb); + if (p_clcb) { tBTA_GATTC_RCB *p_clreg = p_clcb->p_rcb; bta_gattc_clcb_dealloc(p_clcb); @@ -523,10 +525,82 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); } else { - APPL_TRACE_ERROR("%s(), line = %d, alloc fail, size %d, no memory. free=%d, largest_block=%d", __func__, __LINE__, - sizeof(tBTA_GATTC_DATA) + len, heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__); return FALSE; } + } else if (p_data->hdr.event == BTA_GATTC_API_SEARCH_EVT) { + /* + * Fix for Use-After-Free (UAF) bug in service search with filter_uuid. + * + * Problem Description: + * ==================== + * In BTA_GATTC_ServiceSearchRequest(), memory is allocated as: + * [tBTA_GATTC_API_SEARCH structure][tBT_UUID data] + * + * The p_srvc_uuid pointer points to the tBT_UUID data located right after + * the structure: + * p_buf->p_srvc_uuid = (tBT_UUID *)(p_buf + 1); + * + * When this command is enqueued (e.g., during DISCOVER_ST state), the original + * code only performed a shallow copy: + * - Only sizeof(tBTA_GATTC_DATA) was allocated for cmd_data + * - memcpy copied the pointer VALUE (not the pointed data) + * - After the original message is freed by bta_sys_event(), the p_srvc_uuid + * pointer becomes a dangling pointer pointing to freed memory + * + * Memory layout before fix: + * + * Original (p_data): Copy (cmd_data): + * +------------------+----------+ +------------------+ + * | API_SEARCH | tBT_UUID | | API_SEARCH | + * | p_srvc_uuid: --------► | | p_srvc_uuid: --------► (dangling!) + * +------------------+----------+ +------------------+ + * ↑ + * After free(), this memory may be + * overwritten by other allocations + * + * Solution: + * ========= + * For BTA_GATTC_API_SEARCH_EVT with non-NULL p_srvc_uuid, we need to: + * 1. Allocate extra space for tBT_UUID + * 2. Copy the structure + * 3. Update p_srvc_uuid to point to the new location + * 4. Copy the tBT_UUID data + * + * Memory layout after fix: + * + * Copy (cmd_data): + * +------------------+----------+ + * | API_SEARCH | tBT_UUID | + * | p_srvc_uuid: --------► | (points to its own copy) + * +------------------+----------+ + */ + if (p_data->api_search.p_srvc_uuid != NULL) { + /* Allocate space for structure + UUID data (deep copy) */ + len = sizeof(tBTA_GATTC_DATA) + sizeof(tBT_UUID); + if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(len)) != NULL) { + memset(cmd_data, 0, len); + /* Copy the structure */ + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + /* Update pointer to point to the space after the structure */ + cmd_data->api_search.p_srvc_uuid = (tBT_UUID *)(cmd_data + 1); + /* Copy the UUID data */ + memcpy(cmd_data->api_search.p_srvc_uuid, + p_data->api_search.p_srvc_uuid, sizeof(tBT_UUID)); + } else { + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__); + return FALSE; + } + } else { + /* p_srvc_uuid is NULL, no extra space needed (search all services) */ + if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) { + memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); + memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); + } else { + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__); + return FALSE; + } + } } else { if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) { memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c index 692c59c660..4e786bc8a1 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c @@ -695,12 +695,13 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg) p_msg->api_indicate.len, p_msg->api_indicate.value); } - +#if (CLASSIC_BT_INCLUDED == TRUE) /* if over BR_EDR, inform PM for mode change */ if (transport == BTA_TRANSPORT_BR_EDR) { bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda); bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } else { APPL_TRACE_ERROR("Unknown connection ID: %d fail sending notification", p_msg->api_indicate.hdr.layer_specific); @@ -757,7 +758,7 @@ void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg) if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_open.server_if)) != NULL) { /* should always get the connection ID */ if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda, BLE_ADDR_UNKNOWN_TYPE, - p_msg->api_open.is_direct, p_msg->api_open.transport, FALSE)) { + p_msg->api_open.is_direct, p_msg->api_open.transport, FALSE, FALSE, 0xFF, 0xFF)) { status = BTA_GATT_OK; if (GATT_GetConnIdIfConnected(p_rcb->gatt_if, p_msg->api_open.remote_bda, @@ -839,10 +840,11 @@ void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg) p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if); if (p_rcb && p_rcb->p_cback) { +#if (CLASSIC_BT_INCLUDED == TRUE) if (transport == BTA_TRANSPORT_BR_EDR) { bta_sys_conn_close( BTA_ID_GATTS , BTA_ALL_APP_ID, remote_bda); } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) close.status = status; close.conn_id = p_msg->hdr.layer_specific; (*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT, (tBTA_GATTS *)&close); @@ -925,12 +927,13 @@ static void bta_gatts_send_request_cback (UINT16 conn_id, conn_id, trans_id, req_type); if (p_rcb && p_rcb->p_cback) { +#if (CLASSIC_BT_INCLUDED == TRUE) /* if over BR_EDR, inform PM for mode change */ if (transport == BTA_TRANSPORT_BR_EDR) { bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, cb_data.req_data.remote_bda); bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, cb_data.req_data.remote_bda); } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) cb_data.req_data.conn_id = conn_id; cb_data.req_data.trans_id = trans_id; cb_data.req_data.p_data = (tBTA_GATTS_REQ_DATA *)p_data; @@ -980,6 +983,7 @@ static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, p_reg = bta_gatts_find_app_rcb_by_app_if(gatt_if); if (p_reg && p_reg->p_cback) { +#if (CLASSIC_BT_INCLUDED == TRUE) /* there is no RM for GATT */ if (transport == BTA_TRANSPORT_BR_EDR) { if (connected) { @@ -988,6 +992,7 @@ static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, bta_sys_conn_close( BTA_ID_GATTS , BTA_ALL_APP_ID, bda); } } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) if(evt == BTA_GATTS_CONNECT_EVT) { tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE); if(p_lcb != NULL) { diff --git a/components/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h b/components/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h index cb877fcfc2..ac42de6973 100644 --- a/components/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h +++ b/components/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h @@ -130,6 +130,11 @@ typedef struct { tBTA_GATTC_IF client_if; BOOLEAN is_direct; BOOLEAN is_aux; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + BOOLEAN is_pawr_synced; + UINT8 adv_handle; + UINT8 subevent; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) tBTA_TRANSPORT transport; tBTA_ADDR_TYPE own_addr_type; UINT8 phy_mask; diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_le.c b/components/bt/host/bluedroid/bta/hh/bta_hh_le.c index f5697dff52..9bb7801a41 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_le.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_le.c @@ -2603,10 +2603,11 @@ static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond) !p_cb->in_bg_conn && to_add) { /* add device into BG connection to accept remote initiated connection */ BTA_GATTC_Enh_Open(bta_hh_cb.gatt_if, p_cb->addr, BLE_ADDR_UNKNOWN_TYPE, FALSE, - BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, 0, NULL, NULL); + BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, false, 0xFF, 0xFF, 0, NULL, NULL); p_cb->in_bg_conn = TRUE; - +#if (BLE_GATT_BGCONN == TRUE) BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL); +#endif // (BLE_GATT_BGCONN == TRUE) } return; } diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_api.h index aa1b632aad..d8918fccff 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -293,9 +293,6 @@ typedef struct { BOOLEAN report_dup; /* report duplicated inquiry response with higher RSSI value */ tBTA_DM_INQ_FILT filter_type; /* Filter condition type. */ tBTA_DM_INQ_COND filter_cond; /* Filter condition data. */ -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - UINT8 intl_duration[4];/*duration array storing the interleave scan's time portions*/ -#endif } tBTA_DM_INQ; /* Config EIR callback */ @@ -514,13 +511,6 @@ typedef struct { tBTA_BLE_SERVICE service; } tBTA_BLE_INQ_DATA; -enum { - BTA_BLE_BATCH_SCAN_MODE_PASS = 1, - BTA_BLE_BATCH_SCAN_MODE_ACTI = 2, - BTA_BLE_BATCH_SCAN_MODE_PASS_ACTI = 3 -}; -typedef UINT8 tBTA_BLE_BATCH_SCAN_MODE; - enum { BTA_BLE_DISCARD_OLD_ITEMS = 0, BTA_BLE_DISCARD_LOWER_RSSI_ITEMS = 1 @@ -533,19 +523,6 @@ enum { }; typedef UINT8 tBTA_BLE_ADV_CHANGE_REASON; -enum { - BTA_BLE_BATCH_SCAN_ENB_EVT = 1, - BTA_BLE_BATCH_SCAN_CFG_STRG_EVT = 2, - BTA_BLE_BATCH_SCAN_DATA_EVT = 3, - BTA_BLE_BATCH_SCAN_THRES_EVT = 4, - BTA_BLE_BATCH_SCAN_PARAM_EVT = 5, - BTA_BLE_BATCH_SCAN_DIS_EVT = 6 -}; -typedef tBTM_BLE_BATCH_SCAN_EVT tBTA_BLE_BATCH_SCAN_EVT; - -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -typedef tBTM_BLE_TRACK_ADV_ACTION tBTA_BLE_TRACK_ADV_ACTION; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) // #endif /* BLE customer specific feature function type definitions */ @@ -579,7 +556,6 @@ enum { BTA_DM_BLE_SCAN_COND_DELETE, BTA_DM_BLE_SCAN_COND_CLEAR = 2 }; -typedef UINT8 tBTA_DM_BLE_SCAN_COND_OP; /* ADV payload filtering vendor specific call event */ enum { @@ -587,18 +563,6 @@ enum { BTA_BLE_SCAN_PF_COND_EVT }; -/* filter selection bit index */ -#define BTA_DM_BLE_PF_ADDR_FILTER BTM_BLE_PF_ADDR_FILTER -#define BTA_DM_BLE_PF_SRVC_DATA BTM_BLE_PF_SRVC_DATA -#define BTA_DM_BLE_PF_SRVC_UUID BTM_BLE_PF_SRVC_UUID -#define BTA_DM_BLE_PF_SRVC_SOL_UUID BTM_BLE_PF_SRVC_SOL_UUID -#define BTA_DM_BLE_PF_LOCAL_NAME BTM_BLE_PF_LOCAL_NAME -#define BTA_DM_BLE_PF_MANU_DATA BTM_BLE_PF_MANU_DATA -#define BTA_DM_BLE_PF_SRVC_DATA_PATTERN BTM_BLE_PF_SRVC_DATA_PATTERN -#define BTA_DM_BLE_PF_TYPE_ALL BTM_BLE_PF_TYPE_ALL -#define BTA_DM_BLE_PF_TYPE_MAX BTM_BLE_PF_TYPE_MAX -typedef UINT8 tBTA_DM_BLE_PF_COND_TYPE; - typedef union { UINT16 uuid16_mask; UINT32 uuid32_mask; @@ -634,18 +598,6 @@ typedef struct { as data pattern, set to all 0xff, match exact data */ } tBTA_DM_BLE_PF_SRVC_PATTERN_COND; -typedef union { - tBLE_BD_ADDR target_addr; - tBTA_DM_BLE_PF_LOCAL_NAME_COND local_name; /* local name filtering */ - tBTA_DM_BLE_PF_MANU_COND manu_data; /* manufacturer data filtering */ - tBTA_DM_BLE_PF_UUID_COND srvc_uuid; /* service UUID filtering */ - tBTA_DM_BLE_PF_UUID_COND solicitate_uuid; /* solicited service UUID filtering */ - tBTA_DM_BLE_PF_SRVC_PATTERN_COND srvc_data; /* service data pattern */ -} tBTA_DM_BLE_PF_COND_PARAM; - -typedef UINT8 tBTA_DM_BLE_PF_FILT_INDEX; -typedef UINT8 tBTA_DM_BLE_PF_AVBL_SPACE; - typedef INT8 tBTA_DM_RSSI_VALUE; typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE; @@ -1053,82 +1005,8 @@ typedef union { /* Security callback */ typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data); -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -#define BTA_BLE_MULTI_ADV_ILLEGAL 0 - -/* multi adv callback event */ -#define BTA_BLE_MULTI_ADV_ENB_EVT 1 -#define BTA_BLE_MULTI_ADV_DISABLE_EVT 2 -#define BTA_BLE_MULTI_ADV_PARAM_EVT 3 -#define BTA_BLE_MULTI_ADV_DATA_EVT 4 - -typedef UINT8 tBTA_BLE_MULTI_ADV_EVT; - -/* multi adv callback */ -typedef void (tBTA_BLE_MULTI_ADV_CBACK)(tBTA_BLE_MULTI_ADV_EVT event, - UINT8 inst_id, void *p_ref, tBTA_STATUS status); -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - typedef UINT32 tBTA_DM_BLE_REF_VALUE; -#define BTA_DM_BLE_PF_ENABLE_EVT BTM_BLE_PF_ENABLE -#define BTA_DM_BLE_PF_CONFIG_EVT BTM_BLE_PF_CONFIG -typedef UINT8 tBTA_DM_BLE_PF_EVT; - -#define BTA_DM_BLE_PF_ENABLE 1 -#define BTA_DM_BLE_PF_CONFIG 2 -typedef UINT8 tBTA_DM_BLE_PF_ACTION; - -/* Config callback */ -typedef void (tBTA_DM_BLE_PF_CFG_CBACK) (tBTA_DM_BLE_PF_ACTION action, - tBTA_DM_BLE_PF_COND_TYPE cfg_cond, - tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, tBTA_STATUS status, - tBTA_DM_BLE_REF_VALUE ref_value); -/* Param callback */ -typedef void (tBTA_DM_BLE_PF_PARAM_CBACK) (UINT8 action_type, tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, - tBTA_DM_BLE_REF_VALUE ref_value, tBTA_STATUS status); - -/* Status callback */ -typedef void (tBTA_DM_BLE_PF_STATUS_CBACK) (UINT8 action, tBTA_STATUS status, - tBTA_DM_BLE_REF_VALUE ref_value); - - -#define BTA_DM_BLE_PF_BRDCAST_ADDR_FILT 1 -#define BTA_DM_BLE_PF_SERV_DATA_CHG_FILT 2 -#define BTA_DM_BLE_PF_SERV_UUID 4 -#define BTA_DM_BLE_PF_SERV_SOLC_UUID 8 -#define BTA_DM_BLE_PF_LOC_NAME_CHECK 16 -#define BTA_DM_BLE_PF_MANUF_NAME_CHECK 32 -#define BTA_DM_BLE_PF_SERV_DATA_CHECK 64 -typedef UINT16 tBTA_DM_BLE_PF_FEAT_SEL; - -#define BTA_DM_BLE_PF_LIST_LOGIC_OR 1 -#define BTA_DM_BLE_PF_LIST_LOGIC_AND 2 -typedef UINT16 tBTA_DM_BLE_PF_LIST_LOGIC_TYPE; - -#define BTA_DM_BLE_PF_FILT_LOGIC_OR 0 -#define BTA_DM_BLE_PF_FILT_LOGIC_AND 1 -typedef UINT16 tBTA_DM_BLE_PF_FILT_LOGIC_TYPE; - -typedef UINT8 tBTA_DM_BLE_PF_RSSI_THRESHOLD; -typedef UINT8 tBTA_DM_BLE_PF_DELIVERY_MODE; -typedef UINT16 tBTA_DM_BLE_PF_TIMEOUT; -typedef UINT8 tBTA_DM_BLE_PF_TIMEOUT_CNT; -typedef UINT16 tBTA_DM_BLE_PF_ADV_TRACK_ENTRIES; - -typedef struct { - tBTA_DM_BLE_PF_FEAT_SEL feat_seln; - tBTA_DM_BLE_PF_LIST_LOGIC_TYPE list_logic_type; - tBTA_DM_BLE_PF_FILT_LOGIC_TYPE filt_logic_type; - tBTA_DM_BLE_PF_RSSI_THRESHOLD rssi_high_thres; - tBTA_DM_BLE_PF_RSSI_THRESHOLD rssi_low_thres; - tBTA_DM_BLE_PF_DELIVERY_MODE dely_mode; - tBTA_DM_BLE_PF_TIMEOUT found_timeout; - tBTA_DM_BLE_PF_TIMEOUT lost_timeout; - tBTA_DM_BLE_PF_TIMEOUT_CNT found_timeout_cnt; - tBTA_DM_BLE_PF_ADV_TRACK_ENTRIES num_of_tracking_entries; -} tBTA_DM_BLE_PF_FILT_PARAMS; - /* Search callback events */ #define BTA_DM_INQ_RES_EVT 0 /* Inquiry result for a peer device. */ #define BTA_DM_INQ_CMPL_EVT 1 /* Inquiry complete. */ @@ -1228,6 +1106,71 @@ typedef struct { tBTA_DM_SEARCH *p_data; /* Union of all search callback structures */ } tBTA_DM_SEARCH_PARAM; +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +typedef struct { + UINT16 conn_handle; + UINT8 num_config_supported; + UINT16 max_consecutive_proc_supported; + UINT8 num_ant_supported; + UINT8 max_ant_paths_supported; + UINT8 roles_supported; + UINT8 modes_supported; + UINT8 rtt_capability; + UINT8 rtt_aa_only_n; + UINT8 rtt_sounding_n; + UINT8 rtt_random_payload_n; + UINT16 NADM_sounding_capability; + UINT16 NADM_random_capability; + UINT8 cs_sync_phys_supported; + UINT16 subfeatures_supported; + UINT16 T_IP1_times_supported; + UINT16 T_IP2_times_supported; + UINT16 T_FCS_times_supported; + UINT16 T_PM_times_supported; + UINT8 T_SW_times_supported; + UINT8 TX_SNR_capability; +} tBTA_DM_CS_WRITE_CACHED_REMOTE_SUPP_CAPS; + +typedef struct { + UINT16 conn_handle; + UINT8 config_id; + UINT8 create_context; + UINT8 main_mode_type; + UINT8 sub_mode_type; + UINT8 min_main_mode_steps; + UINT8 max_main_mode_steps; + UINT8 main_mode_repetition; + UINT8 mode_0_steps; + UINT8 role; + UINT8 rtt_type; + UINT8 cs_sync_phy; + UINT8 channel_map[10]; + UINT8 channel_map_repetition; + UINT8 channel_selection_type; + UINT8 ch3c_shape; + UINT8 ch3c_jump; + UINT8 reserved; +} tBTA_DM_CS_CREATE_CONFIG_PARAMS; + +typedef struct { + UINT16 conn_handle; + UINT8 config_id; + UINT16 max_procedure_len; + UINT16 min_procedure_interval; + UINT16 max_procedure_interval; + UINT16 max_procedure_count; + uint32_t min_subevent_len; + uint32_t max_subevent_len; + UINT8 tone_ant_config_selection; + UINT8 phy; + UINT8 tx_power_delta; + UINT8 preferred_peer_antenna; + UINT8 SNR_control_initiator; + UINT8 SNR_control_reflector; +} tBTA_DM_CS_SET_PROC_PARAMS; + +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + /* Search callback */ typedef void (tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); @@ -1245,11 +1188,6 @@ typedef void (tBTA_DM_ENCRYPT_CBACK) (BD_ADDR bd_addr, tBTA_TRANSPORT transport, #define BTA_DM_BLE_SEC_MITM BTM_BLE_SEC_ENCRYPT_MITM typedef tBTM_BLE_SEC_ACT tBTA_DM_BLE_SEC_ACT; -typedef tBTM_BLE_TX_TIME_MS tBTA_DM_BLE_TX_TIME_MS; -typedef tBTM_BLE_RX_TIME_MS tBTA_DM_BLE_RX_TIME_MS; -typedef tBTM_BLE_IDLE_TIME_MS tBTA_DM_BLE_IDLE_TIME_MS; -typedef tBTM_BLE_ENERGY_USED tBTA_DM_BLE_ENERGY_USED; - #define BTA_DM_CONTRL_UNKNOWN 0 /* Unknown state */ #define BTA_DM_CONTRL_ACTIVE 1 /* ACL link on, SCO link ongoing, sniff mode */ #define BTA_DM_CONTRL_SCAN 2 /* Scan state - paging/inquiry/trying to connect*/ @@ -1261,9 +1199,6 @@ typedef UINT8 tBTA_DM_BLE_ADV_STATE; typedef UINT8 tBTA_DM_BLE_ADV_INFO_PRESENT; typedef UINT8 tBTA_DM_BLE_RSSI_VALUE; typedef UINT16 tBTA_DM_BLE_ADV_INFO_TIMESTAMP; -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -typedef tBTM_BLE_TRACK_ADV_DATA tBTA_DM_BLE_TRACK_ADV_DATA; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) typedef void (tBTA_BLE_SCAN_THRESHOLD_CBACK)(tBTA_DM_BLE_REF_VALUE ref_value); @@ -1271,33 +1206,12 @@ typedef void (tBTA_BLE_SCAN_REP_CBACK) (tBTA_DM_BLE_REF_VALUE ref_value, UINT8 r UINT8 num_records, UINT16 data_len, UINT8 *p_rep_data, tBTA_STATUS status); -typedef void (tBTA_BLE_SCAN_SETUP_CBACK) (tBTA_BLE_BATCH_SCAN_EVT evt, - tBTA_DM_BLE_REF_VALUE ref_value, - tBTA_STATUS status); - typedef void (tBTA_START_STOP_SCAN_CMPL_CBACK) (tBTA_STATUS status); typedef void (tBTA_START_STOP_ADV_CMPL_CBACK) (tBTA_STATUS status); typedef void (tBTA_CLEAR_ADV_CMPL_CBACK) (tBTA_STATUS status); -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -typedef void (tBTA_BLE_TRACK_ADV_CMPL_CBACK)(int action, tBTA_STATUS status, - tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, - tBTA_DM_BLE_REF_VALUE ref_value); - -typedef void (tBTA_BLE_TRACK_ADV_CBACK)(tBTA_DM_BLE_TRACK_ADV_DATA *p_adv_data); -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) -typedef void (tBTA_BLE_ENERGY_INFO_CBACK)(tBTA_DM_BLE_TX_TIME_MS tx_time, - tBTA_DM_BLE_RX_TIME_MS rx_time, - tBTA_DM_BLE_IDLE_TIME_MS idle_time, - tBTA_DM_BLE_ENERGY_USED energy_used, - tBTA_DM_CONTRL_STATE ctrl_state, - tBTA_STATUS status); -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) - #else typedef UINT8 tBTA_DM_BLE_SEC_ACT; #endif @@ -1573,6 +1487,10 @@ typedef struct { tBTA_DM_BLE_GAP_PHY secondary_phy; UINT8 sid; BOOLEAN scan_req_notif; +#if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) + uint8_t primary_adv_phy_options; + uint8_t secondary_adv_phy_options; +#endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) } tBTA_DM_BLE_GAP_EXT_ADV_PARAMS; typedef struct { @@ -1584,7 +1502,14 @@ typedef struct { typedef struct { UINT16 interval_min; UINT16 interval_max; - UINT8 properties; + UINT16 properties; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + UINT8 num_subevents; + UINT8 subevent_interval; + UINT8 rsp_slot_delay; + UINT8 rsp_slot_spacing; + UINT8 num_rsp_slots; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) } tBTA_DM_BLE_Periodic_Adv_Params; typedef struct { @@ -1701,6 +1626,30 @@ typedef struct { #define BTA_BLE_GAP_SET_HOST_FEATURE_EVT BTM_BLE_GAP_SET_HOST_FEATURE_EVT #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +#define BTA_BLE_GAP_SET_PERIODIC_ADV_SUBEVT_DATA_EVT BTM_BLE_GAP_SET_PERIODIC_ADV_SUBEVT_DATA_EVT +#define BTA_BLE_GAP_SET_PERIODIC_ADV_RESPONSE_DATA_EVT BTM_BLE_GAP_SET_PERIODIC_ADV_RESPONSE_DATA_EVT +#define BTA_BLE_GAP_SET_PERIODIC_SYNC_SUBEVT_EVT BTM_BLE_GAP_SET_PERIODIC_SYNC_SUBEVT_EVT +#define BTA_BLE_GAP_PERIODIC_ADV_SUBEVT_DATA_REQUEST_EVT BTM_BLE_GAP_PERIODIC_ADV_SUBEVT_DATA_REQUEST_EVT +#define BTA_BLE_GAP_PERIODIC_ADV_RESPONSE_REPORT_EVT BTM_BLE_GAP_PERIODIC_ADV_RESPONSE_REPORT_EVT +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#define BTA_BLE_GAP_CS_READ_LOCAL_SUPP_CAPS_EVT BTM_BLE_GAP_CS_READ_LOCAL_SUPP_CAPS_EVT +#define BTA_BLE_GAP_CS_WRITE_CACHED_REMOTE_SUPP_CAPS_EVT BTM_BLE_GAP_CS_WRITE_CACHED_REMOTE_SUPP_CAPS_EVT +#define BTA_BLE_GAP_CS_SET_DEFAULT_SETTINGS_EVT BTM_BLE_GAP_CS_SET_DEFAULT_SETTINGS_EVT +#define BTA_BLE_GAP_CS_WRITE_CACHED_REMOTE_FAE_TAB_EVT BTM_BLE_GAP_CS_WRITE_CACHED_REMOTE_FAE_TAB_EVT +#define BTA_BLE_GAP_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT BTM_BLE_GAP_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT +#define BTA_BLE_GAP_CS_SET_CHANNEL_CLASS_CMPL_EVT BTM_BLE_GAP_CS_SET_CHANNEL_CLASS_CMPL_EVT +#define BTA_BLE_GAP_CS_PROC_PARAMS_CMPL_EVT BTM_BLE_GAP_CS_PROC_PARAMS_CMPL_EVT +#define BTA_BLE_GAP_CS_PROC_ENABLE_CMPL_EVT BTM_BLE_GAP_CS_PROC_ENABLE_CMPL_EVT +#define BTA_BLE_GAP_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT BTM_BLE_GAP_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT +#define BTA_BLE_GAP_CS_SECURITY_ENABLE_CMPL_EVT BTM_BLE_GAP_CS_SECURITY_ENABLE_CMPL_EVT +#define BTA_BLE_GAP_CS_CONFIG_CMPL_EVT BTM_BLE_GAP_CS_CONFIG_CMPL_EVT +#define BTA_BLE_GAP_CS_SUBEVENT_RESULT_EVT BTM_BLE_GAP_CS_SUBEVENT_RESULT_EVT +#define BTA_BLE_GAP_CS_SUBEVENT_RESULT_CONTINUE_EVT BTM_BLE_GAP_CS_SUBEVENT_RESULT_CONTINUE_EVT +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + #define BTA_DM_BLE_5_GAP_UNKNOWN_EVT BTM_BLE_5_GAP_UNKNOWN_EVT typedef tBTM_BLE_5_GAP_EVENT tBTA_DM_BLE_5_GAP_EVENT; @@ -2798,9 +2747,6 @@ extern void BTA_DmBleScan(BOOLEAN start, UINT32 duration, tBTA_DM_SEARCH_CBACK *p_results_cb, tBTA_START_STOP_SCAN_CMPL_CBACK *p_start_stop_scan_cb); -#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) -extern void BTA_DmBleStopAdvertising(void); -#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) extern void BTA_DmSetRandAddress(BD_ADDR rand_addr, tBTA_SET_RAND_ADDR_CBACK *p_set_rand_addr_cback); extern void BTA_DmClearRandAddress(void); @@ -2839,6 +2785,22 @@ extern void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable, tBTA_SET_LOCAL_P *******************************************************************************/ extern void BTA_DmBleConfigLocalIcon(uint16_t icon); +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +/******************************************************************************* +** +** Function BTA_DmBleSetKeyMaterial +** +** Description Set the Encrypted Data Key Material in GAP service +** +** Parameters: session_key - 16-byte session key +** iv - 8-byte initialization vector +** +** Returns void +** +*******************************************************************************/ +extern void BTA_DmBleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv); +#endif + /******************************************************************************* ** ** Function BTA_DmBleEnableRemotePrivacy @@ -2950,7 +2912,7 @@ extern void BTA_DmUpdateDuplicateExceptionalList(UINT8 subcode, UINT32 type, /******************************************************************************* ** -** Function BTA_DmBleBroadcast +** Function BTA_DmBleAdvStop ** ** Description This function starts or stops LE broadcasting. ** @@ -2960,68 +2922,7 @@ extern void BTA_DmUpdateDuplicateExceptionalList(UINT8 subcode, UINT32 type, ** Returns None ** *******************************************************************************/ -extern void BTA_DmBleBroadcast (BOOLEAN start, tBTA_START_STOP_ADV_CMPL_CBACK *p_start_stop_adv_cb); - -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -/******************************************************************************* -** -** Function BTA_BleEnableAdvInstance -** -** Description This function enables the Multi ADV instance feature -** -** Parameters p_params Pointer to ADV param user defined structure -** p_cback Pointer to Multi ADV callback structure -** p_ref - Reference pointer -** -** Returns None -** -*******************************************************************************/ -extern void BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params, - tBTA_BLE_MULTI_ADV_CBACK *p_cback, void *p_ref); - -/******************************************************************************* -** -** Function BTA_BleUpdateAdvInstParam -** -** Description This function updates the Multi ADV instance params -** -** Parameters inst_id Instance ID -** p_params Pointer to ADV param user defined structure -** -** Returns None -** -*******************************************************************************/ -extern void BTA_BleUpdateAdvInstParam (UINT8 inst_id, - tBTA_BLE_ADV_PARAMS *p_params); - -/******************************************************************************* -** -** Function BTA_BleCfgAdvInstData -** -** Description This function is called to configure the ADV instance data -** -** Parameters inst_id - Instance ID -** is_scan_rsp - Boolean value Scan response -** Pointer to User defined ADV data structure -** Returns None -** -*******************************************************************************/ -extern void BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp, - tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_data); - -/******************************************************************************* -** -** Function BTA_BleDisableAdvInstance -** -** Description This function is called to disable the ADV instance -** -** Parameters inst_id - Instance ID to be disabled -** -** Returns None -** -*******************************************************************************/ -extern void BTA_BleDisableAdvInstance(UINT8 inst_id); -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) +extern void BTA_DmBleAdvStop (BOOLEAN start, tBTA_START_STOP_ADV_CMPL_CBACK *p_start_stop_adv_cb); /******************************************************************************* ** @@ -3094,177 +2995,27 @@ void BTA_DmBleGapSubrateReqest(uint16_t conn_handle, uint16_t subrate_min, uint1 extern void BTA_DmBleGapSetHostFeature(uint16_t bit_num, uint8_t bit_val); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleSetStorageParams -** -** Description This function is called to set the storage parameters -** -** Parameters batch_scan_full_max -Max storage space (in %) allocated to full scanning -** batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning -** batch_scan_notify_threshold - Setup notification level based on total space -** consumed by both pools. Setting it to 0 will disable threshold notification -** p_setup_cback - Setup callback -** p_thres_cback - Threshold callback -** p_rep_cback - Reports callback -** ref_value - Reference value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleSetStorageParams(UINT8 batch_scan_full_max, - UINT8 batch_scan_trunc_max, - UINT8 batch_scan_notify_threshold, - tBTA_BLE_SCAN_SETUP_CBACK *p_setup_cback, - tBTA_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback, - tBTA_BLE_SCAN_REP_CBACK *p_rep_cback, - tBTA_DM_BLE_REF_VALUE ref_value); +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +void BTA_DmBleGapSetPASubevtData(uint8_t adv_handle, uint8_t num_subevents_with_data, uint8_t *subevent_params); +void BTA_DmBleGapSetPeriodicAdvRspData(uint16_t sync_handle, uint16_t request_event, uint8_t request_subevent, + uint8_t rsp_subevent, uint8_t rsp_slot, uint8_t rsp_data_len, uint8_t *rsp_data); +void BTA_DmBleGapSetPeriodicSyncSubevt(uint16_t sync_handle, uint16_t periodic_adv_properties, uint8_t num_subevents_to_sync, uint8_t *subevent); +#endif// (BT_BLE_FEAT_PAWR_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleEnableBatchScan -** -** Description This function is called to enable the batch scan -** -** Parameters scan_mode -Batch scan mode -** scan_interval - Scan interval -** scan_window - Scan window -** discard_rule -Discard rules -** addr_type - Address type -** ref_value - Reference value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleEnableBatchScan(tBTA_BLE_BATCH_SCAN_MODE scan_mode, - UINT32 scan_interval, UINT32 scan_window, - tBTA_BLE_DISCARD_RULE discard_rule, - tBLE_ADDR_TYPE addr_type, - tBTA_DM_BLE_REF_VALUE ref_value); - -/******************************************************************************* -** -** Function BTA_DmBleReadScanReports -** -** Description This function is called to read the batch scan reports -** -** Parameters scan_mode -Batch scan mode -** ref_value - Reference value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleReadScanReports(tBTA_BLE_BATCH_SCAN_MODE scan_type, - tBTA_DM_BLE_REF_VALUE ref_value); - -/******************************************************************************* -** -** Function BTA_DmBleDisableBatchScan -** -** Description This function is called to disable the batch scanning -** -** Parameters ref_value - Reference value -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleDisableBatchScan(tBTA_DM_BLE_REF_VALUE ref_value); - -/******************************************************************************* -** -** Function BTA_DmEnableScanFilter -** -** Description This function is called to enable the adv data payload filter -** -** Parameters action - enable or disable the APCF feature -** p_cmpl_cback - Command completed callback -** ref_value - Reference value -** -** Returns void -** -*******************************************************************************/ -extern void BTA_DmEnableScanFilter(UINT8 action, - tBTA_DM_BLE_PF_STATUS_CBACK *p_cmpl_cback, - tBTA_DM_BLE_REF_VALUE ref_value); - -/******************************************************************************* -** -** Function BTA_DmBleScanFilterSetup -** -** Description This function is called to setup the filter params -** -** Parameters p_target: enable the filter condition on a target device; if NULL -** filt_index - Filter index -** p_filt_params -Filter parameters -** ref_value - Reference value -** action - Add, delete or clear -** p_cmpl_back - Command completed callback -** -** Returns void -** -*******************************************************************************/ -extern void BTA_DmBleScanFilterSetup(UINT8 action, - tBTA_DM_BLE_PF_FILT_INDEX filt_index, - tBTA_DM_BLE_PF_FILT_PARAMS *p_filt_params, - tBLE_BD_ADDR *p_target, - tBTA_DM_BLE_PF_PARAM_CBACK *p_cmpl_cback, - tBTA_DM_BLE_REF_VALUE ref_value); - -/******************************************************************************* -** -** Function BTA_DmBleCfgFilterCondition -** -** Description This function is called to configure the adv data payload filter -** condition. -** -** Parameters action: to read/write/clear -** cond_type: filter condition type -** filt_index - Filter index -** p_cond: filter condition parameter -** p_cmpl_back - Command completed callback -** ref_value - Reference value -** -** Returns void -** -*******************************************************************************/ -extern void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action, - tBTA_DM_BLE_PF_COND_TYPE cond_type, - tBTA_DM_BLE_PF_FILT_INDEX filt_index, - tBTA_DM_BLE_PF_COND_PARAM *p_cond, - tBTA_DM_BLE_PF_CFG_CBACK *p_cmpl_cback, - tBTA_DM_BLE_REF_VALUE ref_value); - -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleTrackAdvertiser -** -** Description This function is called to track the advertiser -** -** Parameters ref_value - Reference value -** p_track_adv_cback - ADV callback -** -** Returns None -** -*******************************************************************************/ -extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value, - tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback); -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleGetEnergyInfo -** -** Description This function is called to obtain the energy info -** -** Parameters p_cmpl_cback - Command complete callback -** -** Returns void -** -*******************************************************************************/ -extern void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK *p_cmpl_cback); -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void BTA_DmBleGapReadLocalSupportedCaps(void); +void BTA_DmBleGapReadRemoteSupportedCaps(uint16_t conn_handle); +void BTA_DmBleGapWriteCachedRemoteSupportedCaps(tBTA_DM_CS_WRITE_CACHED_REMOTE_SUPP_CAPS *write_cachedremote_supp_caps); +void BTA_DmBleGapCsSecurityEnable(uint16_t conn_handle); +void BTA_DmBleGapCsSetDefaultSetting(uint16_t conn_handle, uint8_t role_enable, uint8_t cs_sync_ant_selection, int8_t max_tx_power); +void BTA_DmBleGapCsReadRemoteFaeTable(uint16_t conn_handle); +void BTA_DmBleGapWriteCachedRemoteFaeTable(uint16_t conn_handle, uint8_t *remote_fae_table, uint8_t table_len); +void BTA_DmBleGapCsCreateConfig(tBTA_DM_CS_CREATE_CONFIG_PARAMS *create_config_params); +void BTA_DmBleGapCsRemoveConfig(uint16_t conn_handle, uint8_t config_id); +void BTA_DmBleGapCsSetChannelClass(uint8_t *channel_class, uint8_t channl_len); +void BTA_DmBleGapCsSetProcPatams(tBTA_DM_CS_SET_PROC_PARAMS *set_proc_params); +void BTA_DmBleGapCsProcEnable(uint16_t conn_handle, uint8_t config_id, uint8_t enable); +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) /******************************************************************************* ** @@ -3277,17 +3028,6 @@ extern void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK *p_cmpl_cback); *******************************************************************************/ extern void BTA_VendorInit (void); -/******************************************************************************* -** -** Function BTA_BrcmCleanup -** -** Description This function frees up Broadcom specific VS specific dynamic memory -** -** Returns void -** -*******************************************************************************/ -extern void BTA_VendorCleanup (void); - #if (BLE_50_FEATURE_SUPPORT == TRUE) extern void BTA_DmBleGapReadPHY(BD_ADDR addr); diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h index a42d14084b..7c2a4c154c 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h @@ -39,9 +39,11 @@ #endif +#if (APPL_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG) #ifndef BTA_GATT_DEBUG #define BTA_GATT_DEBUG FALSE #endif +#endif typedef enum { BTGATT_DB_PRIMARY_SERVICE, @@ -817,6 +819,7 @@ extern void BTA_GATTC_AppDeregister (tBTA_GATTC_IF client_if); *******************************************************************************/ extern void BTA_GATTC_Enh_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_TYPE remote_addr_type, BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport, BOOLEAN is_aux, tBTA_ADDR_TYPE own_addr_type, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent, UINT8 phy_mask, tBTA_BLE_CONN_PARAMS *phy_1m_conn_params, tBTA_BLE_CONN_PARAMS *phy_2m_conn_params, tBTA_BLE_CONN_PARAMS *phy_coded_conn_params); diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_sys.h b/components/bt/host/bluedroid/bta/include/bta/bta_sys.h index ecf4791995..07cd39d24c 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_sys.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_sys.h @@ -44,7 +44,7 @@ typedef void (tBTA_SYS_DISABLE)(void); /* HW modules */ enum { BTA_SYS_HW_BLUETOOTH, - BTA_SYS_HW_RT, + // BTA_SYS_HW_RT, BTA_SYS_MAX_HW_MODULES }; diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c index a49cfc91a0..492c22022e 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -2923,7 +2923,7 @@ void bta_jv_l2cap_connect_le(tBTA_JV_MSG *p_data) id = t->id; t->init_called = FALSE; - if (L2CA_ConnectFixedChnl(t->chan, t->remote_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE)) { + if (L2CA_ConnectFixedChnl(t->chan, t->remote_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE, FALSE, 0xFF, 0xFF)) { evt.l2c_cl_init.status = BTA_JV_SUCCESS; evt.l2c_cl_init.handle = id; diff --git a/components/bt/host/bluedroid/bta/sys/bta_sys_conn.c b/components/bt/host/bluedroid/bta/sys/bta_sys_conn.c index 914df55d9c..b251a38694 100644 --- a/components/bt/host/bluedroid/bta/sys/bta_sys_conn.c +++ b/components/bt/host/bluedroid/bta/sys/bta_sys_conn.c @@ -28,6 +28,8 @@ #include "bta_sys_int.h" #include "bta/utl.h" +#if (CLASSIC_BT_INCLUDED == TRUE) + /******************************************************************************* ** ** Function bta_sys_rm_register @@ -661,3 +663,5 @@ BOOLEAN bta_sys_vs_hdl(UINT16 evt, void *p) return FALSE; } + +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c index db6ee48972..ea1bc5a854 100644 --- a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c +++ b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c @@ -543,7 +543,7 @@ void bta_sys_deregister(UINT8 id) ** ** Function bta_sys_is_register ** -** Description Called by other BTA subsystems to get registeration +** Description Called by other BTA subsystems to get registration ** status. ** ** @@ -724,7 +724,7 @@ void bta_sys_disable(tBTA_SYS_HW_MODULE module) bta_id_max = BTA_ID_BLUETOOTH_MAX; break; default: - APPL_TRACE_WARNING("bta_sys_disable: unkown module"); + APPL_TRACE_WARNING("bta_sys_disable: unknown module"); return; } @@ -750,7 +750,7 @@ void bta_sys_set_trace_level(UINT8 level) { appl_trace_level = level; } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_sys_get_sys_features @@ -764,3 +764,4 @@ UINT16 bta_sys_get_sys_features (void) { return bta_sys_cb.sys_features; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/bta/sys/include/bta_sys_int.h b/components/bt/host/bluedroid/bta/sys/include/bta_sys_int.h index aa2596d96c..5cff706b56 100644 --- a/components/bt/host/bluedroid/bta/sys/include/bta_sys_int.h +++ b/components/bt/host/bluedroid/bta/sys/include/bta_sys_int.h @@ -56,8 +56,8 @@ typedef struct { tBTA_SYS_HW_STATE state; tBTA_SYS_HW_CBACK *sys_hw_cback[BTA_SYS_MAX_HW_MODULES]; /* enable callback for each HW modules */ UINT32 sys_hw_module_active; /* bitmask of all active modules */ +#if (CLASSIC_BT_INCLUDED == TRUE) UINT16 sys_features; /* Bitmask of sys features */ - tBTA_SYS_CONN_CBACK *prm_cb; /* role management callback registered by DM */ tBTA_SYS_CONN_CBACK *ppm_cb; /* low power management callback registered by DM */ tBTA_SYS_CONN_CBACK *p_policy_cb; /* link policy change callback registered by DM */ @@ -72,6 +72,7 @@ typedef struct { #endif /* VS event handler */ tBTA_SYS_VS_EVT_HDLR *p_vs_evt_hdlr; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } tBTA_SYS_CB; diff --git a/components/bt/host/bluedroid/btc/core/btc_main.c b/components/bt/host/bluedroid/btc/core/btc_main.c index 593bb99e07..0802202797 100644 --- a/components/bt/host/bluedroid/btc/core/btc_main.c +++ b/components/bt/host/bluedroid/btc/core/btc_main.c @@ -79,9 +79,9 @@ static void btc_deinit_bluetooth(void) #if (GATTC_INCLUDED) bta_gattc_deinit(); #endif /* #if (GATTC_INCLUDED) */ -#if (GATTS_INCLUDED) +#if (GATTS_INCLUDED == TRUE) bta_gatts_deinit(); -#endif /* #if (GATTS_INCLUDED) */ +#endif /* #if (GATTS_INCLUDED == TRUE) */ bte_main_shutdown(); #if (SMP_INCLUDED) btc_config_clean_up(); @@ -168,6 +168,7 @@ uint32_t btc_get_ble_status(void) status |= BIT(BTC_BLE_STATUS_CONN); } +#if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) // Address resolve status extern uint8_t btm_get_ble_addr_resolve_disable_status(void); uint8_t addr_resolve_disable = btm_get_ble_addr_resolve_disable_status(); @@ -175,6 +176,7 @@ uint32_t btc_get_ble_status(void) BTC_TRACE_WARNING("%s address resolve disabled", __func__); status |= BIT(BTC_BLE_STATUS_ADDR_RESOLVE_DISABLE); } +#endif // #if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) #if (SMP_INCLUDED == TRUE) // Number of recorded devices diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c index 1fd74b6ada..e52102a845 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -1459,6 +1459,7 @@ static void btc_av_reg_sep(uint8_t tsep, uint8_t seid, esp_a2d_mcc_t *mcc) param.a2d_sep_reg_stat.reg_state = ESP_A2D_SEP_REG_INVALID_STATE; btc_a2d_cb_to_app(ESP_A2D_SEP_REG_STATE_EVT, ¶m); BTC_TRACE_WARNING("%s: try to reg sep when a2dp not init or connected", __func__); + return; } if (mcc->type == ESP_A2D_MCT_SBC) { diff --git a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c index 67b54deea8..a550b5c28a 100644 --- a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -470,35 +470,6 @@ static void btc_stop_adv_callback(uint8_t status) } #endif // #if (BLE_42_ADV_EN == TRUE) -void btc_update_duplicate_exceptional_list_callback(tBTA_STATUS status, uint8_t subcode, uint32_t length, uint8_t *device_info) -{ - esp_ble_gap_cb_param_t param; - bt_status_t ret; - btc_msg_t msg = {0}; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_GAP_BLE; - msg.act = ESP_GAP_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_COMPLETE_EVT; - param.update_duplicate_exceptional_list_cmpl.status = status; - param.update_duplicate_exceptional_list_cmpl.subcode = subcode; - if(length > sizeof(param.update_duplicate_exceptional_list_cmpl.device_info)) { - length = sizeof(param.update_duplicate_exceptional_list_cmpl.device_info); - } - param.update_duplicate_exceptional_list_cmpl.length = length; - memcpy(param.update_duplicate_exceptional_list_cmpl.device_info, device_info, length); - ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); - - if (ret != BT_STATUS_SUCCESS) { - BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); - } -} - -static void btc_ble_update_duplicate_exceptional_list(uint8_t subcode, uint32_t info_type, BD_ADDR device_info, - tBTA_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK p_update_duplicate_ignore_list_cback) -{ - BTA_DmUpdateDuplicateExceptionalList(subcode, info_type, device_info, p_update_duplicate_ignore_list_cback); -} - #if (BLE_42_ADV_EN == TRUE) static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBTA_START_ADV_CMPL_CBACK start_adv_cback) { @@ -735,6 +706,38 @@ static void btc_stop_scan_callback(tBTA_STATUS status) } #endif // #if (BLE_42_SCAN_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) + +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) +void btc_update_duplicate_exceptional_list_callback(tBTA_STATUS status, uint8_t subcode, uint32_t length, uint8_t *device_info) +{ + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_COMPLETE_EVT; + param.update_duplicate_exceptional_list_cmpl.status = status; + param.update_duplicate_exceptional_list_cmpl.subcode = subcode; + if(length > sizeof(param.update_duplicate_exceptional_list_cmpl.device_info)) { + length = sizeof(param.update_duplicate_exceptional_list_cmpl.device_info); + } + param.update_duplicate_exceptional_list_cmpl.length = length; + memcpy(param.update_duplicate_exceptional_list_cmpl.device_info, device_info, length); + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_ble_update_duplicate_exceptional_list(uint8_t subcode, uint32_t info_type, BD_ADDR device_info, + tBTA_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK p_update_duplicate_ignore_list_cback) +{ + BTA_DmUpdateDuplicateExceptionalList(subcode, info_type, device_info, p_update_duplicate_ignore_list_cback); +} +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) + void btc_update_conn_param_callback (UINT8 status, BD_ADDR bd_addr, tBTM_LE_UPDATE_CONN_PRAMS *update_conn_params) { esp_ble_gap_cb_param_t param; @@ -1155,6 +1158,10 @@ void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, #if (BLE_FEAT_CTE_EN == TRUE) param.period_adv_report.params.cte_type = params->period_adv_report.cte_type; #endif // #if (BLE_FEAT_CTE_EN == TRUE) + #if (BT_BLE_FEAT_PAWR_EN == TRUE) + param.period_adv_report.params.periodic_evt_counter = params->period_adv_report.periodic_evt_cnt; + param.period_adv_report.params.subevt = params->period_adv_report.subevt; + #endif // (BT_BLE_FEAT_PAWR_EN == TRUE) param.period_adv_report.params.data_status = params->period_adv_report.data_status; param.period_adv_report.params.data_length = params->period_adv_report.data_length; if (params->period_adv_report.data) { @@ -1179,6 +1186,12 @@ void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.periodic_adv_sync_estab.adv_phy = params->sync_estab.adv_phy; param.periodic_adv_sync_estab.period_adv_interval = params->sync_estab.period_adv_interval; param.periodic_adv_sync_estab.adv_clk_accuracy = params->sync_estab.adv_clk_accuracy; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + param.periodic_adv_sync_estab.num_subevt = params->sync_estab.num_subevt; + param.periodic_adv_sync_estab.subevt_interval = params->sync_estab.subevt_interval; + param.periodic_adv_sync_estab.rsp_slot_delay = params->sync_estab.rsp_slot_delay; + param.periodic_adv_sync_estab.rsp_slot_spacing = params->sync_estab.rsp_slot_spacing; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) break; } #endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) @@ -1287,12 +1300,198 @@ void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.host_feature.status = btc_btm_status_to_esp_status(params->status); break; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + case BTA_BLE_GAP_SET_PERIODIC_ADV_SUBEVT_DATA_EVT: + msg.act = ESP_GAP_BLE_SET_PERIODIC_ADV_SUBEVT_DATA_EVT; + param.pa_subevt_data_evt.status = btc_btm_status_to_esp_status(params->pa_subevt_data_evt.status); + param.pa_subevt_data_evt.adv_handle = params->pa_subevt_data_evt.adv_handle; + break; + case BTA_BLE_GAP_SET_PERIODIC_ADV_RESPONSE_DATA_EVT: + msg.act = ESP_GAP_BLE_SET_PERIODIC_ADV_RESPONSE_DATA_EVT; + param.pa_rsp_data_evt.status = btc_btm_status_to_esp_status(params->pa_rsp_data_evt.status); + param.pa_rsp_data_evt.sync_handle = params->pa_rsp_data_evt.sync_handle; + break; + case BTA_BLE_GAP_SET_PERIODIC_SYNC_SUBEVT_EVT: + msg.act = ESP_GAP_BLE_SET_PERIODIC_SYNC_SUBEVT_EVT; + param.pa_sync_subevt_evt.status = btc_btm_status_to_esp_status(params->pa_sync_subevt_evt.status); + param.pa_sync_subevt_evt.sync_handle = params->pa_sync_subevt_evt.sync_handle; + break; + case BTA_BLE_GAP_PERIODIC_ADV_SUBEVT_DATA_REQUEST_EVT: + msg.act = ESP_GAP_BLE_PERIODIC_ADV_SUBEVT_DATA_REQUEST_EVT; + param.pa_subevt_data_req_evt.adv_handle = params->pa_subevent_data_req_evt.adv_handle; + param.pa_subevt_data_req_evt.subevt_start = params->pa_subevent_data_req_evt.subevt_start; + param.pa_subevt_data_req_evt.subevt_data_count = params->pa_subevent_data_req_evt.subevt_data_count; + break; + case BTA_BLE_GAP_PERIODIC_ADV_RESPONSE_REPORT_EVT: + msg.act = ESP_GAP_BLE_PERIODIC_ADV_RESPONSE_REPORT_EVT; + param.pa_rsp_rpt_evt.adv_handle = params->pa_rsp_rpt_evt.adv_handle; + param.pa_rsp_rpt_evt.subevt = params->pa_rsp_rpt_evt.subevt; + param.pa_rsp_rpt_evt.tx_status = params->pa_rsp_rpt_evt.tx_status; + param.pa_rsp_rpt_evt.num_rsp = params->pa_rsp_rpt_evt.num_rsp; + param.pa_rsp_rpt_evt.pa_rsp_info = (esp_ble_pa_rsp_info *)params->pa_rsp_rpt_evt.rsp_data_info; + break; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + case BTA_BLE_GAP_CS_READ_LOCAL_SUPP_CAPS_EVT: + msg.act = ESP_GAP_BLE_CS_READ_LOCAL_SUPP_CAPS_EVT; + param.cs_read_local_supp_caps.status = params->cs_read_local_supp_caps.status; + param.cs_read_local_supp_caps.conn_handle = params->cs_read_local_supp_caps.conn_handle; + param.cs_read_local_supp_caps.num_config_supported = params->cs_read_local_supp_caps.num_config_supported; + param.cs_read_local_supp_caps.max_consecutive_proc_supported = params->cs_read_local_supp_caps.max_consecutive_proc_supported; + param.cs_read_local_supp_caps.num_ant_supported = params->cs_read_local_supp_caps.num_ant_supported; + param.cs_read_local_supp_caps.max_ant_paths_supported= params->cs_read_local_supp_caps.max_ant_paths_supported; + param.cs_read_local_supp_caps.roles_supported = params->cs_read_local_supp_caps.roles_supported; + param.cs_read_local_supp_caps.modes_supported = params->cs_read_local_supp_caps.modes_supported; + param.cs_read_local_supp_caps.rtt_capability = params->cs_read_local_supp_caps.rtt_capability; + param.cs_read_local_supp_caps.rtt_aa_only_n = params->cs_read_local_supp_caps.rtt_aa_only_n; + param.cs_read_local_supp_caps.rtt_sounding_n = params->cs_read_local_supp_caps.rtt_sounding_n; + param.cs_read_local_supp_caps.rtt_random_payload_n = params->cs_read_local_supp_caps.rtt_random_payload_n; + param.cs_read_local_supp_caps.NADM_sounding_capability = params->cs_read_local_supp_caps.NADM_sounding_capability; + param.cs_read_local_supp_caps.NADM_random_capability = params->cs_read_local_supp_caps.NADM_random_capability; + param.cs_read_local_supp_caps.cs_sync_phys_supported = params->cs_read_local_supp_caps.cs_sync_phys_supported; + param.cs_read_local_supp_caps.subfeatures_supported = params->cs_read_local_supp_caps.subfeatures_supported; + param.cs_read_local_supp_caps.T_IP1_times_supported = params->cs_read_local_supp_caps.T_IP1_times_supported; + param.cs_read_local_supp_caps.T_IP2_times_supported = params->cs_read_local_supp_caps.T_IP2_times_supported; + param.cs_read_local_supp_caps.T_FCS_times_supported = params->cs_read_local_supp_caps.T_FCS_times_supported; + param.cs_read_local_supp_caps.T_PM_times_supported = params->cs_read_local_supp_caps.T_PM_times_supported; + param.cs_read_local_supp_caps.T_SW_times_supported = params->cs_read_local_supp_caps.T_SW_times_supported; + param.cs_read_local_supp_caps.TX_SNR_capability = params->cs_read_local_supp_caps.TX_SNR_capability; + break; + case BTA_BLE_GAP_CS_WRITE_CACHED_REMOTE_SUPP_CAPS_EVT: + msg.act = ESP_GAP_BLE_CS_WRITE_CACHED_REMOTE_SUPP_CAPS_EVT; + param.cs_write_cached_remote_supp_caps.status = params->cs_write_cached_remote_supp_caps.status; + param.cs_write_cached_remote_supp_caps.conn_handle = params->cs_write_cached_remote_supp_caps.conn_handle; + break; + case BTA_BLE_GAP_CS_SET_DEFAULT_SETTINGS_EVT: + msg.act = ESP_GAP_BLE_CS_SET_DEFAULT_SETTINGS_EVT; + param.cs_set_default_settings.status = params->cs_set_default_settings.status; + param.cs_set_default_settings.conn_handle = params->cs_set_default_settings.conn_handle; + break; + case BTA_BLE_GAP_CS_WRITE_CACHED_REMOTE_FAE_TAB_EVT: + msg.act = ESP_GAP_BLE_CS_WRITE_CACHED_REMOTE_FAE_TABLE_EVT; + param.cs_write_cached_remote_fae_tab.status = params->cs_write_cached_remote_fae_tab.status; + param.cs_write_cached_remote_fae_tab.conn_handle = params->cs_write_cached_remote_fae_tab.conn_handle; + break; + case BTA_BLE_GAP_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT: + msg.act = ESP_GAP_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT; + param.cs_read_remote_supp_caps.status = params->cs_read_remote_supp_caps.status; + param.cs_read_remote_supp_caps.conn_handle = params->cs_read_remote_supp_caps.conn_handle; + param.cs_read_remote_supp_caps.num_config_supported = params->cs_read_remote_supp_caps.num_config_supported; + param.cs_read_remote_supp_caps.max_consecutive_proc_supported = params->cs_read_remote_supp_caps.max_consecutive_proc_supported; + param.cs_read_remote_supp_caps.num_ant_supported = params->cs_read_remote_supp_caps.num_ant_supported; + param.cs_read_remote_supp_caps.max_ant_paths_supported = params->cs_read_remote_supp_caps.max_ant_paths_supported; + param.cs_read_remote_supp_caps.roles_supported = params->cs_read_remote_supp_caps.roles_supported; + param.cs_read_remote_supp_caps.modes_supported = params->cs_read_remote_supp_caps.modes_supported; + param.cs_read_remote_supp_caps.rtt_capability = params->cs_read_remote_supp_caps.rtt_capability; + param.cs_read_remote_supp_caps.rtt_aa_only_n = params->cs_read_remote_supp_caps.rtt_aa_only_n; + param.cs_read_remote_supp_caps.rtt_sounding_n = params->cs_read_remote_supp_caps.rtt_sounding_n; + param.cs_read_remote_supp_caps.rtt_random_payload_n = params->cs_read_remote_supp_caps.rtt_random_payload_n; + param.cs_read_remote_supp_caps.NADM_sounding_capability = params->cs_read_remote_supp_caps.NADM_sounding_capability; + param.cs_read_remote_supp_caps.NADM_random_capability = params->cs_read_remote_supp_caps.NADM_random_capability; + param.cs_read_remote_supp_caps.cs_sync_phys_supported = params->cs_read_remote_supp_caps.cs_sync_phys_supported; + param.cs_read_remote_supp_caps.subfeatures_supported = params->cs_read_remote_supp_caps.subfeatures_supported; + param.cs_read_remote_supp_caps.T_IP1_times_supported = params->cs_read_remote_supp_caps.T_IP1_times_supported; + param.cs_read_remote_supp_caps.T_IP2_times_supported = params->cs_read_remote_supp_caps.T_IP2_times_supported; + param.cs_read_remote_supp_caps.T_FCS_times_supported = params->cs_read_remote_supp_caps.T_FCS_times_supported; + param.cs_read_remote_supp_caps.T_PM_times_supported = params->cs_read_remote_supp_caps.T_PM_times_supported; + param.cs_read_remote_supp_caps.T_SW_times_supported = params->cs_read_remote_supp_caps.T_SW_times_supported; + param.cs_read_remote_supp_caps.TX_SNR_capability = params->cs_read_remote_supp_caps.TX_SNR_capability; + break; + case BTA_BLE_GAP_CS_SET_CHANNEL_CLASS_CMPL_EVT: + msg.act = ESP_GAP_BLE_CS_SET_CHANNEL_CLASS_CMPL_EVT; + param.cs_set_channel_class.status = params->status; + break; + case BTA_BLE_GAP_CS_PROC_PARAMS_CMPL_EVT: + msg.act = ESP_GAP_BLE_CS_SET_PROC_PARAMS_CMPL_EVT; + param.cs_set_proc_params.status = params->cs_set_proc_params.status; + param.cs_set_proc_params.conn_handle = params->cs_set_proc_params.conn_handle; + break; + case BTA_BLE_GAP_CS_PROC_ENABLE_CMPL_EVT: + msg.act = ESP_GAP_BLE_CS_PROC_ENABLE_CMPL_EVT; + param.cs_proc_enable.status = params->cs_proc_en.status; + param.cs_proc_enable.conn_handle = params->cs_proc_en.conn_handle; + param.cs_proc_enable.config_id = params->cs_proc_en.config_id; + param.cs_proc_enable.state = params->cs_proc_en.state; + param.cs_proc_enable.tone_ant_config_select = params->cs_proc_en.tone_ant_config_select; + param.cs_proc_enable.select_tx_power = params->cs_proc_en.select_tx_power; + param.cs_proc_enable.subevent_Len = params->cs_proc_en.subevent_Len; + param.cs_proc_enable.subevents_per_event = params->cs_proc_en.subevents_per_event; + param.cs_proc_enable.subevent_interval = params->cs_proc_en.subevent_interval; + param.cs_proc_enable.event_interval = params->cs_proc_en.event_interval; + param.cs_proc_enable.procedure_interval = params->cs_proc_en.procedure_interval; + param.cs_proc_enable.procedure_count = params->cs_proc_en.procedure_count; + param.cs_proc_enable.max_procedure_len = params->cs_proc_en.max_procedure_len; + break; + case BTA_BLE_GAP_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT: + msg.act = ESP_GAP_BLE_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT; + param.cs_read_remote_fae_tab.status = params->cs_read_remote_fae_tab.status; + param.cs_read_remote_fae_tab.conn_handle = params->cs_read_remote_fae_tab.conn_handle; + memcpy(param.cs_read_remote_fae_tab.remote_fae_table, params->cs_read_remote_fae_tab.remote_fae_table, 72); + break; + case BTA_BLE_GAP_CS_SECURITY_ENABLE_CMPL_EVT: + msg.act = ESP_GAP_BLE_CS_SECURITY_ENABLE_CMPL_EVT; + param.cs_security_enable.status = params->cs_security_enable.status; + param.cs_security_enable.conn_handle = params->cs_security_enable.conn_handle; + break; + case BTA_BLE_GAP_CS_CONFIG_CMPL_EVT: + msg.act = ESP_GAP_BLE_CS_CONFIG_CMPL_EVT; + param.cs_config_update.status = params->cs_config_update.status; + param.cs_config_update.conn_handle = params->cs_config_update.conn_handle; + param.cs_config_update.config_id = params->cs_config_update.config_id; + param.cs_config_update.action = params->cs_config_update.action; + param.cs_config_update.main_mode_type = params->cs_config_update.main_mode_type; + param.cs_config_update.sub_mode_type = params->cs_config_update.sub_mode_type; + param.cs_config_update.min_main_mode_steps = params->cs_config_update.min_main_mode_steps; + param.cs_config_update.max_main_mode_steps = params->cs_config_update.max_main_mode_steps; + param.cs_config_update.main_mode_repetition = params->cs_config_update.main_mode_repetition; + param.cs_config_update.mode_0_steps = params->cs_config_update.mode_0_steps; + param.cs_config_update.role = params->cs_config_update.role; + param.cs_config_update.rtt_type = params->cs_config_update.rtt_type; + param.cs_config_update.cs_sync_phy = params->cs_config_update.cs_sync_phy; + memcpy(param.cs_config_update.channel_map, params->cs_config_update.channel_map, 10); + param.cs_config_update.channel_map_repetition = params->cs_config_update.channel_map_repetition; + param.cs_config_update.channel_selection_type = params->cs_config_update.channel_selection_type; + param.cs_config_update.ch3c_shape = params->cs_config_update.ch3c_shape; + param.cs_config_update.ch3c_jump = params->cs_config_update.ch3c_jump; + param.cs_config_update.reserved = params->cs_config_update.reserved; + param.cs_config_update.t_ip1_time = params->cs_config_update.t_ip1_time; + param.cs_config_update.t_ip2_time = params->cs_config_update.t_ip2_time; + param.cs_config_update.t_fcs_time = params->cs_config_update.t_fcs_time; + param.cs_config_update.t_pm_time = params->cs_config_update.t_pm_time; + break; + case BTA_BLE_GAP_CS_SUBEVENT_RESULT_EVT: + msg.act = ESP_GAP_BLE_CS_SUBEVENT_RESULT_EVT; + param.cs_subevt_result.conn_handle = params->cs_subevt_result.conn_handle; + param.cs_subevt_result.config_id = params->cs_subevt_result.config_id; + param.cs_subevt_result.start_acl_conn_event_counter = params->cs_subevt_result.start_acl_conn_event_counter; + param.cs_subevt_result.procedure_counter = params->cs_subevt_result.procedure_counter; + param.cs_subevt_result.frequency_compensation = params->cs_subevt_result.frequency_compensation; + param.cs_subevt_result.reference_power_level = params->cs_subevt_result.reference_power_level; + param.cs_subevt_result.procedure_done_status = params->cs_subevt_result.procedure_done_status; + param.cs_subevt_result.subevent_done_status = params->cs_subevt_result.subevent_done_status; + param.cs_subevt_result.abort_reason = params->cs_subevt_result.abort_reason; + param.cs_subevt_result.num_ant_paths = params->cs_subevt_result.num_ant_paths; + param.cs_subevt_result.num_steps_reported = params->cs_subevt_result.num_steps_reported; + param.cs_subevt_result.step_info = (esp_ble_cs_step_info *)params->cs_subevt_result.step_info; + break; + case BTA_BLE_GAP_CS_SUBEVENT_RESULT_CONTINUE_EVT: + msg.act = ESP_GAP_BLE_CS_SUBEVENT_RESULT_CONTINUE_EVT; + param.cs_subevt_result_continue.conn_handle = params->cs_subevt_result_continue.conn_handle; + param.cs_subevt_result_continue.config_id = params->cs_subevt_result_continue.config_id; + param.cs_subevt_result_continue.proc_done_status = params->cs_subevt_result_continue.proc_done_status; + param.cs_subevt_result_continue.subevt_done_status = params->cs_subevt_result_continue.subevt_done_status; + param.cs_subevt_result_continue.abort_reason = params->cs_subevt_result_continue.abort_reason; + param.cs_subevt_result_continue.num_ant_paths = params->cs_subevt_result_continue.num_ant_paths; + param.cs_subevt_result_continue.num_steps_reported = params->cs_subevt_result_continue.num_steps_reported; + param.cs_subevt_result_continue.step_info = (esp_ble_cs_step_info *)params->cs_subevt_result_continue.step_info; + break; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) default: break; } ret = btc_transfer_context(&msg, ¶m, - sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + sizeof(esp_ble_gap_cb_param_t), btc_gap_ble_cb_deep_copy, btc_gap_ble_cb_deep_free); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); @@ -1605,7 +1804,7 @@ static void btc_ble_stop_advertising(tBTA_START_STOP_ADV_CMPL_CBACK *stop_adv_cb { bool stop_adv = false; - BTA_DmBleBroadcast(stop_adv, stop_adv_cb); + BTA_DmBleAdvStop(stop_adv, stop_adv_cb); } #endif // #if (BLE_42_ADV_EN == TRUE) @@ -1978,6 +2177,58 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + case BTC_GAP_BLE_SET_PA_SUBEVT_DATA: { + btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src; + btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest; + if (src->per_adv_subevent_data_params.subevent_params) { + uint16_t params_len = src->per_adv_subevent_data_params.num_subevents_with_data * sizeof(esp_ble_subevent_params); + dst->per_adv_subevent_data_params.subevent_params = osi_malloc(params_len); + if (dst->per_adv_subevent_data_params.subevent_params) { + for (uint8_t i = 0; i < src->per_adv_subevent_data_params.num_subevents_with_data; i++) + { + /* Fix: Use sizeof(esp_ble_subevent_params) instead of params_len to prevent buffer overflow */ + memcpy(&dst->per_adv_subevent_data_params.subevent_params[i], + &src->per_adv_subevent_data_params.subevent_params[i], + sizeof(esp_ble_subevent_params)); + dst->per_adv_subevent_data_params.subevent_params[i].subevent_data = osi_malloc(src->per_adv_subevent_data_params.subevent_params[i].subevent_data_len); + if (dst->per_adv_subevent_data_params.subevent_params[i].subevent_data) { + memcpy(dst->per_adv_subevent_data_params.subevent_params[i].subevent_data, src->per_adv_subevent_data_params.subevent_params[i].subevent_data, src->per_adv_subevent_data_params.subevent_params[i].subevent_data_len); + } else if (src->per_adv_subevent_data_params.subevent_params[i].subevent_data_len != 0) { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + } + } + break; + } + case BTC_GAP_BLE_SET_PA_RSP_DATA: { + btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src; + btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest; + if (src->per_adv_response_data_params.response_data && src->per_adv_response_data_params.response_data_len) { + dst->per_adv_response_data_params.response_data = osi_malloc(src->per_adv_response_data_params.response_data_len); + if (dst->per_adv_response_data_params.response_data) { + memcpy(dst->per_adv_response_data_params.response_data, src->per_adv_response_data_params.response_data, src->per_adv_response_data_params.response_data_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + } + case BTC_GAP_BLE_SET_PA_SYNC_SUBEVT: { + btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src; + btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest; + if (src->per_sync_subevent_params.subevent && src->per_sync_subevent_params.num_subevents_to_sync) { + dst->per_sync_subevent_params.subevent = osi_malloc(src->per_sync_subevent_params.num_subevents_to_sync); + if (dst->per_sync_subevent_params.subevent) { + memcpy(dst->per_sync_subevent_params.subevent, src->per_sync_subevent_params.subevent, src->per_sync_subevent_params.num_subevents_to_sync); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + } +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) default: BTC_TRACE_ERROR("Unhandled deep copy %d\n", msg->act); break; @@ -2014,8 +2265,91 @@ void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + case ESP_GAP_BLE_PERIODIC_ADV_RESPONSE_REPORT_EVT: + if (src->pa_rsp_rpt_evt.pa_rsp_info) { + // num_rsp is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + dst->pa_rsp_rpt_evt.num_rsp = src->pa_rsp_rpt_evt.num_rsp; + + dst->pa_rsp_rpt_evt.pa_rsp_info = osi_malloc(src->pa_rsp_rpt_evt.num_rsp * sizeof(esp_ble_pa_rsp_info)); + if (dst->pa_rsp_rpt_evt.pa_rsp_info) { + for (UINT8 i = 0; i < src->pa_rsp_rpt_evt.num_rsp; i++) + { + dst->pa_rsp_rpt_evt.pa_rsp_info[i].tx_power = src->pa_rsp_rpt_evt.pa_rsp_info[i].tx_power; + dst->pa_rsp_rpt_evt.pa_rsp_info[i].rssi = src->pa_rsp_rpt_evt.pa_rsp_info[i].rssi; + dst->pa_rsp_rpt_evt.pa_rsp_info[i].cte_type = src->pa_rsp_rpt_evt.pa_rsp_info[i].cte_type; + dst->pa_rsp_rpt_evt.pa_rsp_info[i].rsp_slot = src->pa_rsp_rpt_evt.pa_rsp_info[i].rsp_slot; + dst->pa_rsp_rpt_evt.pa_rsp_info[i].data_status = src->pa_rsp_rpt_evt.pa_rsp_info[i].data_status; + // data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + dst->pa_rsp_rpt_evt.pa_rsp_info[i].data_len = src->pa_rsp_rpt_evt.pa_rsp_info[i].data_len; + if (src->pa_rsp_rpt_evt.pa_rsp_info[i].data_len && src->pa_rsp_rpt_evt.pa_rsp_info[i].data) { + dst->pa_rsp_rpt_evt.pa_rsp_info[i].data = osi_malloc(src->pa_rsp_rpt_evt.pa_rsp_info[i].data_len); + if (dst->pa_rsp_rpt_evt.pa_rsp_info[i].data) { + memcpy(dst->pa_rsp_rpt_evt.pa_rsp_info[i].data, src->pa_rsp_rpt_evt.pa_rsp_info[i].data, src->pa_rsp_rpt_evt.pa_rsp_info[i].data_len); + } else { + BTC_TRACE_ERROR("%s, data, no enough memory for data_len %d at index %d", __func__, dst->pa_rsp_rpt_evt.pa_rsp_info[i].data_len, i); + dst->pa_rsp_rpt_evt.pa_rsp_info[i].data_len = 0; + } + } else { + dst->pa_rsp_rpt_evt.pa_rsp_info[i].data = NULL; + } + } + } else { + BTC_TRACE_ERROR("%s, pa_rsp_info, no enough memory for array size %d", __func__, src->pa_rsp_rpt_evt.num_rsp); + } + } + break; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + case BTA_BLE_GAP_CS_SUBEVENT_RESULT_EVT: + if (src->cs_subevt_result.step_info) { + dst->cs_subevt_result.step_info = osi_malloc(src->cs_subevt_result.num_steps_reported * sizeof(esp_ble_cs_step_info)); + if (dst->cs_subevt_result.step_info) { + for (UINT8 i = 0; i < src->cs_subevt_result.num_steps_reported; i++) + { + dst->cs_subevt_result.step_info[i].step_mode = src->cs_subevt_result.step_info[i].step_mode; + dst->cs_subevt_result.step_info[i].step_channel = src->cs_subevt_result.step_info[i].step_channel; + dst->cs_subevt_result.step_info[i].step_data_len = src->cs_subevt_result.step_info[i].step_data_len; + if (src->cs_subevt_result.step_info[i].step_data_len) { + dst->cs_subevt_result.step_info[i].data = osi_malloc(src->cs_subevt_result.step_info[i].step_data_len); + if (dst->cs_subevt_result.step_info[i].data) { + memcpy(dst->cs_subevt_result.step_info[i].data, src->cs_subevt_result.step_info[i].data, src->cs_subevt_result.step_info[i].step_data_len); + } else { + BTC_TRACE_ERROR("%s, data, no enough memory.", __func__); + } + } + } + } else { + BTC_TRACE_ERROR("%s, pa_rsp_info, no enough memory.", __func__); + } + } + break; + case BTA_BLE_GAP_CS_SUBEVENT_RESULT_CONTINUE_EVT: + if (src->cs_subevt_result_continue.step_info) { + dst->cs_subevt_result_continue.step_info = osi_malloc(src->cs_subevt_result_continue.num_steps_reported * sizeof(esp_ble_cs_step_info)); + if (dst->cs_subevt_result_continue.step_info) { + for (UINT8 i = 0; i < src->cs_subevt_result_continue.num_steps_reported; i++) + { + dst->cs_subevt_result_continue.step_info[i].step_mode = src->cs_subevt_result_continue.step_info[i].step_mode; + dst->cs_subevt_result_continue.step_info[i].step_channel = src->cs_subevt_result_continue.step_info[i].step_channel; + dst->cs_subevt_result_continue.step_info[i].step_data_len = src->cs_subevt_result_continue.step_info[i].step_data_len; + if (src->cs_subevt_result_continue.step_info[i].step_data_len) { + dst->cs_subevt_result_continue.step_info[i].data = osi_malloc(src->cs_subevt_result_continue.step_info[i].step_data_len); + if (dst->cs_subevt_result_continue.step_info[i].data) { + memcpy(dst->cs_subevt_result_continue.step_info[i].data, src->cs_subevt_result_continue.step_info[i].data, src->cs_subevt_result.step_info[i].step_data_len); + } else { + BTC_TRACE_ERROR("%s, data, no enough memory.", __func__); + } + } + } + } else { + BTC_TRACE_ERROR("%s, pa_rsp_info, no enough memory.", __func__); + } + } + break; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) default: - BTC_TRACE_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); + // BTC_TRACE_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); break; } } @@ -2136,6 +2470,35 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) break; } break; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + case BTC_GAP_BLE_SET_PA_SUBEVT_DATA: { + struct per_adv_subevent_data_params_args *per_adv_subevent_data_params = &((btc_ble_5_gap_args_t *)msg->arg)->per_adv_subevent_data_params; + if (per_adv_subevent_data_params->subevent_params) { + for (uint8_t i = 0; i < per_adv_subevent_data_params->num_subevents_with_data; i++) + { + if (per_adv_subevent_data_params->subevent_params[i].subevent_data) { + osi_free(per_adv_subevent_data_params->subevent_params[i].subevent_data); + } + } + osi_free(per_adv_subevent_data_params->subevent_params); + } + break; + } + case BTC_GAP_BLE_SET_PA_RSP_DATA: { + uint8_t *response_data = ((btc_ble_5_gap_args_t *)msg->arg)->per_adv_response_data_params.response_data; + if (response_data) { + osi_free(response_data); + } + break; + } + case BTC_GAP_BLE_SET_PA_SYNC_SUBEVT: { + uint8_t *subevent = ((btc_ble_5_gap_args_t *)msg->arg)->per_sync_subevent_params.subevent; + if (subevent) { + osi_free(subevent); + } + break; + } +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) default: BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); break; @@ -2167,6 +2530,52 @@ void btc_gap_ble_cb_deep_free(btc_msg_t *msg) } break; } +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + case ESP_GAP_BLE_PERIODIC_ADV_RESPONSE_REPORT_EVT: + esp_ble_pa_rsp_info *pa_rsp_info = ((esp_ble_gap_cb_param_t *)msg->arg)->pa_rsp_rpt_evt.pa_rsp_info; + if (pa_rsp_info) { + uint8_t num_rsp = ((esp_ble_gap_cb_param_t *)msg->arg)->pa_rsp_rpt_evt.num_rsp; + for (UINT8 i = 0; i < num_rsp; i++) { + if (pa_rsp_info[i].data) { + osi_free(pa_rsp_info[i].data); + } + } + osi_free(pa_rsp_info); + } + break; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + case BTA_BLE_GAP_CS_SUBEVENT_RESULT_EVT: + { + esp_ble_cs_step_info *step_info = ((esp_ble_gap_cb_param_t *)msg->arg)->cs_subevt_result.step_info; + if (step_info) { + uint8_t num_step = ((esp_ble_gap_cb_param_t *)msg->arg)->cs_subevt_result.num_steps_reported; + for (uint8_t i = 0; i < num_step; i++) + { + if (step_info[i].data) { + osi_free(step_info[i].data); + } + } + osi_free(step_info); + } + } + break; + case BTA_BLE_GAP_CS_SUBEVENT_RESULT_CONTINUE_EVT: + { + esp_ble_cs_step_info *step_info = ((esp_ble_gap_cb_param_t *)msg->arg)->cs_subevt_result_continue.step_info; + if (step_info) { + uint8_t num_step = ((esp_ble_gap_cb_param_t *)msg->arg)->cs_subevt_result_continue.num_steps_reported; + for (uint8_t i = 0; i < num_step; i++) + { + if (step_info[i].data) { + osi_free(step_info[i].data); + } + } + osi_free(step_info); + } + } + break; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) default: BTC_TRACE_DEBUG("Unhandled deep free %d", msg->act); break; @@ -2289,13 +2698,17 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) btc_scan_rsp_data_raw_callback); break; #endif // #if (BLE_42_ADV_EN == TRUE) +#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) + +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) case BTC_GAP_BLE_UPDATE_DUPLICATE_SCAN_EXCEPTIONAL_LIST: btc_ble_update_duplicate_exceptional_list(arg->update_duplicate_exceptional_list.subcode, arg->update_duplicate_exceptional_list.info_type, arg->update_duplicate_exceptional_list.device_info, btc_update_duplicate_exceptional_list_callback); break; -#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) + #if (SMP_INCLUDED == TRUE) case BTC_GAP_BLE_SET_ENCRYPTION_EVT: { BD_ADDR bd_addr; @@ -2453,7 +2866,10 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) params.secondary_phy = arg_5->ext_adv_set_params.params.secondary_phy; params.sid = arg_5->ext_adv_set_params.params.sid; params.scan_req_notif = arg_5->ext_adv_set_params.params.scan_req_notif; - +#if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) + params.primary_adv_phy_options = arg_5->ext_adv_set_params.params.primary_adv_phy_options; + params.secondary_adv_phy_options= arg_5->ext_adv_set_params.params.secondary_adv_phy_options; +#endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) memcpy(params.peer_addr, arg_5->ext_adv_set_params.params.peer_addr, sizeof(BD_ADDR)); BTC_TRACE_DEBUG("BTC_GAP_BLE_SET_EXT_ADV_PARAMS"); @@ -2517,6 +2933,13 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) params.interval_min = arg_5->peridic_adv_set_params.params.interval_min; params.interval_max = arg_5->peridic_adv_set_params.params.interval_max; params.properties = arg_5->peridic_adv_set_params.params.properties; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + params.num_subevents = arg_5->peridic_adv_set_params.params.num_subevents; + params.subevent_interval = arg_5->peridic_adv_set_params.params.subevent_interval; + params.rsp_slot_delay = arg_5->peridic_adv_set_params.params.rsp_slot_delay; + params.rsp_slot_spacing = arg_5->peridic_adv_set_params.params.rsp_slot_spacing; + params.num_rsp_slots = arg_5->peridic_adv_set_params.params.num_rsp_slots; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) BTC_TRACE_DEBUG("BTC_GAP_BLE_SET_PERIODIC_ADV_PARAMS"); BTA_DmBleGapPeriodicAdvSetParams(arg_5->peridic_adv_set_params.instance, ¶ms); @@ -2725,6 +3148,62 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) BTA_DmBleGapSetHostFeature(arg_5->set_host_feature_params.bit_num, arg_5->set_host_feature_params.bit_val); break; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + case BTC_GAP_BLE_SET_PA_SUBEVT_DATA: + BTA_DmBleGapSetPASubevtData(arg_5->per_adv_subevent_data_params.adv_handle, arg_5->per_adv_subevent_data_params.num_subevents_with_data, (uint8_t *)(arg_5->per_adv_subevent_data_params.subevent_params)); + break; + case BTC_GAP_BLE_SET_PA_RSP_DATA: + BTA_DmBleGapSetPeriodicAdvRspData(arg_5->per_adv_response_data_params.sync_handle, arg_5->per_adv_response_data_params.request_event, arg_5->per_adv_response_data_params.request_subevent, + arg_5->per_adv_response_data_params.response_subevent, arg_5->per_adv_response_data_params.response_slot, arg_5->per_adv_response_data_params.response_data_len, arg_5->per_adv_response_data_params.response_data); + break; + case BTC_GAP_BLE_SET_PA_SYNC_SUBEVT: + BTA_DmBleGapSetPeriodicSyncSubevt(arg_5->per_sync_subevent_params.sync_handle, arg_5->per_sync_subevent_params.periodic_adv_properties, arg_5->per_sync_subevent_params.num_subevents_to_sync, arg_5->per_sync_subevent_params.subevent); + break; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + case BTC_GAP_BLE_CS_READ_LOCAL_SUPPORTED_CAPS: + BTA_DmBleGapReadLocalSupportedCaps(); + break; + case BTC_GAP_BLE_CS_READ_REMOTE_SUPPORTED_CAPS: + BTA_DmBleGapReadRemoteSupportedCaps(arg_5->cs_read_remote_supp_caps.conn_handle); + break; + case BTC_GAP_BLE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPS: + BTA_DmBleGapWriteCachedRemoteSupportedCaps((tBTA_DM_CS_WRITE_CACHED_REMOTE_SUPP_CAPS *)&arg_5->cs_write_cached_remote_supp_caps); + break; + case BTC_GAP_BLE_CS_SECURITY_ENABLE: + BTA_DmBleGapCsSecurityEnable(arg_5->cs_security_enable.conn_handle); + break; + case BTC_GAP_BLE_CS_SET_DEFAULT_SETTINGS: + BTA_DmBleGapCsSetDefaultSetting(arg_5->cs_set_default_settings_params.conn_handle, arg_5->cs_set_default_settings_params.role_enable, + arg_5->cs_set_default_settings_params.cs_sync_ant_selection, arg_5->cs_set_default_settings_params.max_tx_power); + break; + case BTC_GAP_BLE_CS_READ_REMOTE_FAE_TABLE: + BTA_DmBleGapCsReadRemoteFaeTable(arg_5->cs_read_remote_tab.conn_handle); + break; + case BTC_GAP_BLE_CS_WRITE_CACHED_REMOTE_FAE_TABLE: + BTA_DmBleGapWriteCachedRemoteFaeTable(arg_5->cs_write_cached_remote_fae_table_params.conn_handle, &arg_5->cs_write_cached_remote_fae_table_params.remote_fae_table[0], 72); + break; + case BTC_GAP_BLE_CS_CREATE_CONFIG: + BTA_DmBleGapCsCreateConfig((tBTA_DM_CS_CREATE_CONFIG_PARAMS*)&arg_5->cs_create_config_params); + break; + case BTC_GAP_BLE_CS_REMOVE_CONFIG: + BTA_DmBleGapCsRemoveConfig(arg_5->cs_remove_config_params.conn_handle, arg_5->cs_remove_config_params.config_id); + break; + case BTC_GAP_BLE_CS_SET_CAHNNEL_CLASSIFICATION: + BTA_DmBleGapCsSetChannelClass(&arg_5->cs_set_channel_class_params.channel_class[0], 10); + break; + case BTC_GAP_BLE_CS_SET_PROCEDURE_PARAMS: + BTA_DmBleGapCsSetProcPatams((tBTA_DM_CS_SET_PROC_PARAMS *)&arg_5->cs_set_procedure_params); + break; + case BTC_GAP_BLE_CS_PROCEDURE_ENABLE: + BTA_DmBleGapCsProcEnable(arg_5->cs_procedure_enable_params.conn_handle, arg_5->cs_procedure_enable_params.config_id, arg_5->cs_procedure_enable_params.enable); + break; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + case BTC_GAP_BLE_ACT_SET_KEY_MATERIAL: + BTA_DmBleSetKeyMaterial(arg->set_key_material.session_key, arg->set_key_material.iv); + break; +#endif default: break; } diff --git a/components/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c index e8f7444368..9928a7ab2e 100644 --- a/components/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -213,12 +213,21 @@ static void btc_gattc_app_unregister(btc_ble_gattc_args_t *arg) static void btc_gattc_open(btc_ble_gattc_args_t *arg) { tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE; - +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + BTA_GATTC_Enh_Open(arg->open.gattc_if, arg->open.remote_bda, + arg->open.remote_addr_type, arg->open.is_direct, + transport, arg->open.is_aux, arg->open.own_addr_type, + arg->open.is_pawr_synced, arg->open.adv_handle, arg->open.subevent, + arg->open.phy_mask, (void *)&arg->open.phy_1m_conn_params, + (void *)&arg->open.phy_2m_conn_params, (void *)&arg->open.phy_coded_conn_params); +#else BTA_GATTC_Enh_Open(arg->open.gattc_if, arg->open.remote_bda, arg->open.remote_addr_type, arg->open.is_direct, transport, arg->open.is_aux, arg->open.own_addr_type, + false, 0xff, 0xff, arg->open.phy_mask, (void *)&arg->open.phy_1m_conn_params, (void *)&arg->open.phy_2m_conn_params, (void *)&arg->open.phy_coded_conn_params); +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) } static void btc_gattc_close(btc_ble_gattc_args_t *arg) diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h index 03b1e0885d..a429751293 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h @@ -141,6 +141,28 @@ typedef enum { BTC_GAP_ACT_SET_HOST_FEATURE, #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) BTC_GAP_BLE_READ_CHANNEL_MAP, +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + BTC_GAP_BLE_SET_PA_SUBEVT_DATA, + BTC_GAP_BLE_SET_PA_RSP_DATA, + BTC_GAP_BLE_SET_PA_SYNC_SUBEVT, +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + BTC_GAP_BLE_CS_READ_LOCAL_SUPPORTED_CAPS, + BTC_GAP_BLE_CS_READ_REMOTE_SUPPORTED_CAPS, + BTC_GAP_BLE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPS, + BTC_GAP_BLE_CS_SECURITY_ENABLE, + BTC_GAP_BLE_CS_SET_DEFAULT_SETTINGS, + BTC_GAP_BLE_CS_READ_REMOTE_FAE_TABLE, + BTC_GAP_BLE_CS_WRITE_CACHED_REMOTE_FAE_TABLE, + BTC_GAP_BLE_CS_CREATE_CONFIG, + BTC_GAP_BLE_CS_REMOVE_CONFIG, + BTC_GAP_BLE_CS_SET_CAHNNEL_CLASSIFICATION, + BTC_GAP_BLE_CS_SET_PROCEDURE_PARAMS, + BTC_GAP_BLE_CS_PROCEDURE_ENABLE, +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + BTC_GAP_BLE_ACT_SET_KEY_MATERIAL, +#endif } btc_gap_ble_act_t; /* btc_ble_gap_args_t */ @@ -196,19 +218,28 @@ typedef union { struct cfg_local_icon_args { uint16_t icon; } cfg_local_icon; +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + //BTC_GAP_BLE_ACT_SET_KEY_MATERIAL + struct set_key_material_args { + uint8_t session_key[16]; + uint8_t iv[8]; + } set_key_material; +#endif //BTC_GAP_BLE_ACT_UPDATE_WHITE_LIST struct update_white_list_args { bool add_remove; esp_bd_addr_t remote_bda; esp_ble_wl_addr_type_t wl_addr_type; } update_white_list; -#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) //BTC_GAP_BLE_UPDATE_DUPLICATE_SCAN_EXCEPTIONAL_LIST struct update_duplicate_exceptional_list_args { uint8_t subcode; uint32_t info_type; esp_duplicate_info_t device_info; } update_duplicate_exceptional_list; +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) +#if (BLE_42_FEATURE_SUPPORT == TRUE) //BTC_GAP_BLE_ACT_SET_CONN_PARAMS struct set_conn_params_args { esp_bd_addr_t bd_addr; @@ -531,9 +562,136 @@ typedef union { } subrate_req_param; #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) struct set_host_feature_arg { - uint16_t bit_num; - uint8_t bit_val; - } set_host_feature_params; + uint16_t bit_num; + uint8_t bit_val; + } set_host_feature_params; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + // BTC_GAP_BLE_SET_PA_SUBEVT_DATA + struct per_adv_subevent_data_params_args { + uint8_t adv_handle; + uint8_t num_subevents_with_data; + esp_ble_subevent_params *subevent_params; + } per_adv_subevent_data_params; + // BTC_GAP_BLE_SET_PA_RSP_DATA + struct per_adv_response_data_params_args { + uint16_t sync_handle; + uint16_t request_event; + uint8_t request_subevent; + uint8_t response_subevent; + uint8_t response_slot; + uint8_t response_data_len; + uint8_t *response_data; + } per_adv_response_data_params; + // BTC_GAP_BLE_SET_PA_SYNC_SUBEVT + struct per_sync_subevent_params_args { + uint16_t sync_handle; + uint16_t periodic_adv_properties; + uint8_t num_subevents_to_sync; + uint8_t *subevent; + } per_sync_subevent_params; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + struct cs_read_remote_supp_caps_args { + uint16_t conn_handle; + } cs_read_remote_supp_caps; + + struct cs_write_cached_remote_supp_caps_args { + uint16_t conn_handle; + uint8_t num_config_supported; + uint16_t max_consecutive_proc_supported; + uint8_t num_ant_supported; + uint8_t max_ant_paths_supported; + uint8_t roles_supported; + uint8_t modes_supported; + uint8_t rtt_capability; + uint8_t rtt_aa_only_n; + uint8_t rtt_sounding_n; + uint8_t rtt_random_payload_n; + uint16_t NADM_sounding_capability; + uint16_t NADM_random_capability; + uint8_t cs_sync_phys_supported; + uint16_t subfeatures_supported; + uint16_t T_IP1_times_supported; + uint16_t T_IP2_times_supported; + uint16_t T_FCS_times_supported; + uint16_t T_PM_times_supported; + uint8_t T_SW_times_supported; + uint8_t TX_SNR_capability; + } cs_write_cached_remote_supp_caps; + + struct cs_security_enable_args { + uint16_t conn_handle; + } cs_security_enable; + + struct cs_set_default_settings_params_args { + uint16_t conn_handle; + uint8_t role_enable; + uint8_t cs_sync_ant_selection; + int8_t max_tx_power; + } cs_set_default_settings_params; + + struct cs_read_remote_tab_args { + uint16_t conn_handle; + } cs_read_remote_tab; + + struct cs_write_cached_remote_fae_table_params_args { + uint16_t conn_handle; + uint8_t remote_fae_table[72]; + } cs_write_cached_remote_fae_table_params; + + struct cs_create_config_params_args { + uint16_t conn_handle; + uint8_t config_id; + uint8_t create_context; + uint8_t main_mode_type; + uint8_t sub_mode_type; + uint8_t min_main_mode_steps; + uint8_t max_main_mode_steps; + uint8_t main_mode_repetition; + uint8_t mode_0_steps; + uint8_t role; + uint8_t rtt_type; + uint8_t cs_sync_phy; + uint8_t channel_map[10]; + uint8_t channel_map_repetition; + uint8_t channel_selection_type; + uint8_t ch3c_shape; + uint8_t ch3c_jump; + uint8_t reserved; + } cs_create_config_params; + + struct cs_remove_config_params_args { + uint16_t conn_handle; + uint8_t config_id; + } cs_remove_config_params; + + struct cs_set_channel_class_params_args { + uint8_t channel_class[10]; + } cs_set_channel_class_params; + + struct cs_set_procedure_params_args { + uint16_t conn_handle; + uint8_t config_id; + uint16_t max_procedure_len; + uint16_t min_procedure_interval; + uint16_t max_procedure_interval; + uint16_t max_procedure_count; + uint32_t min_subevent_len; + uint32_t max_subevent_len; + uint8_t tone_ant_config_selection; + uint8_t phy; + uint8_t tx_power_delta; + uint8_t preferred_peer_antenna; + uint8_t SNR_control_initiator; + uint8_t SNR_control_reflector; + } cs_set_procedure_params; + + struct cs_procedure_enable_params_args { + uint16_t conn_handle; + uint8_t config_id; + uint8_t enable; + } cs_procedure_enable_params; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) } btc_ble_5_gap_args_t; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h index 1c8ef828b0..7580b7f17c 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h @@ -58,6 +58,9 @@ typedef union { bool is_direct; bool is_aux; esp_ble_addr_type_t own_addr_type; + bool is_pawr_synced; + uint8_t adv_handle; + uint8_t subevent; esp_ble_phy_mask_t phy_mask; esp_ble_conn_params_t phy_1m_conn_params; esp_ble_conn_params_t phy_2m_conn_params; diff --git a/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c b/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c index 84641f31c8..5f4bb5f110 100644 --- a/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c +++ b/components/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c @@ -42,6 +42,7 @@ #define VFS_CLOSE_TIMEOUT (20 * 1000) #define BTC_L2CAP_ROLE_MASTER 0 #define BTC_L2CAP_ROLE_SLAVE 1 +#define BTC_L2CAP_RX_MTU (990) typedef struct { bool peer_fc; /* true if flow control is set based on peer's request */ @@ -101,10 +102,10 @@ static const tL2CAP_ERTM_INFO obex_l2c_etm_opt = { L2CAP_FCR_ERTM_MODE, /* Mandatory for OBEX over l2cap */ L2CAP_FCR_CHAN_OPT_ERTM, /* Mandatory for OBEX over l2cap */ - OBX_USER_RX_POOL_ID, - OBX_USER_TX_POOL_ID, - OBX_FCR_RX_POOL_ID, - OBX_FCR_TX_POOL_ID + L2CAP_USER_RX_BUF_SIZE, + L2CAP_USER_TX_BUF_SIZE, + L2CAP_FCR_RX_BUF_SIZE, + L2CAP_FCR_TX_BUF_SIZE }; #if L2CAP_DYNAMIC_MEMORY == FALSE @@ -554,7 +555,7 @@ static void btc_l2cap_start_srv(btc_l2cap_args_t *arg) cfg.fcr_present = TRUE; cfg.fcr = obex_l2c_fcr_opts_def; BTA_JvL2capStartServer(slot->security, slot->role, &obex_l2c_etm_opt, slot->psm, - L2CAP_MAX_SDU_LENGTH, &cfg, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)slot->id); + BTC_L2CAP_RX_MTU, &cfg, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)slot->id); osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); } while(0); @@ -695,7 +696,7 @@ static void btc_l2cap_connect(btc_l2cap_args_t *arg) cfg.fcr = obex_l2c_fcr_opts_def; BTA_JvL2capConnect(slot->security, slot->role, &obex_l2c_etm_opt, slot->psm, - L2CAP_MAX_SDU_LENGTH, &cfg, slot->addr, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)slot->id); + BTC_L2CAP_RX_MTU, &cfg, slot->addr, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)slot->id); osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); } while (0); @@ -1025,6 +1026,15 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) p_buf->event++; BTA_JvL2capWrite(p_data->l2c_write.handle, slot->id, p_buf->data + p_buf->offset, p_buf->len, (void *)slot->id); } + } else { + if (!p_data->l2c_write.cong && slot->connected) { + // retry + BTA_JvL2capWrite(p_data->l2c_write.handle, slot->id, p_buf->data + p_buf->offset, p_buf->len, (void *)slot->id); + } else { + p_buf->event--; + // Reset layer-specific flag to 0, marking packet as ready for transmission + p_buf->layer_specific = 0; + } } } osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); @@ -1085,7 +1095,7 @@ static ssize_t l2cap_vfs_write(int fd, const void * data, size_t size) } p_buf->offset = 0; p_buf->len = write_size; - p_buf->event = 0; // indicate the p_buf be sent count + p_buf->event = 0; // Indicate the count of successful sends of p_buf p_buf->layer_specific = 0; // indicate the p_buf whether to be sent, 0 - ready to send; 1 - have sent memcpy((UINT8 *)(p_buf + 1), data + sent, write_size); } diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 16a6320dbe..d82ec6b547 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -278,6 +278,12 @@ #define UC_BT_BLE_FEAT_CREATE_SYNC_ENH FALSE #endif +#ifdef CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#else +#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX 3 +#endif + #ifdef CONFIG_BT_BLE_FEAT_ISO_EN #define UC_BT_BLE_FEAT_ISO_EN CONFIG_BT_BLE_FEAT_ISO_EN #else @@ -364,6 +370,24 @@ #define UC_BT_BLE_FEAT_CONN_SUBRATING FALSE #endif +#ifdef CONFIG_BT_BLE_FEAT_PAWR_EN +#define UC_BT_BLE_FEAT_PAWR_EN CONFIG_BT_BLE_FEAT_PAWR_EN +#else +#define UC_BT_BLE_FEAT_PAWR_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_ADV_CODING_SELECTION +#define UC_BT_BLE_FEAT_ADV_CODING_SELECTION CONFIG_BT_BLE_FEAT_ADV_CODING_SELECTION +#else +#define UC_BT_BLE_FEAT_ADV_CODING_SELECTION FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_CHANNEL_SOUNDING +#define UC_BT_BLE_FEAT_CHANNEL_SOUNDING CONFIG_BT_BLE_FEAT_CHANNEL_SOUNDING +#else +#define UC_BT_BLE_FEAT_CHANNEL_SOUNDING FALSE +#endif + #ifdef CONFIG_BT_BLE_VENDOR_HCI_EN #define UC_BT_BLE_VENDOR_HCI_EN CONFIG_BT_BLE_VENDOR_HCI_EN #else @@ -449,6 +473,24 @@ #define UC_BT_BLE_SMP_BOND_NVS_FLASH FALSE #endif +#ifdef CONFIG_BT_SMP_CRYPTO_STACK_NATIVE +#define UC_BT_SMP_CRYPTO_STACK_NATIVE TRUE +#else +#define UC_BT_SMP_CRYPTO_STACK_NATIVE FALSE +#endif + +#ifdef CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS +#define UC_BT_SMP_CRYPTO_MBEDTLS TRUE +#else +#define UC_BT_SMP_CRYPTO_MBEDTLS FALSE +#endif + +#ifdef CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT +#define UC_BT_SMP_CRYPTO_TINYCRYPT TRUE +#else +#define UC_BT_SMP_CRYPTO_TINYCRYPT FALSE +#endif + //Device Name Maximum Length #ifdef CONFIG_BT_MAX_DEVICE_NAME_LEN #define UC_MAX_LOC_BD_NAME_LEN CONFIG_BT_MAX_DEVICE_NAME_LEN @@ -568,6 +610,18 @@ #define UC_BT_GATTS_APPEARANCE_WRITABLE FALSE #endif +#ifdef CONFIG_BT_GATTS_SECURITY_LEVELS_CHAR +#define UC_BT_GATTS_SECURITY_LEVELS_CHAR CONFIG_BT_GATTS_SECURITY_LEVELS_CHAR +#else +#define UC_BT_GATTS_SECURITY_LEVELS_CHAR FALSE +#endif + +#ifdef CONFIG_BT_GATTS_KEY_MATERIAL_CHAR +#define UC_BT_GATTS_KEY_MATERIAL_CHAR CONFIG_BT_GATTS_KEY_MATERIAL_CHAR +#else +#define UC_BT_GATTS_KEY_MATERIAL_CHAR FALSE +#endif + #ifdef CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN #define UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN #else diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 6ec7ec52ba..2766a27fa9 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -319,6 +319,12 @@ #define BLE_FEAT_CREATE_SYNC_ENH FALSE #endif +#ifdef UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#define BLE_FEAT_CREATE_SYNC_RETRY_MAX UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX +#else +#define BLE_FEAT_CREATE_SYNC_RETRY_MAX 3 +#endif + #if (UC_BT_BLE_FEAT_ISO_EN == TRUE) #define BLE_FEAT_ISO_EN TRUE #else @@ -367,8 +373,8 @@ #define BLE_ISO_CIS_MAX_COUNT (0) #endif -#ifdef CONFIG_BT_BLE_ISO_BIS_MAX_COUNT -#define BLE_ISO_BIS_MAX_COUNT CONFIG_BT_BLE_ISO_BIS_MAX_COUNT +#ifdef UC_BT_BLE_ISO_BIS_MAX_COUNT +#define BLE_ISO_BIS_MAX_COUNT UC_BT_BLE_ISO_BIS_MAX_COUNT #else #define BLE_ISO_BIS_MAX_COUNT (0) #endif @@ -415,6 +421,24 @@ #define BLE_FEAT_CONN_SUBRATING FALSE #endif +#if (UC_BT_BLE_FEAT_PAWR_EN == TRUE) +#define BT_BLE_FEAT_PAWR_EN TRUE +#else +#define BT_BLE_FEAT_PAWR_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) +#define BT_BLE_FEAT_ADV_CODING_SELECTION TRUE +#else +#define BT_BLE_FEAT_ADV_CODING_SELECTION FALSE +#endif + +#if (UC_BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#define BT_BLE_FEAT_CHANNEL_SOUNDING TRUE +#else +#define BT_BLE_FEAT_CHANNEL_SOUNDING FALSE +#endif + #if (UC_BT_BLE_VENDOR_HCI_EN == TRUE) #define BLE_VENDOR_HCI_EN TRUE #else @@ -433,13 +457,13 @@ #define CONTROLLER_RPA_LIST_ENABLE FALSE #endif -#if (UC_BT_GATTS_ENABLE) +#if (UC_BT_GATTS_ENABLE == TRUE) #define GATTS_INCLUDED TRUE #else #define GATTS_INCLUDED FALSE #endif /* UC_BT_GATTS_ENABLE */ -#if (UC_BT_GATTC_ENABLE) +#if (UC_BT_GATTC_ENABLE == TRUE) #define GATTC_INCLUDED TRUE #else #define GATTC_INCLUDED FALSE @@ -499,6 +523,24 @@ #define BLE_SMP_BOND_NVS_FLASH FALSE #endif +#if (UC_BT_SMP_CRYPTO_STACK_NATIVE) +#define SMP_CRYPTO_STACK_NATIVE TRUE +#else +#define SMP_CRYPTO_STACK_NATIVE FALSE +#endif /* UC_BT_SMP_CRYPTO_STACK_NATIVE */ + +#if (UC_BT_SMP_CRYPTO_MBEDTLS) +#define SMP_CRYPTO_MBEDTLS TRUE +#else +#define SMP_CRYPTO_MBEDTLS FALSE +#endif /* UC_BT_SMP_CRYPTO_MBEDTLS */ + +#if (UC_BT_SMP_CRYPTO_TINYCRYPT) +#define SMP_CRYPTO_TINYCRYPT TRUE +#else +#define SMP_CRYPTO_TINYCRYPT FALSE +#endif /* UC_BT_SMP_CRYPTO_TINYCRYPT */ + #ifdef UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP #define BLE_ADV_REPORT_FLOW_CONTROL (UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP && BLE_INCLUDED) #endif /* UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP */ @@ -786,6 +828,18 @@ #define GATTS_APPEARANCE_WRITABLE FALSE #endif +#if (UC_BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) +#define BT_GATTS_SECURITY_LEVELS_CHAR TRUE +#else +#define BT_GATTS_SECURITY_LEVELS_CHAR FALSE +#endif + +#if (UC_BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +#define BT_GATTS_KEY_MATERIAL_CHAR TRUE +#else +#define BT_GATTS_KEY_MATERIAL_CHAR FALSE +#endif + #ifdef UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN #define BTM_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN #endif @@ -800,11 +854,6 @@ #define BT_CLASSIC_BQB_INCLUDED FALSE #endif -/* This feature is used to enable interleaved scan*/ -#ifndef BTA_HOST_INTERLEAVE_SEARCH -#define BTA_HOST_INTERLEAVE_SEARCH FALSE -#endif - #ifndef BT_USE_TRACES #define BT_USE_TRACES FALSE #endif @@ -1569,71 +1618,6 @@ #define BLE_INCLUDED FALSE #endif -#ifndef BLE_ANDROID_CONTROLLER_SCAN_FILTER -#define BLE_ANDROID_CONTROLLER_SCAN_FILTER FALSE -#endif - -#ifndef BLE_HOST_BLE_MULTI_ADV_EN -#define BLE_HOST_BLE_MULTI_ADV_EN FALSE -#endif - -#ifndef BLE_HOST_TRACK_ADVERTISER_EN -#define BLE_HOST_TRACK_ADVERTISER_EN FALSE -#endif - -#ifndef BLE_HOST_ENERGY_INFO_EN -#define BLE_HOST_ENERGY_INFO_EN FALSE -#endif - - -#ifndef BLE_HOST_ENABLE_TEST_MODE_EN -#define BLE_HOST_ENABLE_TEST_MODE_EN FALSE -#endif - -#ifndef BLE_HOST_EXECUTE_CBACK_EN -#define BLE_HOST_EXECUTE_CBACK_EN FALSE -#endif - -#ifndef BLE_HOST_REMOVE_ALL_ACL_EN -#define BLE_HOST_REMOVE_ALL_ACL_EN FALSE -#endif - -#ifndef BLE_HOST_REMOVE_AN_ACL_EN -#define BLE_HOST_REMOVE_AN_ACL_EN FALSE -#endif - -#ifndef BLE_HOST_READ_TX_POWER_EN -#define BLE_HOST_READ_TX_POWER_EN FALSE -#endif - -#ifndef BLE_HOST_STOP_ADV_UNUSED -#define BLE_HOST_STOP_ADV_UNUSED FALSE -#endif - -#ifndef BLE_HOST_BLE_OBSERVE_EN -#define BLE_HOST_BLE_OBSERVE_EN FALSE -#endif - -#ifndef BLE_HOST_BLE_SCAN_PARAM_UNUSED -#define BLE_HOST_BLE_SCAN_PARAM_UNUSED FALSE -#endif - -#ifndef BLE_HOST_CONN_SCAN_PARAM_EN -#define BLE_HOST_CONN_SCAN_PARAM_EN FALSE -#endif - -#ifndef BLE_HOST_SETUP_STORAGE_EN -#define BLE_HOST_SETUP_STORAGE_EN FALSE -#endif - -#ifndef BLE_HOST_READ_SCAN_REPORTS_EN -#define BLE_HOST_READ_SCAN_REPORTS_EN FALSE -#endif - -#ifndef BLE_HOST_BATCH_SCAN_EN -#define BLE_HOST_BATCH_SCAN_EN FALSE -#endif - #ifndef BLE_HOST_BG_CONNECT_EN #define BLE_HOST_BG_CONNECT_EN FALSE #endif @@ -1657,14 +1641,6 @@ #define BLE_LOCAL_PRIVACY_ENABLED TRUE #endif -/* - * Toggles support for vendor specific extensions such as RPA offloading, - * feature discovery, multi-adv etc. - */ -#ifndef BLE_VND_INCLUDED -#define BLE_VND_INCLUDED FALSE -#endif - #ifndef BTM_BLE_ADV_TX_POWER #ifdef CONFIG_IDF_TARGET_ESP32 #define BTM_BLE_ADV_TX_POWER {-12, -9, -6, -3, 0, 3, 6, 9} @@ -1689,11 +1665,6 @@ #endif #endif - -#ifndef BLE_BATCH_SCAN_INCLUDED -#define BLE_BATCH_SCAN_INCLUDED TRUE -#endif - /****************************************************************************** ** ** ATT/GATT Protocol/Profile Settings @@ -2112,7 +2083,7 @@ * in basic and streaming modes. Range: 1 - 63 */ #ifndef OBX_FCR_OPT_TX_WINDOW_SIZE_BR_EDR -#define OBX_FCR_OPT_TX_WINDOW_SIZE_BR_EDR 20 +#define OBX_FCR_OPT_TX_WINDOW_SIZE_BR_EDR 10 #endif /* diff --git a/components/bt/host/bluedroid/common/include/common/bt_trace.h b/components/bt/host/bluedroid/common/include/common/bt_trace.h index bd3b1ed8fc..85ddbe58d4 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_trace.h +++ b/components/bt/host/bluedroid/common/include/common/bt_trace.h @@ -57,6 +57,14 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l #define BTTRC_DUMP_BUFFER(_prefix, _data, _len) #endif +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + +/* Support up to 64 bytes of buffer */ +const char *bt_hex2str(const void *buf, size_t len); + //static const char BTE_LOGMSG_MODULE[] = "bte_logmsg_module"; /* BTrgs);E tracing IDs for debug purposes */ diff --git a/components/bt/host/bluedroid/device/controller.c b/components/bt/host/bluedroid/device/controller.c index 4b68eb93c8..d471c8be9e 100644 --- a/components/bt/host/bluedroid/device/controller.c +++ b/components/bt/host/bluedroid/device/controller.c @@ -31,7 +31,7 @@ #include "osi/future.h" #include "config/stack_config.h" #if (BLE_50_FEATURE_SUPPORT == TRUE) -const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x07\xff\xff\xff\xff" }; +const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\xff\xff\xff\xff\xff" }; #else const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x06\x7f" }; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) @@ -87,7 +87,7 @@ typedef struct { uint16_t ble_ext_adv_data_max_len; #endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #if (BLE_50_EXTEND_SYNC_EN == TRUE) - uint16_t get_ble_periodic_advertiser_list_size; + uint8_t get_ble_periodic_advertiser_list_size; #endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) } controller_local_param_t; diff --git a/components/bt/host/bluedroid/hci/ble_hci_iso.c b/components/bt/host/bluedroid/hci/ble_hci_iso.c index 9c73fae237..6a61836ef2 100644 --- a/components/bt/host/bluedroid/hci/ble_hci_iso.c +++ b/components/bt/host/bluedroid/hci/ble_hci_iso.c @@ -64,16 +64,16 @@ ble_hci_set_iso_buf_sz(uint16_t pktlen, uint8_t max_pkts) ble_hs_iso_avail_pkts = max_pkts; #endif /* (BLE_ISO_STD_FLOW_CTRL) */ - HCI_TRACE_WARNING("ISO Flow Control:\n"); - HCI_TRACE_WARNING(" Length: %u\n", pktlen); - HCI_TRACE_WARNING(" Count: %u\n", max_pkts); - HCI_TRACE_WARNING(" Status: "); + HCI_TRACE_DEBUG("ISO Flow Control:"); + HCI_TRACE_DEBUG("Length: %u\n", pktlen); + HCI_TRACE_DEBUG("Count: %u\n", max_pkts); + HCI_TRACE_DEBUG("Status: "); #if (BLE_ISO_STD_FLOW_CTRL == TRUE) - HCI_TRACE_WARNING("%s\n", "Standard"); + HCI_TRACE_DEBUG("%s", "Standard"); #elif (BLE_ISO_NON_STD_FLOW_CTRL == TRUE) - HCI_TRACE_WARNING("%s\n", "Non-standard"); + HCI_TRACE_DEBUG("%s\n", "Non-standard"); #else - HCI_TRACE_WARNING("%s\n", "Not support"); + HCI_TRACE_DEBUG("%s\n", "Not support"); #endif return 0; @@ -261,7 +261,7 @@ ble_hci_iso_tx_now(struct ble_hci_iso_conn *conn, const uint8_t *sdu, #endif dlh_len = (conn->ts_flag ? BLE_HCI_ISO_DATA_LOAD_TS_SZ : 0) + BLE_HCI_ISO_DATA_LOAD_HDR_SZ; - + // free in controller frag = malloc(BLE_HCI_ISO_DATA_HDR_SZ + dlh_len + conn->sdu_len); if (frag == NULL) { HCI_TRACE_ERROR("frag is null\n"); @@ -279,7 +279,7 @@ ble_hci_iso_tx_now(struct ble_hci_iso_conn *conn, const uint8_t *sdu, rc = ble_hci_tx_iso_data(frag, BLE_HCI_ISO_DATA_HDR_SZ + dlh_len + conn->sdu_len, NULL); if (rc) { - HCI_TRACE_ERROR("iso tx failed\n"); + HCI_TRACE_ERROR("iso tx failed_%d\n", rc); return 14; } diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index 0baa265f2a..90cb2a1177 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -660,7 +660,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) } #endif pkt_size = BT_PKT_LINKED_HDR_SIZE + BT_HDR_SIZE + len; - #if HEAP_MEMORY_DEBUG + #if (HEAP_MEMORY_DEBUG || HEAP_MEMORY_STATS) linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size); #else linked_pkt = (pkt_linked_item_t *) osi_calloc_base(pkt_size); diff --git a/components/bt/host/bluedroid/hci/hci_layer.c b/components/bt/host/bluedroid/hci/hci_layer.c index f87b7f7c8f..c6a6efa4ee 100644 --- a/components/bt/host/bluedroid/hci/hci_layer.c +++ b/components/bt/host/bluedroid/hci/hci_layer.c @@ -51,6 +51,10 @@ #define HCI_DOWNSTREAM_DATA_QUEUE_IDX (0) +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + typedef struct { bool timer_is_set; osi_alarm_t *command_response_timer; @@ -711,3 +715,27 @@ const char *hci_status_code_to_string(uint8_t status) } } #endif + +const char *bt_hex2str(const void *buf, size_t len) +{ + static const char hex[] = "0123456789abcdef"; + static char str[129]; + const uint8_t *b = buf; + size_t i; + + len = MIN(len, (sizeof(str) - 1) / 2); + + for (i = 0; i < len; i++) { + str[i * 2] = hex[b[i] >> 4]; + str[i * 2 + 1] = hex[b[i] & 0xf]; + } + + str[i * 2] = '\0'; + + return str; +} + +int get_hci_work_queue_size(int wq_idx) +{ + return osi_thread_queue_wait_size(hci_host_thread, wq_idx); +} diff --git a/components/bt/host/bluedroid/hci/hci_packet_parser.c b/components/bt/host/bluedroid/hci/hci_packet_parser.c index 560ee7b4a1..87c8499f8e 100644 --- a/components/bt/host/bluedroid/hci/hci_packet_parser.c +++ b/components/bt/host/bluedroid/hci/hci_packet_parser.c @@ -219,7 +219,7 @@ static void parse_ble_read_suggested_default_data_length_response( uint16_t *ble_default_packet_txtime_ptr) { - uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */); + uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 4 /* bytes after: 2+2 */); if (stream) { STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream); STREAM_TO_UINT16(*ble_default_packet_txtime_ptr, stream); @@ -235,7 +235,7 @@ static void parse_ble_read_adv_max_len_response( uint16_t *adv_max_len_ptr) { - uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 1 /* bytes after */); + uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 2 /* bytes after */); if (stream) { // Size: 2 Octets ; Value: 0x001F – 0x0672 ; Maximum supported advertising data length STREAM_TO_UINT16(*adv_max_len_ptr, stream); @@ -246,7 +246,7 @@ static void parse_ble_read_adv_max_len_response( #if (BLE_50_EXTEND_SYNC_EN == TRUE) static void parse_ble_read_periodic_adv_list_size_response( BT_HDR *response, - uint16_t *periodic_adv_list_size_ptr) + uint8_t *periodic_adv_list_size_ptr) { uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_PERIOD_ADV_LIST_SIZE, 1 /* bytes after */); diff --git a/components/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h b/components/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h index c40ffef94c..d926dd67ad 100644 --- a/components/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h +++ b/components/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h @@ -114,7 +114,7 @@ typedef struct { #if (BLE_50_EXTEND_SYNC_EN == TRUE) void (*parse_ble_read_periodic_adv_list_size_response) ( BT_HDR *response, - uint16_t *periodic_advertiser_list_size + uint8_t *periodic_advertiser_list_size ); #endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/components/bt/host/bluedroid/hci/packet_fragmenter.c b/components/bt/host/bluedroid/hci/packet_fragmenter.c index f0ee531433..ccc220fbf1 100644 --- a/components/bt/host/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/host/bluedroid/hci/packet_fragmenter.c @@ -180,8 +180,7 @@ static void reassemble_and_dispatch(BT_HDR *packet) partial_packet = (BT_HDR *)osi_calloc(full_length + sizeof(BT_HDR)); if (partial_packet == NULL) { - HCI_TRACE_WARNING("%s full_length %d no memory, free=%d, largest_block=%d", __func__, full_length, - heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); + HCI_TRACE_WARNING("%s full_length %d no memory.", __func__, full_length); assert(0); } diff --git a/components/bt/host/bluedroid/main/bte_init.c b/components/bt/host/bluedroid/main/bte_init.c index c60f6f7bd1..c19b50b6aa 100644 --- a/components/bt/host/bluedroid/main/bte_init.c +++ b/components/bt/host/bluedroid/main/bte_init.c @@ -264,14 +264,18 @@ void BTE_DeinitStack(void) bta_ag_cb_ptr = NULL; } #endif +#if (CLASSIC_BT_INCLUDED == TRUE) if (bta_dm_conn_srvcs_ptr){ osi_free(bta_dm_conn_srvcs_ptr); bta_dm_conn_srvcs_ptr = NULL; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) if (bta_dm_di_cb_ptr){ osi_free(bta_dm_di_cb_ptr); bta_dm_di_cb_ptr = NULL; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) if (bta_dm_search_cb_ptr){ osi_free(bta_dm_search_cb_ptr); bta_dm_search_cb_ptr = NULL; @@ -438,17 +442,25 @@ bt_status_t BTE_InitStack(void) if ((bta_dm_search_cb_ptr = (tBTA_DM_SEARCH_CB *)osi_malloc(sizeof(tBTA_DM_SEARCH_CB))) == NULL) { goto error_exit; } +#if (CLASSIC_BT_INCLUDED == TRUE) if ((bta_dm_di_cb_ptr = (tBTA_DM_DI_CB *)osi_malloc(sizeof(tBTA_DM_DI_CB))) == NULL) { goto error_exit; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) if ((bta_dm_conn_srvcs_ptr = (tBTA_DM_CONNECTED_SRVCS *)osi_malloc(sizeof(tBTA_DM_CONNECTED_SRVCS))) == NULL) { goto error_exit; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) memset((void *)bta_sys_cb_ptr, 0, sizeof(tBTA_SYS_CB)); memset((void *)bta_dm_cb_ptr, 0, sizeof(tBTA_DM_CB)); memset((void *)bta_dm_search_cb_ptr, 0, sizeof(tBTA_DM_SEARCH_CB)); +#if (CLASSIC_BT_INCLUDED == TRUE) memset((void *)bta_dm_di_cb_ptr, 0, sizeof(tBTA_DM_DI_CB)); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) memset((void *)bta_dm_conn_srvcs_ptr, 0, sizeof(tBTA_DM_CONNECTED_SRVCS)); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) //memset((void *)bta_prm_cb_ptr, 0, sizeof(tBTA_PRM_CB)); #if (defined BTA_HF_INCLUDED && BTA_HF_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/main/bte_main.c b/components/bt/host/bluedroid/main/bte_main.c index c974037ef9..73cbafc644 100644 --- a/components/bt/host/bluedroid/main/bte_main.c +++ b/components/bt/host/bluedroid/main/bte_main.c @@ -105,9 +105,6 @@ int bte_main_boot_entry(bluedroid_init_done_cb_t cb) ******************************************************************************/ void bte_main_shutdown(void) { -#if (BLE_INCLUDED == TRUE) - BTA_VendorCleanup(); -#endif #if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE) free_controller_param(); diff --git a/components/bt/host/bluedroid/stack/btm/btm_acl.c b/components/bt/host/bluedroid/stack/btm/btm_acl.c index 6350f4ba26..a5aed0a91b 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_acl.c @@ -75,7 +75,9 @@ void btm_acl_init (void) btm_cb.p_bl_changed_cb = NULL; #endif btm_cb.p_acl_db_list = list_new(osi_free_func); +#if (CLASSIC_BT_INCLUDED == TRUE) btm_cb.p_pm_mode_db_list = list_new(osi_free_func); +#endif// #if (CLASSIC_BT_INCLUDED == TRUE) /* Initialize nonzero defaults */ btm_cb.btm_def_link_super_tout = HCI_DEFAULT_INACT_TOUT; @@ -257,7 +259,9 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L #endif BTM_TRACE_DEBUG ("Duplicate btm_acl_created: RemBdAddr: %02x%02x%02x%02x%02x%02x\n", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); +#if (CLASSIC_BT_INCLUDED == TRUE) BTM_SetLinkPolicy(p->remote_addr, &btm_cb.btm_def_link_policy); +#endif // (CLASSIC_BT_INCLUDED == TRUE) return; } @@ -292,12 +296,16 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L p->conn_addr[0], p->conn_addr[1], p->conn_addr[2], p->conn_addr[3], p->conn_addr[4], p->conn_addr[5]); #endif #endif +#if (CLASSIC_BT_INCLUDED == TRUE) p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE; + p->p_pm_mode_db = btm_pm_sm_alloc(); + #if BTM_PM_DEBUG == TRUE BTM_TRACE_DEBUG( "btm_pm_sm_alloc handle:%d st:%d", hci_handle, p->p_pm_mode_db->state); #endif // BTM_PM_DEBUG +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if (CLASSIC_BT_INCLUDED == TRUE) btm_sec_update_legacy_auth_state(p, BTM_ACL_LEGACY_AUTH_NONE); @@ -384,7 +392,7 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L } } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_acl_report_role_change @@ -408,6 +416,7 @@ void btm_acl_report_role_change (UINT8 hci_status, BD_ADDR bda) btm_cb.devcb.p_switch_role_cb = NULL; } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -432,8 +441,10 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport) if (p != (tACL_CONN *)NULL) { p->in_use = FALSE; +#if (CLASSIC_BT_INCLUDED == TRUE) /* if the disconnected channel has a pending role switch, clear it now */ btm_acl_report_role_change(HCI_ERR_NO_CONNECTION, bda); +#endif // (CLASSIC_BT_INCLUDED == TRUE) /* Only notify if link up has had a chance to be issued */ if (p->link_up_issued) { @@ -484,8 +495,9 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport) } #endif - +#if (CLASSIC_BT_INCLUDED == TRUE) list_remove(btm_cb.p_pm_mode_db_list, p->p_pm_mode_db); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /* Clear the ACL connection data */ memset(p, 0, sizeof(tACL_CONN)); if (list_remove(btm_cb.p_acl_db_list, p)) { @@ -532,7 +544,9 @@ void btm_acl_device_down (void) void btm_acl_update_busy_level (tBTM_BLI_EVENT event) { UINT8 busy_level_flags = 0; +#if (CLASSIC_BT_INCLUDED == TRUE) BOOLEAN old_inquiry_state = btm_cb.is_inquiry; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) BTM_TRACE_DEBUG ("btm_acl_update_busy_level\n"); @@ -543,6 +557,7 @@ void btm_acl_update_busy_level (tBTM_BLI_EVENT event) case BTM_BLI_ACL_DOWN_EVT: BTM_TRACE_DEBUG ("BTM_BLI_ACL_DOWN_EVT\n"); break; +#if (CLASSIC_BT_INCLUDED == TRUE) case BTM_BLI_PAGE_EVT: BTM_TRACE_DEBUG ("BTM_BLI_PAGE_EVT\n"); btm_cb.is_paging = TRUE; @@ -568,16 +583,24 @@ void btm_acl_update_busy_level (tBTM_BLI_EVENT event) btm_cb.is_inquiry = FALSE; busy_level_flags = BTM_BL_INQUIRY_COMPLETE; break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } UINT8 busy_level; +#if (CLASSIC_BT_INCLUDED == TRUE) if (btm_cb.is_paging || btm_cb.is_inquiry) { busy_level = 10; - } else { + } else +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + { busy_level = BTM_GetNumAclLinks(); } - if ((busy_level != btm_cb.busy_level) || (old_inquiry_state != btm_cb.is_inquiry)) { + if ((busy_level != btm_cb.busy_level) +#if (CLASSIC_BT_INCLUDED == TRUE) + || (old_inquiry_state != btm_cb.is_inquiry) +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + ) { tBTM_BL_UPDATE_DATA evt = { .event = BTM_BL_UPDATE_EVT, .busy_level = busy_level, @@ -635,7 +658,7 @@ tBTM_STATUS BTM_GetRole (BD_ADDR remote_bd_addr, UINT8 *p_role) return (BTM_SUCCESS); } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_SwitchRole @@ -786,7 +809,7 @@ void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) tBTM_SEC_DEV_REC *p_dev_rec; tBTM_BL_ROLE_CHG_DATA evt; - BTM_TRACE_DEBUG ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d\n", + BTM_TRACE_DEBUG ("btm_acl_encrypt_change handle=%d status=%d encr_enable=%d\n", handle, status, encr_enable); p = btm_handle_to_acl(handle); if (p == NULL) { @@ -854,6 +877,8 @@ void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) #endif } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_SetLinkPolicy @@ -937,7 +962,7 @@ void BTM_SetDefaultLinkPolicy (UINT16 settings) /* Set the default Link Policy of the controller */ btsnd_hcic_write_def_policy_set(settings); } - +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_read_remote_version_complete @@ -1243,6 +1268,7 @@ void btm_establish_continue (tACL_CONN *p_acl_cb) tBTM_BL_EVENT_DATA evt_data; BTM_TRACE_DEBUG ("btm_establish_continue\n"); #if (!defined(BTM_BYPASS_EXTRA_ACL_SETUP) || BTM_BYPASS_EXTRA_ACL_SETUP == FALSE) +#if (CLASSIC_BT_INCLUDED == TRUE) #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) if (p_acl_cb->transport == BT_TRANSPORT_BR_EDR) #endif @@ -1256,6 +1282,7 @@ void btm_establish_continue (tACL_CONN *p_acl_cb) BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy); } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) #endif p_acl_cb->link_up_issued = TRUE; @@ -1461,6 +1488,7 @@ void btm_process_clk_off_comp_evt (UINT16 hci_handle, UINT16 clock_offset) } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_acl_role_changed @@ -1560,6 +1588,7 @@ void btm_acl_role_changed (UINT8 hci_status, BD_ADDR bd_addr, UINT8 new_role) #endif } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -1880,6 +1909,7 @@ tBTM_STATUS BTM_RegAclLinkStatNotif(tBTM_ACL_LINK_STAT_CB *p_cb) return BTM_SUCCESS; } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_SetQoS @@ -1961,7 +1991,7 @@ void btm_qos_setup_complete (UINT8 status, UINT16 handle, FLOW_SPEC *p_flow) (*p_cb)(&qossu); } } - +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_qos_setup_timeout @@ -1976,7 +2006,9 @@ void btm_qos_setup_timeout (void *p_tle) { BTM_TRACE_DEBUG ("%s\n", __func__); +#if (CLASSIC_BT_INCLUDED == TRUE) btm_qos_setup_complete (HCI_ERR_HOST_TIMEOUT, 0, NULL); +#endif // (CLASSIC_BT_INCLUDED == TRUE) } /******************************************************************************* @@ -2027,6 +2059,7 @@ tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL return (BTM_UNKNOWN_ADDR); } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_ReadLinkQuality @@ -2070,65 +2103,6 @@ tBTM_STATUS BTM_ReadLinkQuality (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb) return (BTM_UNKNOWN_ADDR); } -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -/******************************************************************************* -** -** Function BTM_ReadTxPower -** -** Description This function is called to read the current -** TX power of the connection. The tx power level results -** are returned in the callback. -** (tBTM_RSSI_RESULTS) -** -** Returns BTM_CMD_STARTED if successfully initiated or error code -** -*******************************************************************************/ -tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb) -{ - tACL_CONN *p; - BOOLEAN ret; -#define BTM_READ_RSSI_TYPE_CUR 0x00 -#define BTM_READ_RSSI_TYPE_MAX 0X01 - - BTM_TRACE_API ("BTM_ReadTxPower: RemBdAddr: %02x%02x%02x%02x%02x%02x\n", - remote_bda[0], remote_bda[1], remote_bda[2], - remote_bda[3], remote_bda[4], remote_bda[5]); - - /* If someone already waiting on the version, do not allow another */ - if (btm_cb.devcb.p_tx_power_cmpl_cb) { - return (BTM_BUSY); - } - - p = btm_bda_to_acl(remote_bda, transport); - if (p != (tACL_CONN *)NULL) { - btu_start_timer (&btm_cb.devcb.tx_power_timer, BTU_TTYPE_BTM_ACL, - BTM_DEV_REPLY_TIMEOUT); - - btm_cb.devcb.p_tx_power_cmpl_cb = p_cb; - -#if BLE_INCLUDED == TRUE - if (p->transport == BT_TRANSPORT_LE) { - memcpy(btm_cb.devcb.read_tx_pwr_addr, remote_bda, BD_ADDR_LEN); - ret = btsnd_hcic_ble_read_adv_chnl_tx_power(); - } else -#endif - { - ret = btsnd_hcic_read_tx_power (p->hci_handle, BTM_READ_RSSI_TYPE_CUR); - } - if (!ret) { - btm_cb.devcb.p_tx_power_cmpl_cb = NULL; - btu_stop_timer (&btm_cb.devcb.tx_power_timer); - return (BTM_NO_RESOURCES); - } else { - return (BTM_CMD_STARTED); - } - } - - /* If here, no BD Addr found */ - return (BTM_UNKNOWN_ADDR); -} -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) - tBTM_STATUS BTM_SetAclPktTypes(BD_ADDR remote_bda, UINT16 pkt_types, tBTM_CMPL_CB *p_cb) { #if CLASSIC_BT_INCLUDED == TRUE @@ -2169,7 +2143,6 @@ tBTM_STATUS BTM_SetAclPktTypes(BD_ADDR remote_bda, UINT16 pkt_types, tBTM_CMPL_C void btm_acl_pkt_types_changed(UINT8 status, UINT16 handle, UINT16 pkt_types) { -#if CLASSIC_BT_INCLUDED == TRUE BTM_TRACE_DEBUG ("btm_acl_pkt_types_changed\n"); tACL_CONN *conn = NULL; tBTM_SET_ACL_PKT_TYPES_RESULTS results; @@ -2190,8 +2163,8 @@ void btm_acl_pkt_types_changed(UINT8 status, UINT16 handle, UINT16 pkt_types) } btm_cb.devcb.p_set_acl_pkt_types_cmpl_cb = NULL; } -#endif } +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE) @@ -2242,35 +2215,6 @@ tBTM_STATUS BTM_ReadChannelMap(BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb) return BTM_UNKNOWN_ADDR; } -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -tBTM_STATUS BTM_BleReadAdvTxPower(tBTM_CMPL_CB *p_cb) -{ - BOOLEAN ret; - tBTM_TX_POWER_RESULTS result; - /* If someone already waiting on the version, do not allow another */ - if (btm_cb.devcb.p_tx_power_cmpl_cb) { - result.status = BTM_BUSY; - (*p_cb)(&result); - return (BTM_BUSY); - } - - btm_cb.devcb.p_tx_power_cmpl_cb = p_cb; - btu_start_timer (&btm_cb.devcb.tx_power_timer, BTU_TTYPE_BTM_ACL, - BTM_DEV_REPLY_TIMEOUT); - ret = btsnd_hcic_ble_read_adv_chnl_tx_power(); - - if(!ret) { - btm_cb.devcb.p_tx_power_cmpl_cb = NULL; - btu_stop_timer (&btm_cb.devcb.tx_power_timer); - result.status = BTM_NO_RESOURCES; - (*p_cb)(&result); - return (BTM_NO_RESOURCES); - } else { - return BTM_CMD_STARTED; - } -} -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) - void BTM_BleGetWhiteListSize(uint16_t *length) { tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; @@ -2294,79 +2238,7 @@ void BTM_BleGetPeriodicAdvListSize(uint8_t *size) #endif ///BLE_INCLUDED == TRUE -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -/******************************************************************************* -** -** Function btm_read_tx_power_complete -** -** Description This function is called when the command complete message -** is received from the HCI for the read tx power request. -** -** Returns void -** -*******************************************************************************/ -void btm_read_tx_power_complete (UINT8 *p, UINT16 evt_len, BOOLEAN is_ble) -{ - tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_tx_power_cmpl_cb; - tBTM_TX_POWER_RESULTS results; - UINT16 handle; - tACL_CONN *p_acl_cb = NULL; - BTM_TRACE_DEBUG ("btm_read_tx_power_complete\n"); - btu_stop_timer (&btm_cb.devcb.tx_power_timer); - - /* If there was a callback registered for read rssi, call it */ - btm_cb.devcb.p_tx_power_cmpl_cb = NULL; - - if (p_cb) { - if (evt_len < 1) { - BTM_TRACE_ERROR("Bogus event packet, too short\n"); - results.status = BTM_ERR_PROCESSING; - goto err_out; - } - - STREAM_TO_UINT8 (results.hci_status, p); - - if (results.hci_status == HCI_SUCCESS) { - results.status = BTM_SUCCESS; - - if (!is_ble) { - if (evt_len < 1 + 3) { - BTM_TRACE_ERROR("Bogus event packet, too short\n"); - results.status = BTM_ERR_PROCESSING; - goto err_out; - } - STREAM_TO_UINT16 (handle, p); - STREAM_TO_UINT8 (results.tx_power, p); - - /* Search through the list of active channels for the correct BD Addr */ - p_acl_cb = btm_handle_to_acl(handle); - if (p_acl_cb) { - memcpy (results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN); - } - } #if BLE_INCLUDED == TRUE - else { - if (evt_len < 1 + 1) { - BTM_TRACE_ERROR("Bogus event packet, too short\n"); - results.status = BTM_ERR_PROCESSING; - goto err_out; - } - STREAM_TO_UINT8 (results.tx_power, p); - memcpy(results.rem_bda, btm_cb.devcb.read_tx_pwr_addr, BD_ADDR_LEN); - } -#endif - BTM_TRACE_DEBUG ("BTM TX power Complete: tx_power %d, hci status 0x%02x\n", - results.tx_power, results.hci_status); - } else { - results.status = BTM_ERR_PROCESSING; - } - -err_out: - (*p_cb)(&results); - } -} -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) - /******************************************************************************* ** ** Function btm_read_channel_map_complete @@ -2421,7 +2293,7 @@ void btm_read_channel_map_complete(UINT8 *p) (*p_cb)(&results); } } - +#endif // #if BLE_INCLUDED == TRUE /******************************************************************************* ** @@ -2481,6 +2353,7 @@ err_out: } } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_read_link_quality_complete @@ -2527,6 +2400,7 @@ void btm_read_link_quality_complete (UINT8 *p) (*p_cb)(&results); } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -2585,6 +2459,7 @@ UINT8 BTM_SetTraceLevel (UINT8 new_level) return (btm_cb.trace_level); } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_cont_rswitch @@ -2639,7 +2514,9 @@ void btm_cont_rswitch (tACL_CONN *p, tBTM_SEC_DEV_REC *p_dev_rec, } } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_acl_resubmit_page @@ -2693,6 +2570,7 @@ void btm_acl_reset_paging (void) btm_cb.paging = FALSE; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -2830,7 +2708,9 @@ void btm_acl_chk_peer_pkt_type_support (tACL_CONN *p, UINT16 *p_pkt_type) void btm_acl_free(void) { list_free(btm_cb.p_acl_db_list); +#if (CLASSIC_BT_INCLUDED == TRUE) list_free(btm_cb.p_pm_mode_db_list); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } /******************************************************************************* diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble.c b/components/bt/host/bluedroid/stack/btm/btm_ble.c index d65e632931..60601893da 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble.c @@ -77,18 +77,16 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d tBTM_SEC_DEV_REC *p_dev_rec; tBTM_INQ_INFO *p_info = NULL; - BTM_TRACE_DEBUG ("BTM_SecAddBleDevice dev_type=0x%x", dev_type); + BTM_TRACE_DEBUG ("%s dev_type=0x%x bd_addr="MACSTR"", __func__, dev_type, MAC2STR(bd_addr)); p_dev_rec = btm_find_dev (bd_addr); if (!p_dev_rec) { - BTM_TRACE_DEBUG("Add a new device"); - /* There is no device record, allocate one. * If we can not find an empty spot for this one, let it fail. */ if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS) { - p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); - if(p_dev_rec) { - list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); + p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); + if (p_dev_rec) { + list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); BTM_TRACE_DEBUG ("allocate a new dev rec idx=0x%x\n", list_length(btm_cb.p_sec_dev_rec_list)); /* Mark this record as in use and initialize */ @@ -158,22 +156,20 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_KEY_TYPE key_type) { tBTM_SEC_DEV_REC *p_dev_rec; - BTM_TRACE_DEBUG ("BTM_SecAddBleKey"); p_dev_rec = btm_find_dev (bd_addr); + if (!p_dev_rec || !p_le_key || (key_type != BTM_LE_KEY_PENC && key_type != BTM_LE_KEY_PID && key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC && key_type != BTM_LE_KEY_LCSRK && key_type != BTM_LE_KEY_LID)) { - BTM_TRACE_WARNING ("BTM_SecAddBleKey() Wrong Type, or No Device record \ - for bdaddr: %08x%04x, Type: %d", - (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], - (bd_addr[4] << 8) + bd_addr[5], key_type); + BTM_TRACE_WARNING ("BTM_SecAddBleKey() Wrong Type, or No Device record \ + for bdaddr: "MACSTR", key_type: %02x", + MAC2STR(bd_addr), key_type); return (FALSE); } - BTM_TRACE_DEBUG ("BTM_SecAddLeKey() BDA: %08x%04x, Type: 0x%02x", - (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], - (bd_addr[4] << 8) + bd_addr[5], key_type); + BTM_TRACE_DEBUG ("BTM_SecAddLeKey() BDA: "MACSTR", key_type: 0x%02x", + MAC2STR(bd_addr), key_type); btm_sec_save_le_key (bd_addr, key_type, p_le_key, FALSE); @@ -553,48 +549,6 @@ void BTM_BleSecureConnectionCreateOobData(void) #endif } -#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) -/****************************************************************************** -** -** Function BTM_BleSetConnScanParams -** -** Description Set scan parameter used in BLE connection request -** -** Parameters: scan_interval: scan interval -** scan_window: scan window -** -** Returns void -** -*******************************************************************************/ -void BTM_BleSetConnScanParams (UINT32 scan_interval, UINT32 scan_window) -{ -#if SMP_INCLUDED == TRUE - tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb; - BOOLEAN new_param = FALSE; - - if (BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) && - BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX)) { - if (p_ble_cb->scan_int != scan_interval) { - p_ble_cb->scan_int = scan_interval; - new_param = TRUE; - } - - if (p_ble_cb->scan_win != scan_window) { - p_ble_cb->scan_win = scan_window; - new_param = TRUE; - } -#if (tGATT_BG_CONN_DEV == TRUE) - if (new_param && p_ble_cb->conn_state == BLE_BG_CONN) { - btm_ble_suspend_bg_conn(); - } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) - } else { - BTM_TRACE_ERROR("Illegal Connection Scan Parameters"); - } -#endif -} -#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) - /******************************************************** ** ** Function BTM_BleSetPrefConnParams @@ -1759,15 +1713,14 @@ void btm_ble_ltk_request_reply(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk) tBTM_CB *p_cb = &btm_cb; if (p_rec == NULL) { - BTM_TRACE_ERROR("btm_ble_ltk_request_reply received for unknown device"); + BTM_TRACE_ERROR("%s received for unknown device "MACSTR"", __func__, MAC2STR(bda)); return; } - BTM_TRACE_DEBUG ("btm_ble_ltk_request_reply"); + BTM_TRACE_DEBUG ("%s key_type=%x key_size=%d", __func__, p_rec->ble.key_type, p_rec->ble.keys.key_size); p_cb->enc_handle = p_rec->ble_hci_handle; p_cb->key_size = p_rec->ble.keys.key_size; - BTM_TRACE_DEBUG("key size = %d", p_rec->ble.keys.key_size); if (use_stk) { btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, stk); } else { /* calculate LTK using peer device */ @@ -2047,7 +2000,8 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced) STREAM_TO_UINT8 (role, p); STREAM_TO_UINT8 (bda_type, p); STREAM_TO_BDADDR (bda, p); - BTM_TRACE_DEBUG("status = %d, handle = %d, role = %d, bda_type = %d",status,handle,role,bda_type); + BTM_TRACE_DEBUG("status=%d handle=%d role=%d bda_type=%d bda="MACSTR"", + status, handle, role, bda_type, MAC2STR(bda)); if (status == 0) { if (enhanced) { STREAM_TO_BDADDR (local_rpa, p); diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c index 4b3372504e..7ecde99cee 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c @@ -17,6 +17,7 @@ tBTM_BLE_EXTENDED_CB extend_adv_cb; tBTM_BLE_5_HCI_CBACK ble_5_hci_cb; #define INVALID_VALUE 0XFF + extern BOOLEAN BTM_GetLocalResolvablePrivateAddr(BD_ADDR bda); extern void BTM_UpdateAddrInfor(uint8_t addr_type, BD_ADDR bda); extern void BTM_BleSetStaticAddr(BD_ADDR rand_addr); @@ -38,6 +39,19 @@ typedef struct { tBTM_EXT_ADV_RECORD adv_record[MAX_BLE_ADV_INSTANCE] = {0}; #endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) +/* Create sync retry control block */ +typedef struct { + bool in_use; /* Whether sync creation is in progress */ + uint8_t retry_count; /* Current retry count */ + tBTM_BLE_Periodic_Sync_Params params; /* Saved sync parameters for retry */ +} tBTM_BLE_SYNC_RETRY_CB; + +static tBTM_BLE_SYNC_RETRY_CB sync_retry_cb = {0}; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) + extern void btm_ble_inter_set(bool extble_inter); #if !UC_BT_STACK_NO_LOG @@ -401,7 +415,18 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR #else btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = params->own_addr_type; #endif - +#if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) + if ((err = btsnd_hcic_ble_set_ext_adv_params_v2(instance, params->type, params->interval_min, params->interval_max, + params->channel_map, params->own_addr_type, params->peer_addr_type, + params->peer_addr, params->filter_policy, params->tx_power, + params->primary_phy, params->max_skip, + params->secondary_phy, params->sid, params->scan_req_notif, + params->primary_adv_phy_options, params->secondary_adv_phy_options)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("LE EA SetParams: cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + goto end; + } +#else if ((err = btsnd_hcic_ble_set_ext_adv_params(instance, params->type, params->interval_min, params->interval_max, params->channel_map, params->own_addr_type, params->peer_addr_type, params->peer_addr, params->filter_policy, params->tx_power, @@ -411,6 +436,7 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR status = BTM_HCI_ERROR | err; goto end; } +#endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) extend_adv_cb.inst[instance].configured = true; @@ -692,7 +718,6 @@ tBTM_STATUS BTM_BlePeriodicAdvSetParams(UINT8 instance, tBTM_BLE_Periodic_Adv_Pa tBTM_STATUS status = BTM_SUCCESS; tHCI_STATUS err = HCI_SUCCESS; tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; - //ext_adv_flag = true; if (instance >= MAX_BLE_ADV_INSTANCE) { status = BTM_ILLEGAL_VALUE; @@ -710,11 +735,20 @@ tBTM_STATUS BTM_BlePeriodicAdvSetParams(UINT8 instance, tBTM_BLE_Periodic_Adv_Pa goto end; } - if ((err= btsnd_hcic_ble_set_periodic_adv_params(instance, params->interval_min, +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + if ((err = btsnd_hcic_ble_set_periodic_adv_params_v2(instance, params->interval_min, params->interval_max, + params->properties, params->num_subevents, params->subevent_interval, + params->rsp_slot_delay, params->rsp_slot_spacing, params->num_rsp_slots)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("LE PA SetParams_V2: cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } +#else + if ((err = btsnd_hcic_ble_set_periodic_adv_params(instance, params->interval_min, params->interval_max, params->properties)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA SetParams: cmd err=0x%x", err); status = BTM_HCI_ERROR | err; } +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) end: @@ -859,11 +893,19 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params) SET_BIT(option, 2); } #endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) - +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + /* Save parameters for potential retry */ + memcpy(&sync_retry_cb.params, params, sizeof(tBTM_BLE_Periodic_Sync_Params)); + sync_retry_cb.retry_count = 0; + sync_retry_cb.in_use = true; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) if (!btsnd_hcic_ble_periodic_adv_create_sync(option, params->sid, params->addr_type, params->addr, params->sync_timeout, params->sync_cte_type)) { BTM_TRACE_ERROR("LE PA CreateSync cmd failed"); status = BTM_ILLEGAL_VALUE; +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + sync_retry_cb.in_use = false; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) } end: @@ -921,6 +963,11 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void) tBTM_STATUS status = BTM_SUCCESS; tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + /* Clear retry state when sync is cancelled */ + sync_retry_cb.in_use = false; + sync_retry_cb.retry_count = 0; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) if ((err = btsnd_hcic_ble_periodic_adv_create_sync_cancel()) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err); status = BTM_HCI_ERROR | err; @@ -1378,6 +1425,48 @@ void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *par return; } +#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) + /* Check if retry is needed for error 0x3E (Connection Failed to be Established) */ + if (params->status == HCI_ERR_CONN_FAILED_ESTABLISHMENT && + sync_retry_cb.in_use && + sync_retry_cb.retry_count < BLE_FEAT_CREATE_SYNC_RETRY_MAX) { + + sync_retry_cb.retry_count++; + BTM_TRACE_WARNING("%s, Create sync failed with 0x3E, retry %d/%d", + __func__, sync_retry_cb.retry_count, BLE_FEAT_CREATE_SYNC_RETRY_MAX); + + /* Build option from saved parameters */ + uint8_t option = 0x00; + if (sync_retry_cb.params.filter_policy) { + SET_BIT(option, 0); + } +#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE) + if (sync_retry_cb.params.reports_disabled) { + SET_BIT(option, 1); + } + if (sync_retry_cb.params.filter_duplicates) { + SET_BIT(option, 2); + } +#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) + + /* Retry create sync with saved parameters */ + if (btsnd_hcic_ble_periodic_adv_create_sync(option, + sync_retry_cb.params.sid, + sync_retry_cb.params.addr_type, + sync_retry_cb.params.addr, + sync_retry_cb.params.sync_timeout, + sync_retry_cb.params.sync_cte_type)) { + /* Retry command sent successfully, wait for next event */ + return; + } + /* If retry command failed, fall through to report failure */ + BTM_TRACE_ERROR("%s, Retry create sync command failed", __func__); + } + + /* Clear retry state */ + sync_retry_cb.in_use = false; + sync_retry_cb.retry_count = 0; +#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0) memcpy(&cb_params.sync_estab, params, sizeof(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB)); // If the user has register the callback function, should callback it to the application. @@ -1740,3 +1829,352 @@ tBTM_STATUS BTM_BleSetHostFeature(uint16_t bit_num, uint8_t bit_val) return status; } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +void BTM_BleSetPaSubeventData(UINT8 adv_handle, UINT8 num_subevents_with_data, uint8_t *subevent_params) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_periodic_adv_subevt_data(adv_handle, num_subevents_with_data, (ble_subevent_params *)subevent_params)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, err); + status = BTM_HCI_ERROR | err; + } + + cb_params.pa_subevt_data_evt.status = status; + cb_params.pa_subevt_data_evt.adv_handle = adv_handle; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_PERIODIC_ADV_SUBEVT_DATA_EVT, &cb_params); +} + +void BTM_BleSetPaResponseData(UINT16 sync_handle, UINT16 req_evt, UINT8 req_subevt, UINT8 rsp_subevt, UINT8 rsp_slot, UINT8 rsp_data_len, UINT8 *rsp_data) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_periodic_adv_rsp_data(sync_handle, req_evt, req_subevt, rsp_subevt, rsp_slot, rsp_data_len, rsp_data)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, err); + status = BTM_HCI_ERROR | err; + } + + cb_params.pa_rsp_data_evt.status = status; + cb_params.pa_rsp_data_evt.sync_handle = sync_handle; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_PERIODIC_ADV_RESPONSE_DATA_EVT, &cb_params); +} + +void BTM_BleSetPaSyncSubevt(UINT16 sync_handle, UINT16 periodic_adv_properties, UINT8 num_subevents_to_sync, UINT8 *subevt) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_periodic_sync_subevt(sync_handle, periodic_adv_properties, num_subevents_to_sync, subevt)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, err); + status = BTM_HCI_ERROR | err; + } + + cb_params.pa_sync_subevt_evt.status = status; + cb_params.pa_sync_subevt_evt.sync_handle = sync_handle; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_PERIODIC_SYNC_SUBEVT_EVT, &cb_params); +} + +void btm_ble_pa_subevt_data_req_evt(tBTM_BLE_PA_SUBEVT_DATA_REQ_EVT *params) +{ + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_PERIODIC_ADV_SUBEVT_DATA_REQUEST_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)params); +} + +void btm_ble_pa_rsp_rpt_evt(tBTM_BLE_PA_RSP_REPORT_EVT *params) +{ + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_PERIODIC_ADV_RESPONSE_REPORT_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)params); +} + +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void BTM_BleCSReadLocalSuppCaps(void) +{ + btsnd_hcic_ble_cs_read_local_supported_caps(); +} + +void btm_ble_cs_read_local_supp_caps_cmpl_evt(uint8_t *p) +{ + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.status, p); + if (cb_params.cs_read_local_supp_caps.status != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, cb_params.cs_read_local_supp_caps.status); + cb_params.cs_read_local_supp_caps.status |= BTM_HCI_ERROR; + goto _error; + } + + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.conn_handle, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.num_config_supported, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.max_consecutive_proc_supported, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.num_ant_supported, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.max_ant_paths_supported, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.roles_supported, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.modes_supported, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.rtt_capability, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.rtt_aa_only_n, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.rtt_sounding_n, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.rtt_random_payload_n, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.NADM_sounding_capability, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.NADM_random_capability, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.cs_sync_phys_supported, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.subfeatures_supported, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.T_IP1_times_supported, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.T_IP2_times_supported, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.T_FCS_times_supported, p); + STREAM_TO_UINT16(cb_params.cs_read_local_supp_caps.T_PM_times_supported, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.T_SW_times_supported, p); + STREAM_TO_UINT8(cb_params.cs_read_local_supp_caps.TX_SNR_capability, p); + +_error: + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_READ_LOCAL_SUPP_CAPS_EVT, &cb_params); +} + +void BTM_BleCSReadRemoteSuppCaps(UINT16 conn_handle) +{ + btsnd_hcic_ble_cs_read_remote_supported_capabilities(conn_handle); +} + +void btm_ble_cs_read_remote_supp_caps_cmd_status(UINT8 status) +{ + if (status != HCI_SUCCESS) { + tBTM_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT cs_read_remote_supp_caps = {0}; + cs_read_remote_supp_caps.status = (status | BTM_HCI_ERROR); + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)&cs_read_remote_supp_caps); + } +} + +void BTM_BleGapWriteCachedRemoteSupportedCaps(UINT16 conn_handle, UINT8 num_config_supported, UINT16 max_consecutive_proc_supported, + UINT8 num_ant_supported, UINT8 max_ant_paths_supported, UINT8 roles_supported, + UINT8 modes_supported, UINT8 rtt_capability, UINT8 rtt_aa_only_n, + UINT8 rtt_sounding_n, UINT8 rtt_random_payload_n, UINT16 NADM_sounding_capability, + UINT16 NADM_random_capability, UINT8 cs_sync_phys_supported, UINT16 subfeatures_supported, + UINT16 T_IP1_times_supported, UINT16 T_IP2_times_supported, UINT16 T_FCS_times_supported, + UINT16 T_PM_times_supported, UINT8 T_SW_times_supported, UINT8 TX_SNR_capability) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_cs_write_cached_remote_supported_capabilities(conn_handle, num_config_supported, max_consecutive_proc_supported, + num_ant_supported, max_ant_paths_supported, roles_supported, + modes_supported, rtt_capability, rtt_aa_only_n, + rtt_sounding_n, rtt_random_payload_n, NADM_sounding_capability, + NADM_random_capability, cs_sync_phys_supported, subfeatures_supported, + T_IP1_times_supported, T_IP2_times_supported, T_FCS_times_supported, + T_PM_times_supported, T_SW_times_supported, TX_SNR_capability)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cs write cached remote support caps, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cs_write_cached_remote_supp_caps.status = status; + cb_params.cs_write_cached_remote_supp_caps.conn_handle = conn_handle; + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_WRITE_CACHED_REMOTE_SUPP_CAPS_EVT, &cb_params); +} + +void BTM_BleGapCsSecurityEnable(UINT16 conn_handle) +{ + btsnd_hcic_ble_cs_security_enable(conn_handle); +} + +void btm_ble_cs_security_enable_cmd_status(UINT8 status) +{ + tBTM_BLE_CS_SEC_ENABLE_CMPL_EVT cs_security_enable = {0}; + if (status != HCI_SUCCESS) { + cs_security_enable.status = (status | BTM_HCI_ERROR); + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_SECURITY_ENABLE_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)&cs_security_enable); + } +} + +void BTM_BleGapCsSetDefaultSetting(UINT16 conn_handle, UINT8 role_enable, UINT8 cs_sync_ant_selection, INT8 max_tx_power) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_cs_set_default_settings(conn_handle, role_enable, cs_sync_ant_selection, max_tx_power)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cs set default setting, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cs_set_default_settings.status = status; + cb_params.cs_set_default_settings.conn_handle = conn_handle; + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_SET_DEFAULT_SETTINGS_EVT, &cb_params); +} + +void BTM_BleGapCsReadRemoteFaeTable(UINT16 conn_handle) +{ + btsnd_hcic_ble_cs_read_remote_fae_table(conn_handle); +} + +void btm_ble_cs_read_remote_fae_table_cmd_status(UINT8 status) +{ + tBTM_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT cs_read_remote_fae_tab = {0}; + if (status != HCI_SUCCESS) { + cs_read_remote_fae_tab.status = (status | BTM_HCI_ERROR); + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)&cs_read_remote_fae_tab); + } +} + +void BTM_BleGapWriteCachedRemoteFaeTable(UINT16 conn_handle, UINT8 *remote_fae_table) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_cs_write_cached_remote_fae_table(conn_handle, remote_fae_table)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cs write cached remote fae tab, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cs_write_cached_remote_fae_tab.status = status; + cb_params.cs_write_cached_remote_fae_tab.conn_handle = conn_handle; + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_WRITE_CACHED_REMOTE_FAE_TAB_EVT, &cb_params); +} + +void BTM_BleGapCsCreateConfig(UINT16 conn_handle, UINT8 config_id, UINT8 create_context, + UINT8 main_mode_type, UINT8 sub_mode_type, UINT8 min_main_mode_steps, + UINT8 max_main_mode_steps, UINT8 main_mode_repetition, UINT8 mode_0_steps, + UINT8 role, UINT8 rtt_type, UINT8 cs_sync_phy, UINT8 *channel_map, + UINT8 channel_map_repetition, UINT8 channel_selection_type, UINT8 ch3c_shape, + UINT8 ch3c_jump,UINT8 reserved) +{ + btsnd_hcic_ble_cs_create_config(conn_handle, config_id, create_context, + main_mode_type, sub_mode_type, min_main_mode_steps, + max_main_mode_steps, main_mode_repetition, mode_0_steps, + role, rtt_type, cs_sync_phy, channel_map, + channel_map_repetition, channel_selection_type, ch3c_shape, + ch3c_jump, reserved); +} + +void BTM_BleGapCsRemoveConfig(UINT16 conn_handle, UINT8 config_id) +{ + btsnd_hcic_ble_cs_remove_config(conn_handle, config_id); +} + +void btm_ble_cs_update_config_cmd_status(UINT8 status, BOOLEAN create) +{ + tBTM_BLE_CS_CONFIG_CMPL_EVT config_cmpl = {0}; + if (status != HCI_SUCCESS) { + config_cmpl.status = (status | BTM_HCI_ERROR); + config_cmpl.action = (create? 0x01:0x00); + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_CONFIG_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)&config_cmpl); + } +} + +void BTM_BleGapCsSetChannelClass(UINT8 *channel_class) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_cs_set_channel_classification(channel_class)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cs set channel class, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.status = status; + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_SET_CHANNEL_CLASS_CMPL_EVT, &cb_params); +} + +void BTM_BleGapCsSetProcPatams(UINT16 conn_handle, UINT8 config_id, UINT16 max_procedure_len, + UINT16 min_procedure_interval, UINT16 max_procedure_interval, + UINT16 max_procedure_count, UINT32 min_subevent_len, + UINT32 max_subevent_len, UINT8 tone_ant_config_selection, + UINT8 phy, UINT8 tx_power_delta, UINT8 preferred_peer_antenna, + UINT8 SNR_control_initiator, UINT8 SNR_control_reflector) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_cs_set_procedure_params(conn_handle, config_id, max_procedure_len, + min_procedure_interval, max_procedure_interval, + max_procedure_count, min_subevent_len, + max_subevent_len, tone_ant_config_selection, + phy, tx_power_delta, preferred_peer_antenna, + SNR_control_initiator, SNR_control_reflector)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cs set procedure params, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cs_set_proc_params.status = status; + cb_params.cs_set_proc_params.conn_handle = conn_handle; + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_PROC_PARAMS_CMPL_EVT, &cb_params); +} + +void BTM_BleGapCsProcEnable(UINT16 conn_handle, UINT8 config_id, UINT8 enable) +{ + btsnd_hcic_ble_cs_procedure_enable(conn_handle, config_id, enable); +} + +void btm_ble_cs_read_remote_supp_caps_cmpl_evt(tBTM_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT *cs_read_remote_supp_caps) +{ + if (cs_read_remote_supp_caps->status != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, cs_read_remote_supp_caps->status); + cs_read_remote_supp_caps->status |= BTM_HCI_ERROR; + } + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)cs_read_remote_supp_caps); +} + +void btm_ble_cs_read_remote_fae_tab_cmpl_evt(tBTM_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT *cs_read_remote_fae_tab) +{ + if (cs_read_remote_fae_tab->status != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, cs_read_remote_fae_tab->status); + cs_read_remote_fae_tab->status |= BTM_HCI_ERROR; + } + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)cs_read_remote_fae_tab); +} + +void btm_ble_cs_securuty_enable_cmpl_evt(tBTM_BLE_CS_SEC_ENABLE_CMPL_EVT *cs_security_enable) +{ + if (cs_security_enable->status != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, cs_security_enable->status); + cs_security_enable->status |= BTM_HCI_ERROR; + } + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_SECURITY_ENABLE_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)cs_security_enable); +} + +void btm_ble_cs_config_cmpl_evt(tBTM_BLE_CS_CONFIG_CMPL_EVT *config_cmpl) +{ + if (config_cmpl->status != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, config_cmpl->status); + config_cmpl->status |= BTM_HCI_ERROR; + } + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_CONFIG_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)config_cmpl); +} + +void btm_ble_cs_proc_enable_cmpl_evt(tBTM_BLE_CS_PROC_ENABLE_CMPL_EVT *proc_en) +{ + if (proc_en->status != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err = 0x%x", __func__, proc_en->status); + proc_en->status |= BTM_HCI_ERROR; + } + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_PROC_ENABLE_CMPL_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)proc_en); +} + +void btm_ble_cs_subevt_result_evt(tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT *subevt_result) +{ + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_SUBEVENT_RESULT_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)subevt_result); +} + +void btm_ble_cs_subevt_continue_result_evt(tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT *subevt_result_continue) +{ + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_CS_SUBEVENT_RESULT_CONTINUE_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)subevt_result_continue); +} + +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c b/components/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c index 7eef55e912..8f00b9d690 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c @@ -22,1286 +22,5 @@ #include "common/bt_target.h" #if (BLE_INCLUDED == TRUE) -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE -#include "stack/bt_types.h" -#include "stack/hcimsgs.h" -#include "stack/btu.h" -#include "btm_int.h" -#include "osi/allocator.h" -#include "stack/hcidefs.h" -#include "stack/btm_ble_api.h" -#include "device/controller.h" -#define BTM_BLE_ADV_FILT_META_HDR_LENGTH 3 -#define BTM_BLE_ADV_FILT_FEAT_SELN_LEN 13 -#define BTM_BLE_ADV_FILT_TRACK_NUM 2 - -#define BTM_BLE_PF_SELECT_NONE 0 - -/* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */ -#define BTM_BLE_META_HDR_LENGTH 3 -#define BTM_BLE_PF_FEAT_SEL_LEN 18 -#define BTM_BLE_PCF_ENABLE_LEN 2 - -#define BTM_BLE_META_ADDR_LEN 7 -#define BTM_BLE_META_UUID_LEN 40 - -#define BTM_BLE_PF_BIT_TO_MASK(x) (UINT16)(1 << (x)) - - -#if BTM_DYNAMIC_MEMORY == FALSE -tBTM_BLE_ADV_FILTER_CB btm_ble_adv_filt_cb; -tBTM_BLE_VSC_CB cmn_ble_adv_vsc_cb; -#else -tBTM_BLE_ADV_FILTER_CB *btm_ble_adv_filt_cb_ptr; -tBTM_BLE_VSC_CB *cmn_ble_adv_vsc_cb_ptr; -#define btm_ble_adv_filt_cb (*btm_ble_adv_filt_cb_ptr) -#define cmn_ble_adv_vsc_cb (*cmn_ble_adv_vsc_cb_ptr) -#endif - -static const BD_ADDR na_bda = {0}; - -static UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action, - UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr, UINT8 num_available); - -#define BTM_BLE_SET_SCAN_PF_OPCODE(x, y) (((x)<<4)|y) -#define BTM_BLE_GET_SCAN_PF_SUBCODE(x) ((x) >> 4) -#define BTM_BLE_GET_SCAN_PF_ACTION(x) ((x) & 0x0f) -#define BTM_BLE_INVALID_COUNTER 0xff - - -/* length of each multi adv sub command */ -#define BTM_BLE_ADV_FILTER_ENB_LEN 3 - -/* length of each batch scan command */ -#define BTM_BLE_ADV_FILTER_CLEAR_LEN 3 -#define BTM_BLE_ADV_FILTER_LEN 2 - -#define BTM_BLE_ADV_FILT_CB_EVT_MASK 0xF0 -#define BTM_BLE_ADV_FILT_SUBCODE_MASK 0x0F - -/******************************************************************************* -** -** Function btm_ble_obtain_vsc_details -** -** Description This function obtains the VSC details -** -** Parameters -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_obtain_vsc_details(void) -{ - tBTM_STATUS st = BTM_SUCCESS; - -#if BLE_VND_INCLUDED == TRUE - BTM_BleGetVendorCapabilities(&cmn_ble_adv_vsc_cb); - if (0 == cmn_ble_adv_vsc_cb.max_filter) { - st = BTM_MODE_UNSUPPORTED; - return st; - } -#else - cmn_ble_adv_vsc_cb.max_filter = BTM_BLE_MAX_FILTER_COUNTER; -#endif - return st; -} - -/******************************************************************************* -** -** Function btm_ble_advfilt_enq_op_q -** -** Description enqueue an adv filter operation in q to check command complete -** status -** -** Returns void -** -*******************************************************************************/ -void btm_ble_advfilt_enq_op_q(UINT8 action, UINT8 ocf, tBTM_BLE_FILT_CB_EVT cb_evt, - tBTM_BLE_REF_VALUE ref, tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback, - tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback) -{ - btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx] = (action | (ocf << 4)); - btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.next_idx] = ref; - btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.next_idx] = cb_evt; - btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.next_idx] = p_cmpl_cback; - btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.next_idx] - = p_filt_param_cback; - BTM_TRACE_DEBUG("btm_ble_advfilt_enq_op_q: act_ocf:%d, action:%d, ocf:%d,cb_evt;%d, cback:%p", - btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx], action, - ocf, cb_evt, p_cmpl_cback); - btm_ble_adv_filt_cb.op_q.next_idx = (btm_ble_adv_filt_cb.op_q.next_idx + 1) - % BTM_BLE_PF_TYPE_MAX; -} - -/******************************************************************************* -** -** Function btm_ble_advfilt_deq_op_q -** -** Description dequeue an adv filter operation from q when command complete -** is received -** -** Returns void -** -*******************************************************************************/ -void btm_ble_advfilt_deq_op_q(UINT8 *p_action, UINT8 *p_ocf, tBTM_BLE_FILT_CB_EVT *p_cb_evt, - tBTM_BLE_REF_VALUE *p_ref, tBTM_BLE_PF_CFG_CBACK **p_cmpl_cback, - tBTM_BLE_PF_PARAM_CBACK **p_filt_param_cback) -{ - *p_ocf = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx] >> 4); - *p_action = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx] - & BTM_BLE_ADV_FILT_SUBCODE_MASK); - *p_ref = btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.pending_idx]; - *p_cb_evt = btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.pending_idx]; - *p_cmpl_cback = btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.pending_idx]; - *p_filt_param_cback = - btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.pending_idx]; - - btm_ble_adv_filt_cb.op_q.pending_idx = (btm_ble_adv_filt_cb.op_q.pending_idx + 1) - % BTM_BLE_PF_TYPE_MAX; - BTM_TRACE_DEBUG("btm_ble_advfilt_deq_op_q: ocf:%d, action:%d, ref_value:%d, cb_evt:%x", - *p_ocf, *p_action, *p_ref, *p_cb_evt); -} - -/******************************************************************************* -** -** Function btm_ble_condtype_to_ocf -** -** Description Convert cond_type to OCF -** -** Returns Returns ocf value -** -*******************************************************************************/ -UINT8 btm_ble_condtype_to_ocf(UINT8 cond_type) -{ - UINT8 ocf = 0; - - switch (cond_type) { - case BTM_BLE_PF_ADDR_FILTER: - ocf = BTM_BLE_META_PF_ADDR; - break; - case BTM_BLE_PF_SRVC_UUID: - ocf = BTM_BLE_META_PF_UUID; - break; - case BTM_BLE_PF_SRVC_SOL_UUID: - ocf = BTM_BLE_META_PF_SOL_UUID; - break; - case BTM_BLE_PF_LOCAL_NAME: - ocf = BTM_BLE_META_PF_LOCAL_NAME; - break; - case BTM_BLE_PF_MANU_DATA: - ocf = BTM_BLE_META_PF_MANU_DATA; - break; - case BTM_BLE_PF_SRVC_DATA_PATTERN: - ocf = BTM_BLE_META_PF_SRVC_DATA; - break; - case BTM_BLE_PF_TYPE_ALL: - ocf = BTM_BLE_META_PF_ALL; - break; - default: - ocf = BTM_BLE_PF_TYPE_MAX; - break; - } - return ocf; -} - -/******************************************************************************* -** -** Function btm_ble_ocf_to_condtype -** -** Description Convert OCF to cond type -** -** Returns Returns condtype value -** -*******************************************************************************/ -UINT8 btm_ble_ocf_to_condtype(UINT8 ocf) -{ - UINT8 cond_type = 0; - - switch (ocf) { - case BTM_BLE_META_PF_FEAT_SEL: - cond_type = BTM_BLE_META_PF_FEAT_SEL; - break; - case BTM_BLE_META_PF_ADDR: - cond_type = BTM_BLE_PF_ADDR_FILTER; - break; - case BTM_BLE_META_PF_UUID: - cond_type = BTM_BLE_PF_SRVC_UUID; - break; - case BTM_BLE_META_PF_SOL_UUID: - cond_type = BTM_BLE_PF_SRVC_SOL_UUID; - break; - case BTM_BLE_META_PF_LOCAL_NAME: - cond_type = BTM_BLE_PF_LOCAL_NAME; - break; - case BTM_BLE_META_PF_MANU_DATA: - cond_type = BTM_BLE_PF_MANU_DATA; - break; - case BTM_BLE_META_PF_SRVC_DATA: - cond_type = BTM_BLE_PF_SRVC_DATA_PATTERN; - break; - case BTM_BLE_META_PF_ALL: - cond_type = BTM_BLE_PF_TYPE_ALL; - break; - default: - cond_type = BTM_BLE_PF_TYPE_MAX; - break; - } - return cond_type; -} - -/******************************************************************************* -** -** Function btm_ble_scan_pf_cmpl_cback -** -** Description the BTM BLE customer feature VSC complete callback for ADV PF filtering -** -** Returns pointer to the counter if found; NULL otherwise. -** -*******************************************************************************/ -void btm_ble_scan_pf_cmpl_cback(tBTM_VSC_CMPL *p_params) -{ - UINT8 status = 0; - UINT8 *p = p_params->p_param_buf, op_subcode = 0, action = 0xff; - UINT16 evt_len = p_params->param_len; - UINT8 ocf = BTM_BLE_META_PF_ALL, cond_type = 0; - UINT8 num_avail = 0, cb_evt = 0; - tBTM_BLE_REF_VALUE ref_value = 0; - tBTM_BLE_PF_CFG_CBACK *p_scan_cfg_cback = NULL; - tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback = NULL; - - if (evt_len < 3 || evt_len > 4) { - BTM_TRACE_ERROR("%s cannot interpret APCF callback status = %d, length = %d", - __func__, status, evt_len); - btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback, - &p_filt_param_cback); - return; - } - - btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback, - &p_filt_param_cback); - - STREAM_TO_UINT8(status, p); - STREAM_TO_UINT8(op_subcode, p); - STREAM_TO_UINT8(action, p); - - /* Ignore the event, if it is not the same one expected */ - if (3 == evt_len) { - if (ocf != op_subcode) { - BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:3-Incorrect opcode :%d, %d, %d, %d, %d, %d", - ocf, op_subcode, action, evt_len, ref_value, status); - return; - } else { - if (NULL != btm_ble_adv_filt_cb.p_filt_stat_cback) { - btm_ble_adv_filt_cb.p_filt_stat_cback(action, status, ref_value); - } - BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback enabled/disabled, %d, %d, %d, %d", - ocf, action, status, ref_value); - return; - } - } - - if (4 == evt_len && ocf != op_subcode) { - BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:4-Incorrect opcode: %d, %d, %d, %d, %d", - ocf, op_subcode, action, status, ref_value); - return; - } - - STREAM_TO_UINT8(num_avail, p); - switch (op_subcode) { - case BTM_BLE_META_PF_ADDR: - case BTM_BLE_META_PF_UUID: - case BTM_BLE_META_PF_SOL_UUID: - case BTM_BLE_META_PF_LOCAL_NAME: - case BTM_BLE_META_PF_MANU_DATA: - case BTM_BLE_META_PF_SRVC_DATA: - cond_type = btm_ble_ocf_to_condtype(ocf); - BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback Recd: %d, %d, %d, %d, %d, %d", op_subcode, - ocf, action, status, ref_value, num_avail); - if (HCI_SUCCESS == status) { - if (memcmp(&btm_ble_adv_filt_cb.cur_filter_target.bda, &na_bda, BD_ADDR_LEN) == 0) { - btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail); - } else { - btm_ble_cs_update_pf_counter(action, cond_type, - &btm_ble_adv_filt_cb.cur_filter_target, num_avail); - } - } - - /* send ADV PF operation complete */ - btm_ble_adv_filt_cb.op_type = 0; - break; - - case BTM_BLE_META_PF_FEAT_SEL: - BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback-Feat sel event: %d, %d, %d, %d", - action, status, ref_value, num_avail); - break; - - default: - BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback: unknown operation: %d", op_subcode); - break; - } - - BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback: calling the cback: %d", cb_evt); - switch (cb_evt) { - case BTM_BLE_FILT_CFG: - if (NULL != p_scan_cfg_cback) { - p_scan_cfg_cback(action, cond_type, num_avail, status, ref_value); - } - break; - case BTM_BLE_FILT_ADV_PARAM: - if (NULL != p_filt_param_cback) { - p_filt_param_cback(action, num_avail, ref_value, status); - } - break; - default: - break; - } -} - -/******************************************************************************* -** -** Function btm_ble_find_addr_filter_counter -** -** Description find the per bd address ADV payload filter counter by BD_ADDR. -** -** Returns pointer to the counter if found; NULL otherwise. -** -*******************************************************************************/ -tBTM_BLE_PF_COUNT *btm_ble_find_addr_filter_counter(tBLE_BD_ADDR *p_le_bda) -{ - UINT8 i; - tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1]; - - if (p_le_bda == NULL) { - return &btm_ble_adv_filt_cb.p_addr_filter_count[0]; - } - - for (i = 0; i < cmn_ble_adv_vsc_cb.max_filter; i ++, p_addr_filter ++) { - if (p_addr_filter->in_use && - memcmp(p_le_bda->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) { - return p_addr_filter; - } - } - return NULL; -} - -/******************************************************************************* -** -** Function btm_ble_alloc_addr_filter_counter -** -** Description allocate the per device adv payload filter counter. -** -** Returns pointer to the counter if allocation succeed; NULL otherwise. -** -*******************************************************************************/ -tBTM_BLE_PF_COUNT *btm_ble_alloc_addr_filter_counter(BD_ADDR bd_addr) -{ - UINT8 i; - tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1]; - - for (i = 0; i < cmn_ble_adv_vsc_cb.max_filter; i ++, p_addr_filter ++) { - if (memcmp(na_bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) { - memcpy(p_addr_filter->bd_addr, bd_addr, BD_ADDR_LEN); - p_addr_filter->in_use = TRUE; - return p_addr_filter; - } - } - return NULL; -} -/******************************************************************************* -** -** Function btm_ble_dealloc_addr_filter_counter -** -** Description de-allocate the per device adv payload filter counter. -** -** Returns TRUE if deallocation succeed; FALSE otherwise. -** -*******************************************************************************/ -BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filter_type) -{ - UINT8 i; - tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1]; - BOOLEAN found = FALSE; - - if (BTM_BLE_PF_TYPE_ALL == filter_type && NULL == p_bd_addr) { - memset(&btm_ble_adv_filt_cb.p_addr_filter_count[0], 0, sizeof(tBTM_BLE_PF_COUNT)); - } - - for (i = 0; i < cmn_ble_adv_vsc_cb.max_filter; i ++, p_addr_filter ++) { - if ((p_addr_filter->in_use) && (NULL == p_bd_addr || - (memcmp(p_bd_addr->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)) { - found = TRUE; - memset(p_addr_filter, 0, sizeof(tBTM_BLE_PF_COUNT)); - - if (NULL != p_bd_addr) { - break; - } - } - } - return found; -} - -/******************************************************************************* -** -** Function btm_ble_update_pf_local_name -** -** Description this function update(add,delete or clear) the adv local name filtering condition. -** -** -** Returns BTM_SUCCESS if successful, -** BTM_ILLEGAL_VALUE if parameter is not valid. -** -*******************************************************************************/ -tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action, - tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_COND_PARAM *p_cond) -{ - tBTM_BLE_PF_LOCAL_NAME_COND *p_local_name = (p_cond == NULL) ? NULL : &p_cond->local_name; - UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH], - *p = param, - len = BTM_BLE_ADV_FILT_META_HDR_LENGTH; - tBTM_STATUS st = BTM_ILLEGAL_VALUE; - - memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH); - - UINT8_TO_STREAM(p, BTM_BLE_META_PF_LOCAL_NAME); - UINT8_TO_STREAM(p, action); - - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - if (BTM_BLE_SCAN_COND_ADD == action || - BTM_BLE_SCAN_COND_DELETE == action) { - if (NULL == p_local_name) { - return st; - } - - if (p_local_name->data_len > BTM_BLE_PF_STR_LEN_MAX) { - p_local_name->data_len = BTM_BLE_PF_STR_LEN_MAX; - } - - ARRAY_TO_STREAM(p, p_local_name->p_data, p_local_name->data_len); - len += p_local_name->data_len; - } - - /* send local name filter */ - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - len, - param, - btm_ble_scan_pf_cmpl_cback)) - != BTM_NO_RESOURCES) { - memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); - } else { - BTM_TRACE_ERROR("Local Name PF filter update failed"); - } - - return st; -} - - -/******************************************************************************* -** -** Function btm_ble_update_srvc_data_change -** -** Description this function update(add/remove) service data change filter. -** -** -** Returns BTM_SUCCESS if successful, -** BTM_ILLEGAL_VALUE if parameter is not valid. -** -*******************************************************************************/ -tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action, - tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_COND_PARAM *p_cond) -{ - tBTM_STATUS st = BTM_ILLEGAL_VALUE; - tBLE_BD_ADDR *p_bd_addr = p_cond ? &p_cond->target_addr : NULL; - UINT8 num_avail = (action == BTM_BLE_SCAN_COND_ADD) ? 0 : 1; - - if (btm_ble_cs_update_pf_counter (action, BTM_BLE_PF_SRVC_DATA, p_bd_addr, num_avail) - != BTM_BLE_INVALID_COUNTER) { - st = BTM_SUCCESS; - } - - return st; -} - -/******************************************************************************* -** -** Function btm_ble_update_pf_manu_data -** -** Description this function update(add,delete or clear) the adv manufacturer -** data filtering condition. -** -** -** Returns BTM_SUCCESS if successful, -** BTM_ILLEGAL_VALUE if parameter is not valid. -** -*******************************************************************************/ -tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action, - tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_COND_PARAM *p_data, - tBTM_BLE_PF_COND_TYPE cond_type, - tBTM_BLE_FILT_CB_EVT cb_evt, - tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_BLE_PF_MANU_COND *p_manu_data = (p_data == NULL) ? NULL : &p_data->manu_data; - tBTM_BLE_PF_SRVC_PATTERN_COND *p_srvc_data = (p_data == NULL) ? NULL : &p_data->srvc_data; - - UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH], - *p = param, - len = BTM_BLE_ADV_FILT_META_HDR_LENGTH; - tBTM_STATUS st = BTM_ILLEGAL_VALUE; - - if (NULL == p_data) { - return st; - } - - memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX - + BTM_BLE_ADV_FILT_META_HDR_LENGTH); - - if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) { - UINT8_TO_STREAM(p, BTM_BLE_META_PF_SRVC_DATA); - } else { - UINT8_TO_STREAM(p, BTM_BLE_META_PF_MANU_DATA); - } - - UINT8_TO_STREAM(p, action); - - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - if (BTM_BLE_SCAN_COND_ADD == action || BTM_BLE_SCAN_COND_DELETE == action) { - if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) { - if (NULL == p_srvc_data) { - return st; - } - if (p_srvc_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) { - p_srvc_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2); - } - - if (p_srvc_data->data_len > 0) { - ARRAY_TO_STREAM(p, p_srvc_data->p_pattern, p_srvc_data->data_len); - len += (p_srvc_data->data_len); - ARRAY_TO_STREAM(p, p_srvc_data->p_pattern_mask, p_srvc_data->data_len); - } - - len += (p_srvc_data->data_len); - BTM_TRACE_DEBUG("Service data length: %d", len); - } else { - if (NULL == p_manu_data) { - BTM_TRACE_ERROR("btm_ble_update_pf_manu_data - No manuf data"); - return st; - } - BTM_TRACE_EVENT("btm_ble_update_pf_manu_data length: %d", - p_manu_data->data_len); - if (p_manu_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) { - p_manu_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2); - } - - UINT16_TO_STREAM(p, p_manu_data->company_id); - if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL) { - ARRAY_TO_STREAM(p, p_manu_data->p_pattern, p_manu_data->data_len); - len += (p_manu_data->data_len + 2); - } else { - len += 2; - } - - if (p_manu_data->company_id_mask != 0) { - UINT16_TO_STREAM (p, p_manu_data->company_id_mask); - } else { - memset(p, 0xff, 2); - p += 2; - } - len += 2; - - if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL) { - ARRAY_TO_STREAM(p, p_manu_data->p_pattern_mask, p_manu_data->data_len); - len += (p_manu_data->data_len); - } - - BTM_TRACE_DEBUG("Manuf data length: %d", len); - } - } - - /* send manufacturer*/ - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - len, - param, - btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) { - memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); - } else { - BTM_TRACE_ERROR("manufacturer data PF filter update failed"); - } - - return st; -} - -/******************************************************************************* -** -** Function btm_ble_cs_update_pf_counter -** -** Description this function is to update the adv data payload filter counter -** -** Returns current number of the counter; BTM_BLE_INVALID_COUNTER if -** counter update failed. -** -*******************************************************************************/ -UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action, - UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr, - UINT8 num_available) -{ - tBTM_BLE_PF_COUNT *p_addr_filter = NULL; - UINT8 *p_counter = NULL; - - btm_ble_obtain_vsc_details(); - - if (cond_type > BTM_BLE_PF_TYPE_ALL) { - BTM_TRACE_ERROR("unknown PF filter condition type %d", cond_type); - return BTM_BLE_INVALID_COUNTER; - } - - /* for these three types of filter, always generic */ - if (BTM_BLE_PF_ADDR_FILTER == cond_type || - BTM_BLE_PF_MANU_DATA == cond_type || - BTM_BLE_PF_LOCAL_NAME == cond_type || - BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) { - p_bd_addr = NULL; - } - - if ((p_addr_filter = btm_ble_find_addr_filter_counter(p_bd_addr)) == NULL && - BTM_BLE_SCAN_COND_ADD == action) { - p_addr_filter = btm_ble_alloc_addr_filter_counter(p_bd_addr->bda); - } - - if (NULL != p_addr_filter) { - /* all filter just cleared */ - if ((BTM_BLE_PF_TYPE_ALL == cond_type && BTM_BLE_SCAN_COND_CLEAR == action) || - /* or bd address filter been deleted */ - (BTM_BLE_PF_ADDR_FILTER == cond_type && - (BTM_BLE_SCAN_COND_DELETE == action || BTM_BLE_SCAN_COND_CLEAR == action))) { - btm_ble_dealloc_addr_filter_counter(p_bd_addr, cond_type); - } - /* if not feature selection, update new addition/reduction of the filter counter */ - else if (cond_type != BTM_BLE_PF_TYPE_ALL) { - p_counter = p_addr_filter->pf_counter; - if (num_available > 0) { - p_counter[cond_type] += 1; - } - - BTM_TRACE_DEBUG("counter = %d, maxfilt = %d, num_avbl=%d", - p_counter[cond_type], cmn_ble_adv_vsc_cb.max_filter, num_available); - return p_counter[cond_type]; - } - } else { - BTM_TRACE_ERROR("no matching filter counter found"); - } - /* no matching filter located and updated */ - return BTM_BLE_INVALID_COUNTER; -} - - -/******************************************************************************* -** -** Function btm_ble_update_addr_filter -** -** Description this function update(add,delete or clear) the address filter of adv. -** -** -** Returns BTM_SUCCESS if successful, -** BTM_ILLEGAL_VALUE if parameter is not valid. -** -*******************************************************************************/ -tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action, - tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_COND_PARAM *p_cond) -{ - UINT8 param[BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH], - * p = param; - tBTM_STATUS st = BTM_ILLEGAL_VALUE; - tBLE_BD_ADDR *p_addr = (p_cond == NULL) ? NULL : &p_cond->target_addr; - - memset(param, 0, BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH); - - UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR); - UINT8_TO_STREAM(p, action); - - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - if (BTM_BLE_SCAN_COND_ADD == action || - BTM_BLE_SCAN_COND_DELETE == action) { - if (NULL == p_addr) { - return st; - } - - BDADDR_TO_STREAM(p, p_addr->bda); - UINT8_TO_STREAM(p, p_addr->type); - } - /* send address filter */ - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN), - param, - btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) { - memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); - } else { - BTM_TRACE_ERROR("Broadcaster Address Filter Update failed"); - } - return st; -} - -/******************************************************************************* -** -** Function btm_ble_update_uuid_filter -** -** Description this function update(add,delete or clear) service UUID filter. -** -** -** Returns BTM_SUCCESS if successful, -** BTM_ILLEGAL_VALUE if parameter is not valid. -** -*******************************************************************************/ -tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action, - tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_COND_TYPE filter_type, - tBTM_BLE_PF_COND_PARAM *p_cond, - tBTM_BLE_FILT_CB_EVT cb_evt, - tBTM_BLE_REF_VALUE ref_value) -{ - UINT8 param[BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH], - * p = param, - len = BTM_BLE_ADV_FILT_META_HDR_LENGTH; - tBTM_STATUS st = BTM_ILLEGAL_VALUE; - tBTM_BLE_PF_UUID_COND *p_uuid_cond; - UINT8 evt_type; - - memset(param, 0, BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH); - - if (BTM_BLE_PF_SRVC_UUID == filter_type) { - evt_type = BTM_BLE_META_PF_UUID; - p_uuid_cond = p_cond ? &p_cond->srvc_uuid : NULL; - } else { - evt_type = BTM_BLE_META_PF_SOL_UUID; - p_uuid_cond = p_cond ? &p_cond->solicitate_uuid : NULL; - } - - if (NULL == p_uuid_cond && action != BTM_BLE_SCAN_COND_CLEAR) { - BTM_TRACE_ERROR("Illegal param for add/delete UUID filter"); - return st; - } - - /* need to add address filter first, if adding per bda UUID filter without address filter */ - if (BTM_BLE_SCAN_COND_ADD == action && NULL != p_uuid_cond && - p_uuid_cond->p_target_addr && - btm_ble_find_addr_filter_counter(p_uuid_cond->p_target_addr) == NULL) { - UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR); - UINT8_TO_STREAM(p, action); - - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda); - UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type); - - /* send address filter */ - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN), - param, - btm_ble_scan_pf_cmpl_cback)) == BTM_NO_RESOURCES) { - BTM_TRACE_ERROR("Update Address filter into controller failed."); - return st; - } - - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_ADDR, cb_evt, ref_value, NULL, NULL); - BTM_TRACE_DEBUG("Updated Address filter"); - } - - p = param; - UINT8_TO_STREAM(p, evt_type); - UINT8_TO_STREAM(p, action); - - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - if ((BTM_BLE_SCAN_COND_ADD == action || - BTM_BLE_SCAN_COND_DELETE == action) && - NULL != p_uuid_cond) { - if (p_uuid_cond->uuid.len == LEN_UUID_16) { - UINT16_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid16); - len += LEN_UUID_16; - } else if (p_uuid_cond->uuid.len == LEN_UUID_32) { /*4 bytes */ - UINT32_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid32); - len += LEN_UUID_32; - } else if (p_uuid_cond->uuid.len == LEN_UUID_128) { - ARRAY_TO_STREAM (p, p_uuid_cond->uuid.uu.uuid128, LEN_UUID_128); - len += LEN_UUID_128; - } else { - BTM_TRACE_ERROR("illegal UUID length: %d", p_uuid_cond->uuid.len); - return BTM_ILLEGAL_VALUE; - } - - if (NULL != p_uuid_cond->p_uuid_mask) { - if (p_uuid_cond->uuid.len == LEN_UUID_16) { - UINT16_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid16_mask); - len += LEN_UUID_16; - } else if (p_uuid_cond->uuid.len == LEN_UUID_32) { /*4 bytes */ - UINT32_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid32_mask); - len += LEN_UUID_32; - } else if (p_uuid_cond->uuid.len == LEN_UUID_128) { - ARRAY_TO_STREAM (p, p_uuid_cond->p_uuid_mask->uuid128_mask, LEN_UUID_128); - len += LEN_UUID_128; - } - } else { - memset(p, 0xff, p_uuid_cond->uuid.len); - len += p_uuid_cond->uuid.len; - } - BTM_TRACE_DEBUG("btm_ble_update_uuid_filter : %d, %d, %d, %d", filter_type, evt_type, - p_uuid_cond->uuid.len, len); - } - - /* send UUID filter update */ - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - len, - param, - btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) { - if (p_uuid_cond && p_uuid_cond->p_target_addr) { - memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_uuid_cond->p_target_addr, - sizeof(tBLE_BD_ADDR)); - } - else { - memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); - } - } else { - BTM_TRACE_ERROR("UUID filter updating failed"); - } - - return st; -} - - -/******************************************************************************* -** -** Function btm_ble_clear_scan_pf_filter -** -** Description clear all adv payload filter by de-select all the adv pf feature bits -** -** -** Returns BTM_SUCCESS if successful, -** BTM_ILLEGAL_VALUE if parameter is not valid. -** -*******************************************************************************/ -tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action, - tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_COND_PARAM *p_cond, - tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback, - tBTM_BLE_FILT_CB_EVT cb_evt, - tBTM_BLE_REF_VALUE ref_value) -{ - tBLE_BD_ADDR *p_target = (p_cond == NULL) ? NULL : &p_cond->target_addr; - tBTM_BLE_PF_COUNT *p_bda_filter; - tBTM_STATUS st = BTM_WRONG_MODE; - UINT8 param[20], *p; - - if (BTM_BLE_SCAN_COND_CLEAR != action) { - BTM_TRACE_ERROR("unable to perform action:%d for generic adv filter type", action); - return BTM_ILLEGAL_VALUE; - } - - p = param; - memset(param, 0, 20); - - p_bda_filter = btm_ble_find_addr_filter_counter(p_target); - - if (NULL == p_bda_filter || - /* not a generic filter */ - (p_target != NULL)) { - BTM_TRACE_ERROR("Error: Can not clear filter, No PF filter has been configured!"); - return st; - } - - /* clear the general filter entry */ - if (NULL == p_target) { - /* clear manufacturer data filter */ - st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL, - BTM_BLE_PF_MANU_DATA, cb_evt, ref_value); - if (BTM_CMD_STARTED == st) { - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_MANU_DATA, cb_evt, - ref_value, NULL, NULL); - } - - /* clear local name filter */ - st = btm_ble_update_pf_local_name(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL); - if (BTM_CMD_STARTED == st) { - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_LOCAL_NAME, cb_evt, - ref_value, NULL, NULL); - } - - /* update the counter for service data */ - st = btm_ble_update_srvc_data_change(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL); - - /* clear UUID filter */ - st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index, - BTM_BLE_PF_SRVC_UUID, NULL, cb_evt, ref_value); - if (BTM_CMD_STARTED == st) { - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_UUID, cb_evt, ref_value, NULL, NULL); - } - - st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index, - BTM_BLE_PF_SRVC_SOL_UUID, NULL, cb_evt, ref_value); - if (BTM_CMD_STARTED == st) { - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SOL_UUID, cb_evt, - ref_value, NULL, NULL); - } - - /* clear service data filter */ - st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL, - BTM_BLE_PF_SRVC_DATA_PATTERN, cb_evt, ref_value); - if (BTM_CMD_STARTED == st) { - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SRVC_DATA, cb_evt, - ref_value, NULL, NULL); - } - } - - /* select feature based on control block settings */ - UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); - UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR); - - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - /* set PCF selection */ - UINT32_TO_STREAM(p, BTM_BLE_PF_SELECT_NONE); - /* set logic condition as OR as default */ - UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR); - - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN), - param, - btm_ble_scan_pf_cmpl_cback)) - != BTM_NO_RESOURCES) { - if (p_target) { - memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_target, sizeof(tBLE_BD_ADDR)); - } else { - memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); - } - } - return st; -} - -/******************************************************************************* -** -** Function BTM_BleAdvFilterParamSetup -** -** Description This function is called to setup the adv data payload filter -** condition. -** -** Parameters action - Type of action to be performed -** filt_index - Filter index -** p_filt_params - Filter parameters -** p_target - Target device -** p_cmpl_back - Callback pointer -** ref_value - reference value -** -** Returns void -** -*******************************************************************************/ -tBTM_STATUS BTM_BleAdvFilterParamSetup(int action, tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_FILT_PARAMS *p_filt_params, - tBLE_BD_ADDR *p_target, tBTM_BLE_PF_PARAM_CBACK *p_cmpl_cback, - tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_STATUS st = BTM_WRONG_MODE; - tBTM_BLE_PF_COUNT *p_bda_filter = NULL; - UINT8 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN + - BTM_BLE_ADV_FILT_TRACK_NUM; - UINT8 param[len], *p; - - if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) { - return st; - } - - p = param; - memset(param, 0, len); - BTM_TRACE_EVENT (" BTM_BleAdvFilterParamSetup"); - - if (BTM_BLE_SCAN_COND_ADD == action) { - p_bda_filter = btm_ble_find_addr_filter_counter(p_target); - if (NULL == p_bda_filter) { - BTM_TRACE_ERROR("BD Address not found!"); - return st; - } - - BTM_TRACE_DEBUG("BTM_BleAdvFilterParamSetup : Feat mask:%d", p_filt_params->feat_seln); - /* select feature based on control block settings */ - UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); - UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_ADD); - - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - /* set PCF selection */ - UINT16_TO_STREAM(p, p_filt_params->feat_seln); - /* set logic type */ - UINT16_TO_STREAM(p, p_filt_params->logic_type); - /* set logic condition */ - UINT8_TO_STREAM(p, p_filt_params->filt_logic_type); - /* set RSSI high threshold */ - UINT8_TO_STREAM(p, p_filt_params->rssi_high_thres); - /* set delivery mode */ - UINT8_TO_STREAM(p, p_filt_params->dely_mode); - - if (0x01 == p_filt_params->dely_mode) { - /* set onfound timeout */ - UINT16_TO_STREAM(p, p_filt_params->found_timeout); - /* set onfound timeout count*/ - UINT8_TO_STREAM(p, p_filt_params->found_timeout_cnt); - /* set RSSI low threshold */ - UINT8_TO_STREAM(p, p_filt_params->rssi_low_thres); - /* set onlost timeout */ - UINT16_TO_STREAM(p, p_filt_params->lost_timeout); - /* set num_of_track_entries for firmware greater than L-release version */ - if (cmn_ble_adv_vsc_cb.version_supported > BTM_VSC_CHIP_CAPABILITY_L_VERSION) { - UINT16_TO_STREAM(p, p_filt_params->num_of_tracking_entries); - } - } - - if (cmn_ble_adv_vsc_cb.version_supported == BTM_VSC_CHIP_CAPABILITY_L_VERSION) { - len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN; - } else { - len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN + - BTM_BLE_ADV_FILT_TRACK_NUM; - } - - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - (UINT8)len, - param, - btm_ble_scan_pf_cmpl_cback)) - == BTM_NO_RESOURCES) { - return st; - } - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM, - ref_value, NULL, p_cmpl_cback); - } else if (BTM_BLE_SCAN_COND_DELETE == action) { - /* select feature based on control block settings */ - UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); - UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_DELETE); - /* Filter index */ - UINT8_TO_STREAM(p, filt_index); - - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH), - param, - btm_ble_scan_pf_cmpl_cback)) - == BTM_NO_RESOURCES) { - return st; - } - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM, - ref_value, NULL, p_cmpl_cback); - } else if (BTM_BLE_SCAN_COND_CLEAR == action) { - /* Deallocate all filters here */ - btm_ble_dealloc_addr_filter_counter(NULL, BTM_BLE_PF_TYPE_ALL); - - /* select feature based on control block settings */ - UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL); - UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR); - - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH - 1), - param, - btm_ble_scan_pf_cmpl_cback)) - == BTM_NO_RESOURCES) { - return st; - } - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM, - ref_value, NULL, p_cmpl_cback); - } - - return st; -} - -/******************************************************************************* -** -** Function BTM_BleEnableDisableFilterFeature -** -** Description This function is called to enable / disable the APCF feature -** -** Parameters enable the generic scan condition. -** enable: enable or disable the filter condition -** p_stat_cback - Status callback pointer -** ref_value - Ref value -** Returns void -** -*******************************************************************************/ -tBTM_STATUS BTM_BleEnableDisableFilterFeature(UINT8 enable, - tBTM_BLE_PF_STATUS_CBACK *p_stat_cback, - tBTM_BLE_REF_VALUE ref_value) -{ - UINT8 param[20], *p; - tBTM_STATUS st = BTM_WRONG_MODE; - - if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) { - return st; - } - - p = param; - memset(param, 0, 20); - - /* enable the content filter in controller */ - p = param; - UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE); - /* enable adv data payload filtering */ - UINT8_TO_STREAM(p, enable); - - if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF, - BTM_BLE_PCF_ENABLE_LEN, param, - btm_ble_scan_pf_cmpl_cback)) == BTM_CMD_STARTED) { - btm_ble_adv_filt_cb.p_filt_stat_cback = p_stat_cback; - btm_ble_advfilt_enq_op_q(enable, BTM_BLE_META_PF_ENABLE, BTM_BLE_FILT_ENABLE_DISABLE, - ref_value, NULL, NULL); - } - return st; -} - -/******************************************************************************* -** -** Function BTM_BleCfgFilterCondition -** -** Description This function is called to configure the adv data payload filter -** condition. -** -** Parameters action: to read/write/clear -** cond_type: filter condition type. -** filt_index - Filter index -** p_cond: filter condition parameter -** p_cmpl_cback - Config callback pointer -** ref_value - Reference value -** -** Returns void -** -*******************************************************************************/ -tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action, - tBTM_BLE_PF_COND_TYPE cond_type, - tBTM_BLE_PF_FILT_INDEX filt_index, - tBTM_BLE_PF_COND_PARAM *p_cond, - tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback, - tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_STATUS st = BTM_ILLEGAL_VALUE; - UINT8 ocf = 0; - BTM_TRACE_EVENT (" BTM_BleCfgFilterCondition action:%d, cond_type:%d, index:%d", action, - cond_type, filt_index); - - if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) { - return st; - } - - switch (cond_type) { - /* write service data filter */ - case BTM_BLE_PF_SRVC_DATA_PATTERN: - /* write manufacturer data filter */ - case BTM_BLE_PF_MANU_DATA: - st = btm_ble_update_pf_manu_data(action, filt_index, p_cond, cond_type, 0, ref_value); - break; - - /* write local name filter */ - case BTM_BLE_PF_LOCAL_NAME: - st = btm_ble_update_pf_local_name(action, filt_index, p_cond); - break; - - /* filter on advertiser address */ - case BTM_BLE_PF_ADDR_FILTER: - st = btm_ble_update_addr_filter(action, filt_index, p_cond); - break; - - /* filter on service/solicited UUID */ - case BTM_BLE_PF_SRVC_UUID: - case BTM_BLE_PF_SRVC_SOL_UUID: - st = btm_ble_update_uuid_filter(action, filt_index, cond_type, p_cond, 0, ref_value); - break; - - case BTM_BLE_PF_SRVC_DATA: - st = btm_ble_update_srvc_data_change(action, filt_index, p_cond); - break; - - case BTM_BLE_PF_TYPE_ALL: /* only used to clear filter */ - st = btm_ble_clear_scan_pf_filter(action, filt_index, p_cond, p_cmpl_cback, - 0, ref_value); - break; - - default: - BTM_TRACE_WARNING("condition type [%d] not supported currently.", cond_type); - break; - } - - if (BTM_CMD_STARTED == st && cond_type != BTM_BLE_PF_TYPE_ALL) { - ocf = btm_ble_condtype_to_ocf(cond_type); - btm_ble_advfilt_enq_op_q(action, ocf, BTM_BLE_FILT_CFG, ref_value, p_cmpl_cback, NULL); - } else if (BTM_CMD_STARTED == st && BTM_BLE_PF_TYPE_ALL == cond_type) { - btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_CFG, - ref_value, p_cmpl_cback, NULL); - } - return st; -} - -/******************************************************************************* -** -** Function btm_ble_adv_filter_init -** -** Description This function initializes the adv filter control block -** -** Parameters -** -** Returns status -** -*******************************************************************************/ -void btm_ble_adv_filter_init(void) -{ -#if BTM_DYNAMIC_MEMORY == TRUE - btm_ble_adv_filt_cb_ptr = (tBTM_BLE_ADV_FILTER_CB *)osi_malloc(sizeof(tBTM_BLE_ADV_FILTER_CB)); - cmn_ble_adv_vsc_cb_ptr = (tBTM_BLE_VSC_CB *)osi_malloc(sizeof(tBTM_BLE_VSC_CB)); - if (btm_ble_adv_filt_cb_ptr == NULL || cmn_ble_adv_vsc_cb_ptr == NULL) { - BTM_TRACE_ERROR("%s malloc failed", __func__); - return; - } - memset((void *)btm_ble_adv_filt_cb_ptr, 0, sizeof(tBTM_BLE_ADV_FILTER_CB)); - memset((void *)cmn_ble_adv_vsc_cb_ptr, 0, sizeof(tBTM_BLE_VSC_CB)); -#endif - memset(&btm_ble_adv_filt_cb, 0, sizeof(tBTM_BLE_ADV_FILTER_CB)); - if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) { - return; - } - - if (cmn_ble_adv_vsc_cb.max_filter > 0) { - btm_ble_adv_filt_cb.p_addr_filter_count = - (tBTM_BLE_PF_COUNT *) osi_malloc( sizeof(tBTM_BLE_PF_COUNT) * cmn_ble_adv_vsc_cb.max_filter); - } -} - -/******************************************************************************* -** -** Function btm_ble_adv_filter_cleanup -** -** Description This function de-initializes the adv filter control block -** -** Parameters -** -** Returns status -** -*******************************************************************************/ -void btm_ble_adv_filter_cleanup(void) -{ - if (btm_ble_adv_filt_cb.p_addr_filter_count) { - osi_free(btm_ble_adv_filt_cb.p_addr_filter_count); - btm_ble_adv_filt_cb.p_addr_filter_count = NULL; - } - -#if BTM_DYNAMIC_MEMORY == TRUE - osi_free(btm_ble_adv_filt_cb_ptr); - btm_ble_adv_filt_cb_ptr = NULL; - osi_free(cmn_ble_adv_vsc_cb_ptr); - cmn_ble_adv_vsc_cb_ptr = NULL; -#endif -} - -#endif // #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE #endif diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c b/components/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c index b4b586431c..6fb140e210 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c @@ -29,949 +29,6 @@ #include "stack/hcimsgs.h" #if (BLE_INCLUDED == TRUE) -#if (BLE_HOST_BATCH_SCAN_EN == TRUE) -#if BTM_DYNAMIC_MEMORY == FALSE -tBTM_BLE_BATCH_SCAN_CB ble_batchscan_cb; -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -tBTM_BLE_ADV_TRACK_CB ble_advtrack_cb; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -#else -tBTM_BLE_BATCH_SCAN_CB *ble_batchscan_cb_ptr; -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -tBTM_BLE_ADV_TRACK_CB *ble_advtrack_cb_ptr; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -#define ble_batchscan_cb (*ble_batchscan_cb_ptr) -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -#define ble_advtrack_cb (*ble_advtrack_cb_ptr) -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -#endif - -/* length of each batch scan command */ -#define BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN 4 -#define BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN 12 -#define BTM_BLE_BATCH_SCAN_ENB_DISB_LEN 2 -#define BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN 2 - -#define BTM_BLE_BATCH_SCAN_CB_EVT_MASK 0xF0 -#define BTM_BLE_BATCH_SCAN_SUBCODE_MASK 0x0F - -/******************************************************************************* -** Local functions -*******************************************************************************/ -void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params); -void btm_ble_batchscan_cleanup(void); - -/******************************************************************************* -** -** Function btm_ble_batchscan_filter_track_adv_vse_cback -** -** Description VSE callback for batch scan, filter, and tracking events. -** -** Returns None -** -*******************************************************************************/ -void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p) -{ -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - tBTM_BLE_TRACK_ADV_DATA adv_data; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - UINT8 sub_event = 0; - STREAM_TO_UINT8(sub_event, p); - - BTM_TRACE_EVENT("btm_ble_batchscan_filter_track_adv_vse_cback called with event:%x", sub_event); - if (HCI_VSE_SUBCODE_BLE_THRESHOLD_SUB_EVT == sub_event && - NULL != ble_batchscan_cb.p_thres_cback) { - ble_batchscan_cb.p_thres_cback(ble_batchscan_cb.ref_value); - return; - } -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - if (HCI_VSE_SUBCODE_BLE_TRACKING_SUB_EVT == sub_event && NULL != ble_advtrack_cb.p_track_cback) { - if (len < 10) { - return; - } - - memset(&adv_data, 0 , sizeof(tBTM_BLE_TRACK_ADV_DATA)); - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - adv_data.client_if = (UINT8)ble_advtrack_cb.ref_value; - if (cmn_ble_vsc_cb.version_supported > BTM_VSC_CHIP_CAPABILITY_L_VERSION) { - STREAM_TO_UINT8(adv_data.filt_index, p); - STREAM_TO_UINT8(adv_data.advertiser_state, p); - STREAM_TO_UINT8(adv_data.advertiser_info_present, p); - STREAM_TO_BDADDR(adv_data.bd_addr.address, p); - STREAM_TO_UINT8(adv_data.addr_type, p); - - /* Extract the adv info details */ - if (ADV_INFO_PRESENT == adv_data.advertiser_info_present) { - STREAM_TO_UINT8(adv_data.tx_power, p); - STREAM_TO_UINT8(adv_data.rssi_value, p); - STREAM_TO_UINT16(adv_data.time_stamp, p); - - STREAM_TO_UINT8(adv_data.adv_pkt_len, p); - if (adv_data.adv_pkt_len > 0) { - adv_data.p_adv_pkt_data = osi_malloc(adv_data.adv_pkt_len); - memcpy(adv_data.p_adv_pkt_data, p, adv_data.adv_pkt_len); - } - - STREAM_TO_UINT8(adv_data.scan_rsp_len, p); - if (adv_data.scan_rsp_len > 0) { - adv_data.p_scan_rsp_data = osi_malloc(adv_data.scan_rsp_len); - memcpy(adv_data.p_scan_rsp_data, p, adv_data.scan_rsp_len); - } - } - } else { - /* Based on L-release version */ - STREAM_TO_UINT8(adv_data.filt_index, p); - STREAM_TO_UINT8(adv_data.addr_type, p); - STREAM_TO_BDADDR(adv_data.bd_addr.address, p); - STREAM_TO_UINT8(adv_data.advertiser_state, p); - } - - BTM_TRACE_EVENT("track_adv_vse_cback called: %d, %d, %d", adv_data.filt_index, - adv_data.addr_type, adv_data.advertiser_state); - ble_advtrack_cb.p_track_cback(&adv_data); - return; - } -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -} - -/******************************************************************************* -** -** Function btm_ble_batchscan_enq_op_q -** -** Description enqueue a batchscan operation in q to check command complete -** status -** -** Returns void -** -*******************************************************************************/ -void btm_ble_batchscan_enq_op_q(UINT8 opcode, tBTM_BLE_BATCH_SCAN_STATE cur_state, - UINT8 cb_evt, tBTM_BLE_REF_VALUE ref_value) -{ - ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx] = (opcode | (cb_evt << 4)); - ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx] = cur_state; - ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx] = ref_value; - BTM_TRACE_DEBUG("btm_ble_batchscan_enq_op_q: subcode:%d, Cur_state:%d, ref_value:%d", - ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx], - ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx], - ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx]); - ble_batchscan_cb.op_q.next_idx = (ble_batchscan_cb.op_q.next_idx + 1) - % BTM_BLE_BATCH_SCAN_MAX; -} - -/******************************************************************************* -** -** Function btm_ble_batchscan_enq_rep_q -** -** Description enqueue a batchscan report operation in q to check command complete -** status -** -** Returns void -** -*******************************************************************************/ -tBTM_STATUS btm_ble_batchscan_enq_rep_q(UINT8 report_format, tBTM_BLE_REF_VALUE ref_value) -{ - int i = 0; - for (i = 0; i < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; i++) { - if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[i]) { - return BTM_ILLEGAL_VALUE; - } - } - - ble_batchscan_cb.main_rep_q.rep_mode[ble_batchscan_cb.main_rep_q.next_idx] = report_format; - ble_batchscan_cb.main_rep_q.ref_value[ble_batchscan_cb.main_rep_q.next_idx] = ref_value; - ble_batchscan_cb.main_rep_q.num_records[ble_batchscan_cb.main_rep_q.next_idx] = 0; - ble_batchscan_cb.main_rep_q.data_len[ble_batchscan_cb.main_rep_q.next_idx] = 0; - ble_batchscan_cb.main_rep_q.p_data[ble_batchscan_cb.main_rep_q.next_idx] = NULL; - BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_q: index:%d, rep %d, ref %d", - ble_batchscan_cb.main_rep_q.next_idx, report_format, ref_value); - - ble_batchscan_cb.main_rep_q.next_idx = (ble_batchscan_cb.main_rep_q.next_idx + 1) - % BTM_BLE_BATCH_REP_MAIN_Q_SIZE; - return BTM_SUCCESS; -} - -/******************************************************************************* -** -** Function btm_ble_batchscan_enq_rep_data -** -** Description setup the data in the main report queue -** -** Returns void -** -*******************************************************************************/ -void btm_ble_batchscan_enq_rep_data(UINT8 report_format, UINT8 num_records, UINT8 *p_data, - UINT8 data_len) -{ - int index = 0, len = 0; - UINT8 *p_orig_data = NULL, *p_app_data = NULL; - - for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) { - if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index]) { - break; - } - } - - BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_data: index:%d, rep %d, num %d len : %d", - index, report_format, num_records, data_len); - - if (index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE && data_len > 0 && num_records > 0) { - len = ble_batchscan_cb.main_rep_q.data_len[index]; - p_orig_data = ble_batchscan_cb.main_rep_q.p_data[index]; - if (NULL != p_orig_data) { - p_app_data = osi_malloc(len + data_len); - memcpy(p_app_data, p_orig_data, len); - memcpy(p_app_data + len, p_data, data_len); - osi_free(p_orig_data); - ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data; - ble_batchscan_cb.main_rep_q.num_records[index] += num_records; - ble_batchscan_cb.main_rep_q.data_len[index] += data_len; - } else { - p_app_data = osi_malloc(data_len); - memcpy(p_app_data, p_data, data_len); - ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data; - ble_batchscan_cb.main_rep_q.num_records[index] = num_records; - ble_batchscan_cb.main_rep_q.data_len[index] = data_len; - } - } -} - -/******************************************************************************* -** -** Function btm_ble_batchscan_deq_rep_q -** -** Description dequeue a batchscan report in q when command complete -** is received -** -** Returns void -** -*******************************************************************************/ -void btm_ble_batchscan_deq_rep_data(UINT8 report_format, tBTM_BLE_REF_VALUE *p_ref_value, - UINT8 *p_num_records, UINT8 **p_data, UINT16 *p_data_len) -{ - int index = 0; - - for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) { - if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index]) { - break; - } - } - - if (BTM_BLE_BATCH_REP_MAIN_Q_SIZE == index) { - BTM_TRACE_ERROR("btm_ble_batchscan_deq_rep_data: rep_format:%d not found", report_format); - return; - } - - *p_num_records = ble_batchscan_cb.main_rep_q.num_records[index]; - *p_ref_value = ble_batchscan_cb.main_rep_q.ref_value[index]; - *p_data = ble_batchscan_cb.main_rep_q.p_data[index]; - *p_data_len = ble_batchscan_cb.main_rep_q.data_len[index]; - - ble_batchscan_cb.main_rep_q.p_data[index] = NULL; - ble_batchscan_cb.main_rep_q.data_len[index] = 0; - ble_batchscan_cb.main_rep_q.rep_mode[index] = 0; - ble_batchscan_cb.main_rep_q.ref_value[index] = 0; - ble_batchscan_cb.main_rep_q.num_records[index] = 0; - - BTM_TRACE_DEBUG("btm_ble_batchscan_deq_rep_data: index:%d, rep %d, num %d, data_len %d", - index, report_format, *p_num_records, *p_data_len); - - ble_batchscan_cb.main_rep_q.pending_idx = (ble_batchscan_cb.main_rep_q.pending_idx + 1) - % BTM_BLE_BATCH_SCAN_MAX; -} - -/******************************************************************************* -** -** Function btm_ble_batchscan_deq_op_q -** -** Description dequeue a batch scan operation from q when command complete -** is received -** -** Returns void -** -*******************************************************************************/ -void btm_ble_batchscan_deq_op_q(UINT8 *p_opcode, tBTM_BLE_BATCH_SCAN_STATE *cur_state, - UINT8 *p_cb_evt, tBTM_BLE_REF_VALUE *p_ref) -{ - *p_cb_evt = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx] >> 4); - *p_opcode = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx] - & BTM_BLE_BATCH_SCAN_SUBCODE_MASK); - *p_ref = ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.pending_idx]; - *cur_state = (ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.pending_idx]); - ble_batchscan_cb.op_q.pending_idx = (ble_batchscan_cb.op_q.pending_idx + 1) - % BTM_BLE_BATCH_SCAN_MAX; -} - -/******************************************************************************* -** -** Function btm_ble_read_batchscan_reports -** -** Description This function reads the reports from controller -** -** Parameters scan_mode - The mode for which the reports are to be read out from the controller -** ref_value - Reference value -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_read_batchscan_reports(tBTM_BLE_BATCH_SCAN_MODE scan_mode, - tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - UINT8 param[BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN], *pp; - pp = param; - - memset(param, 0, BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN); - - UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_READ_RESULTS); - UINT8_TO_STREAM (pp, scan_mode); - - if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF, - BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN, param, btm_ble_batchscan_vsc_cmpl_cback)) - != BTM_CMD_STARTED) { - BTM_TRACE_ERROR("btm_ble_read_batchscan_reports %d", status); - return BTM_ILLEGAL_VALUE; - } - - if (BTM_CMD_STARTED == status) { - /* The user needs to be provided scan read reports event */ - btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_READ_RESULTS, ble_batchscan_cb.cur_state, - BTM_BLE_BATCH_SCAN_READ_REPTS_EVT, ref_value); - } - - return status; -} - -/******************************************************************************* -** -** Function btm_ble_batchscan_vsc_cmpl_cback -** -** Description Batch scan VSC complete callback -** -** Parameters p_params - VSC completed callback parameters -** -** Returns void -** -*******************************************************************************/ -void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params) -{ - UINT8 *p = p_params->p_param_buf; - UINT16 len = p_params->param_len; - tBTM_BLE_REF_VALUE ref_value = 0; - - UINT8 status = 0, subcode = 0, opcode = 0; - UINT8 report_format = 0, num_records = 0, cb_evt = 0; - UINT16 data_len = 0; - tBTM_BLE_BATCH_SCAN_STATE cur_state = 0; - tBTM_STATUS btm_status = 0; - UINT8 *p_data = NULL; - - if (len < 2) { - BTM_TRACE_ERROR("wrong length for btm_ble_batch_scan_vsc_cmpl_cback"); - btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value); - return; - } - - STREAM_TO_UINT8(status, p); - STREAM_TO_UINT8(subcode, p); - - btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value); - - BTM_TRACE_DEBUG("btm_ble_batchscan op_code = %02x state = %02x cb_evt = %02x,ref_value=%d", - opcode, cur_state, cb_evt, ref_value); - - if (opcode != subcode) { - BTM_TRACE_ERROR("Got unexpected VSC cmpl, expected: %d got: %d", subcode, opcode); - return; - } - - switch (subcode) { - case BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE: { - if (BTM_SUCCESS == status && BTM_BLE_SCAN_ENABLE_CALLED == cur_state) { - ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLED_STATE; - } else if (BTM_BLE_SCAN_ENABLE_CALLED == cur_state) { - BTM_TRACE_ERROR("SCAN_ENB_DISAB_CUST_FEATURE - Invalid state after enb"); - ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE; - } - - BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEAT status = %d, state: %d,evt=%d", - status, ble_batchscan_cb.cur_state, cb_evt); - - if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) { - ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status); - } - break; - } - - case BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM: { - BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM status = %d, evt=%d", - status, cb_evt); - if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) { - ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status); - } - break; - } - - case BTM_BLE_BATCH_SCAN_SET_PARAMS: { - BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_PARAMS status = %d,evt=%d", status, cb_evt); - - if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state) { - if (BTM_SUCCESS == status) { - ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE; - } else { - BTM_TRACE_ERROR("BTM_BLE_BATCH_SCAN_SET_PARAMS - Invalid state after disabled"); - ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE; - } - } - - if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) { - ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status); - } - break; - } - - case BTM_BLE_BATCH_SCAN_READ_RESULTS: { - if (cb_evt != 0 && NULL != ble_batchscan_cb.p_scan_rep_cback) { - STREAM_TO_UINT8(report_format, p); - STREAM_TO_UINT8(num_records, p); - p = (uint8_t *)(p_params->p_param_buf + 4); - BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_READ_RESULTS status=%d,len=%d,rec=%d", - status, len - 4, num_records); - - if (0 == num_records) { - btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records, - &p_data, &data_len); - if (NULL != ble_batchscan_cb.p_scan_rep_cback) { - ble_batchscan_cb.p_scan_rep_cback(ref_value, report_format, num_records, - data_len, p_data, status); - } - } else { - if ((len - 4) > 0) { - btm_ble_batchscan_enq_rep_data(report_format, num_records, p, len - 4); - /* More records could be in the buffer and needs to be pulled out */ - btm_status = btm_ble_read_batchscan_reports(report_format, ref_value); - if (BTM_CMD_STARTED != btm_status) { - btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records, - &p_data, &data_len); - /* Send whatever is available, in case of a command failure */ - if (NULL != ble_batchscan_cb.p_scan_rep_cback && NULL != p_data) { - ble_batchscan_cb.p_scan_rep_cback(ref_value, report_format, - num_records, data_len, p_data, status); - } - } - } - } - } - break; - } - - default: - break; - } - - return; -} - -/******************************************************************************* -** -** Function btm_ble_set_storage_config -** -** Description This function writes the storage configuration in controller -** -** Parameters batch_scan_full_max -Max storage space (in %) allocated to full scanning -** batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning -** batch_scan_notify_threshold - Setup notification level based on total space -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_set_storage_config(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max, - UINT8 batch_scan_notify_threshold) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - UINT8 param[BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN], *pp; - - pp = param; - memset(param, 0, BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN); - - UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM); - UINT8_TO_STREAM (pp, batch_scan_full_max); - UINT8_TO_STREAM (pp, batch_scan_trunc_max); - UINT8_TO_STREAM (pp, batch_scan_notify_threshold); - - if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF, - BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN, param, - btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) { - BTM_TRACE_ERROR("btm_ble_set_storage_config %d", status); - return BTM_ILLEGAL_VALUE; - } - - return status; -} - -/******************************************************************************* -** -** Function btm_ble_set_batchscan_param -** -** Description This function writes the batch scan params in controller -** -** Parameters scan_mode -Batch scan mode -** scan_interval - Scan interval -** scan_window - Scan window -** discard_rule -Discard rules -** addr_type - Address type -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode, - UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type, - tBTM_BLE_DISCARD_RULE discard_rule) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - UINT8 scan_param[BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN], *pp_scan; - - pp_scan = scan_param; - memset(scan_param, 0, BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN); - - // Override param and decide addr_type based on own addr type - // TODO: Remove upper layer parameter? - addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type; - - UINT8_TO_STREAM (pp_scan, BTM_BLE_BATCH_SCAN_SET_PARAMS); - UINT8_TO_STREAM (pp_scan, scan_mode); - UINT32_TO_STREAM (pp_scan, scan_window); - UINT32_TO_STREAM (pp_scan, scan_interval); - UINT8_TO_STREAM (pp_scan, addr_type); - UINT8_TO_STREAM (pp_scan, discard_rule); - - if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF, - BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN, - scan_param, btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) { - BTM_TRACE_ERROR("btm_ble_set_batchscan_param %d", status); - return BTM_ILLEGAL_VALUE; - } - - return status; -} - -/******************************************************************************* -** -** Function btm_ble_enable_disable_batchscan -** -** Description This function enables the customer specific feature in controller -** -** Parameters enable_disable: true - enable, false - disable -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN should_enable) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - UINT8 shld_enable = 0x01; - UINT8 enable_param[BTM_BLE_BATCH_SCAN_ENB_DISB_LEN], *pp_enable; - - if (!should_enable) { - shld_enable = 0x00; - } - - if (should_enable) { - pp_enable = enable_param; - memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN); - - UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE); - UINT8_TO_STREAM (pp_enable, shld_enable); - - if ((status = BTM_VendorSpecificCommand(HCI_BLE_BATCH_SCAN_OCF, - BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param, - btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) { - status = BTM_MODE_UNSUPPORTED; - BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status); - return BTM_ILLEGAL_VALUE; - } - } else if ((status = btm_ble_set_batchscan_param(BTM_BLE_BATCH_SCAN_MODE_DISABLE, - ble_batchscan_cb.scan_interval, ble_batchscan_cb.scan_window, - ble_batchscan_cb.addr_type, ble_batchscan_cb.discard_rule)) != BTM_CMD_STARTED) { - status = BTM_MODE_UNSUPPORTED; - BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status); - return BTM_ILLEGAL_VALUE; - } - - if (should_enable) { - ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED; - } else { - ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLE_CALLED; - } - return status; -} - -#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleSetStorageConfig -** -** Description This function is called to write storage config params. -** -** Parameters: batch_scan_full_max - Max storage space (in %) allocated to full style -** batch_scan_trunc_max - Max storage space (in %) allocated to trunc style -** batch_scan_notify_threshold - Setup notification level based on total space -** p_setup_cback - Setup callback pointer -** p_thres_cback - Threshold callback pointer -** p_rep_cback - Reports callback pointer -** ref_value - Reference value -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -tBTM_STATUS BTM_BleSetStorageConfig(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max, - UINT8 batch_scan_notify_threshold, - tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback, - tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback, - tBTM_BLE_SCAN_REP_CBACK *p_rep_cback, - tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_TRACE_EVENT (" BTM_BleSetStorageConfig: %d, %d, %d, %d, %d", - ble_batchscan_cb.cur_state, ref_value, batch_scan_full_max, batch_scan_trunc_max, - batch_scan_notify_threshold); - - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) { - BTM_TRACE_ERROR("Controller does not support batch scan"); - return BTM_ERR_PROCESSING; - } - - ble_batchscan_cb.p_setup_cback = p_setup_cback; - ble_batchscan_cb.p_thres_cback = p_thres_cback; - ble_batchscan_cb.p_scan_rep_cback = p_rep_cback; - ble_batchscan_cb.ref_value = ref_value; - - if (batch_scan_full_max > BTM_BLE_ADV_SCAN_FULL_MAX || - batch_scan_trunc_max > BTM_BLE_ADV_SCAN_TRUNC_MAX || - batch_scan_notify_threshold > BTM_BLE_ADV_SCAN_THR_MAX) { - BTM_TRACE_ERROR("Illegal set storage config params"); - return BTM_ILLEGAL_VALUE; - } - - if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state || - BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state || - BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) { - status = btm_ble_enable_disable_batchscan(TRUE); - if (BTM_CMD_STARTED != status) { - return status; - } - - ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED; - btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE, - BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value); - } - - status = btm_ble_set_storage_config(batch_scan_full_max, batch_scan_trunc_max, - batch_scan_notify_threshold); - if (BTM_CMD_STARTED != status) { - return status; - } - /* The user needs to be provided scan config storage event */ - btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM, ble_batchscan_cb.cur_state, - BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, ref_value); - - return status; -} -#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) - -/******************************************************************************* -** -** Function BTM_BleEnableBatchScan -** -** Description This function is called to configure and enable batch scanning -** -** Parameters: scan_mode -Batch scan mode -** scan_interval - Scan interval value -** scan_window - Scan window value -** discard_rule - Data discard rule -** ref_value - Reference value -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode, - UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type, - tBTM_BLE_DISCARD_RULE discard_rule, tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - BTM_TRACE_EVENT (" BTM_BleEnableBatchScan: %d, %d, %d, %d, %d, %d", - scan_mode, scan_interval, scan_window, addr_type, discard_rule, ref_value); - - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) { - BTM_TRACE_ERROR("Controller does not support batch scan"); - return BTM_ERR_PROCESSING; - } - - BTM_TRACE_DEBUG("BTM_BleEnableBatchScan: %d, %x, %x, %d, %d", scan_mode, scan_interval, - scan_window, discard_rule, ble_batchscan_cb.cur_state); - - /* Only 16 bits will be used for scan interval and scan window as per agreement with Google */ - /* So the standard LE range would suffice for scan interval and scan window */ - if ((BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) || - BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX)) - && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode - || BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI == scan_mode) - && (BTM_BLE_DISCARD_OLD_ITEMS == discard_rule || - BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule)) { - if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state || - BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state || - BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) { - status = btm_ble_enable_disable_batchscan(TRUE); - if (BTM_CMD_STARTED != status) { - return status; - } - btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE, - BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value); - } - - ble_batchscan_cb.scan_mode = scan_mode; - ble_batchscan_cb.scan_interval = scan_interval; - ble_batchscan_cb.scan_window = scan_window; - ble_batchscan_cb.addr_type = addr_type; - ble_batchscan_cb.discard_rule = discard_rule; - /* This command starts batch scanning, if enabled */ - status = btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type, - discard_rule); - if (BTM_CMD_STARTED != status) { - return status; - } - - /* The user needs to be provided scan enable event */ - btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, ble_batchscan_cb.cur_state, - BTM_BLE_BATCH_SCAN_ENABLE_EVT, ref_value); - } else { - BTM_TRACE_ERROR("Illegal enable scan params"); - return BTM_ILLEGAL_VALUE; - } - return status; -} - -/******************************************************************************* -** -** Function BTM_BleDisableBatchScan -** -** Description This function is called to disable batch scanning -** -** Parameters: ref_value - Reference value -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - BTM_TRACE_EVENT (" BTM_BleDisableBatchScan"); - - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) { - BTM_TRACE_ERROR("Controller does not support batch scan"); - return BTM_ERR_PROCESSING; - } - - status = btm_ble_enable_disable_batchscan(FALSE); - if (BTM_CMD_STARTED == status) { - /* The user needs to be provided scan disable event */ - btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, - BTM_BLE_SCAN_DISABLE_CALLED, BTM_BLE_BATCH_SCAN_DISABLE_EVT, - ref_value); - } - - return status; -} - -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleReadScanReports -** -** Description This function is called to start reading batch scan reports -** -** Parameters: scan_mode - Batch scan mode -** ref_value - Reference value -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -tBTM_STATUS BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode, - tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - UINT8 read_scan_mode = 0; - UINT8 *p_data = NULL, num_records = 0; - UINT16 data_len = 0; - - BTM_TRACE_EVENT (" BTM_BleReadScanReports; %d, %d", scan_mode, ref_value); - - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) { - BTM_TRACE_ERROR("Controller does not support batch scan"); - return BTM_ERR_PROCESSING; - } - - /* Check if the requested scan mode has already been setup by the user */ - read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_ACTI; - if (0 == read_scan_mode) { - read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_PASS; - } - - /* Check only for modes, as scan reports can be called after disabling batch scan */ - if (read_scan_mode > 0 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || - BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode)) { - status = btm_ble_batchscan_enq_rep_q(scan_mode, ref_value); - if (BTM_SUCCESS == status) { - status = btm_ble_read_batchscan_reports(scan_mode, ref_value); - if (BTM_CMD_STARTED != status) { - btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value, - &num_records, &p_data, &data_len); - } - } - } else { - BTM_TRACE_ERROR("Illegal read scan params: %d, %d, %d", read_scan_mode, scan_mode, - ble_batchscan_cb.cur_state); - return BTM_ILLEGAL_VALUE; - } - return status; -} -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleTrackAdvertiser -** -** Description This function is called to setup the callback for tracking advertisers -** -** Parameters: p_track_cback - Tracking callback pointer -** ref_value - Reference value -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback, - tBTM_BLE_REF_VALUE ref_value) -{ - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - BTM_TRACE_EVENT (" BTM_BleTrackAdvertiser"); - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) { - BTM_TRACE_ERROR("Controller does not support scan storage"); - return BTM_ERR_PROCESSING; - } - - ble_advtrack_cb.p_track_cback = p_track_cback; - ble_advtrack_cb.ref_value = ref_value; - return BTM_CMD_STARTED; -} -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -/******************************************************************************* -** -** Function btm_ble_batchscan_init -** -** Description This function initialize the batch scan control block. -** -** Parameters None -** -** Returns status -** -*******************************************************************************/ -void btm_ble_batchscan_init(void) -{ -#if BTM_DYNAMIC_MEMORY == TRUE - ble_batchscan_cb_ptr = (tBTM_BLE_BATCH_SCAN_CB *)osi_malloc(sizeof(tBTM_BLE_BATCH_SCAN_CB)); -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - ble_advtrack_cb_ptr = (tBTM_BLE_ADV_TRACK_CB *)osi_malloc(sizeof(tBTM_BLE_ADV_TRACK_CB)); -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - if (ble_batchscan_cb_ptr == NULL || ble_advtrack_cb_ptr == NULL) { - BTM_TRACE_ERROR("%s malloc failed", __func__); - return; - } -#endif - BTM_TRACE_EVENT (" btm_ble_batchscan_init"); - memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB)); -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB)); -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, TRUE); -} - -/******************************************************************************* -** -** Function btm_ble_batchscan_cleanup -** -** Description This function cleans the batch scan control block. -** -** Parameters None -** -** Returns void -** -*******************************************************************************/ -void btm_ble_batchscan_cleanup(void) -{ - int index = 0; - BTM_TRACE_EVENT (" btm_ble_batchscan_cleanup"); - - for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) { - if (NULL != ble_batchscan_cb.main_rep_q.p_data[index]) { - osi_free(ble_batchscan_cb.main_rep_q.p_data[index]); - ble_batchscan_cb.main_rep_q.p_data[index] = NULL; - } - } - - memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB)); -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB)); -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -#if BTM_DYNAMIC_MEMORY == TRUE - osi_free(ble_batchscan_cb_ptr); - ble_batchscan_cb_ptr = NULL; -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - osi_free(ble_advtrack_cb_ptr); - ble_advtrack_cb_ptr = NULL; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -#endif -} - -#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) #endif diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c b/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c index bf9b1adbff..452d3b3a1a 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c @@ -39,10 +39,11 @@ #endif #if (BLE_INCLUDED == TRUE) - static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state); static void btm_wl_update_to_controller(void); +#if (BLE_GATT_BGCONN == TRUE) + // Unfortunately (for now?) we have to maintain a copy of the device whitelist // on the host to determine if a device is pending to be connected or not. This // controls whether the host should keep trying to scan for whitelisted @@ -118,6 +119,7 @@ static bool background_connections_pending(void) } return pending_connections; } +#endif // (BLE_GATT_BGCONN == TRUE) /******************************************************************************* ** @@ -137,16 +139,11 @@ void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy) p_inq->sfp = scan_policy; p_inq->scan_type = p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE ? BTM_BLE_SCAN_MODE_ACTI : p_inq->scan_type; - if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0) { - btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval, - (UINT16)scan_window, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, - scan_policy); - } else { - btm_ble_send_extended_scan_params(p_inq->scan_type, scan_interval, scan_window, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, - scan_policy); - } + + btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval, + (UINT16)scan_window, + btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, + scan_policy); } /******************************************************************************* ** @@ -340,6 +337,7 @@ BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_ return FALSE; } +#if (BLE_GATT_BGCONN == TRUE) if (to_add) { /* added the bd_addr to the connection hash map queue */ if(!background_connection_add((bt_bdaddr_t *)bd_addr)) { @@ -359,6 +357,7 @@ BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_ return TRUE; } } +#endif // (BLE_GATT_BGCONN == TRUE) if (update_wl_cb){ //save add whitelist complete callback @@ -386,7 +385,10 @@ void btm_ble_clear_white_list (tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb) BTM_TRACE_EVENT ("btm_ble_clear_white_list"); btsnd_hcic_ble_clear_white_list(); + +#if (BLE_GATT_BGCONN == TRUE) background_connections_clear(); +#endif // (BLE_GATT_BGCONN == TRUE) if (update_wl_cb) { p_cb->update_wl_cb = update_wl_cb; @@ -462,7 +464,15 @@ void btm_ble_add_2_white_list_complete(UINT8 status) BTM_TRACE_EVENT("%s status=%d", __func__, status); tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; if (status == HCI_SUCCESS) { - --btm_cb.ble_ctr_cb.white_list_avail_size; + // --btm_cb.ble_ctr_cb.white_list_avail_size; + /* + According to the latest Bluetooth spec: + If the device is already in the Filter Accept List, the Controller should not add the device + to the Filter Accept List again and should return success. + The host cannot obtain the controller as the actual remaining white list size unless the host + also maintains a white list + Keep consistent behavior with the NimBLE host stack + */ } // add whitelist complete callback if (p_cb->update_wl_cb) @@ -485,7 +495,7 @@ void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len) UNUSED(evt_len); BTM_TRACE_EVENT ("%s status=%d", __func__, *p); if (*p == HCI_SUCCESS) { - ++btm_cb.ble_ctr_cb.white_list_avail_size; + // ++btm_cb.ble_ctr_cb.white_list_avail_size; } if (p_cb->update_wl_cb) { @@ -493,6 +503,7 @@ void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len) } } +#if (BLE_GATT_BGCONN == TRUE) /******************************************************************************* ** ** Function btm_ble_start_auto_conn @@ -516,7 +527,10 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start) if (start) { if (p_cb->conn_state == BLE_CONN_IDLE && background_connections_pending() - && btm_ble_topology_check(BTM_BLE_STATE_INIT)) { +#if (BLE_TOPOLOGY_CHECK == TRUE) + && btm_ble_topology_check(BTM_BLE_STATE_INIT) +#endif // (BLE_TOPOLOGY_CHECK == TRUE) + ) { p_cb->wl_state |= BTM_BLE_WL_INIT; btm_execute_wl_dev_operation(); @@ -604,29 +618,21 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start, tBTM_BLE_SEL_CBACK *p_select_cb btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS; /* Process advertising packets only from devices in the white list */ - if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0) { - /* use passive scan by default */ - if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS, - scan_int, - scan_win, - p_cb->addr_mgnt_cb.own_addr_type, - SP_ADV_WL)) { - return FALSE; - } - } else { - if (!btm_ble_send_extended_scan_params(BTM_BLE_SCAN_MODE_PASS, - scan_int, - scan_win, - p_cb->addr_mgnt_cb.own_addr_type, - SP_ADV_WL)) { - return FALSE; - } + /* use passive scan by default */ + if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS, + scan_int, + scan_win, + p_cb->addr_mgnt_cb.own_addr_type, + SP_ADV_WL)) { + return FALSE; } - +#if (BLE_TOPOLOGY_CHECK == TRUE) if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN)) { BTM_TRACE_ERROR("peripheral device cannot initiate passive scan for a selective connection"); return FALSE; - } else if (background_connections_pending()) { + } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) + if (background_connections_pending()) { #if BLE_PRIVACY_SPT == TRUE btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN); #endif @@ -671,11 +677,13 @@ void btm_ble_initiate_select_conn(BD_ADDR bda) BTM_TRACE_EVENT ("btm_ble_initiate_select_conn"); /* use direct connection procedure to initiate connection */ - if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda, BLE_ADDR_UNKNOWN_TYPE, FALSE)) { + if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda, BLE_ADDR_UNKNOWN_TYPE, FALSE, FALSE, 0xFF, 0xFF)) { BTM_TRACE_ERROR("btm_ble_initiate_select_conn failed"); } } -#if (tGATT_BG_CONN_DEV == TRUE) +#endif // (BLE_GATT_BGCONN == TRUE) + +#if (GATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** ** Function btm_ble_suspend_bg_conn @@ -700,7 +708,7 @@ BOOLEAN btm_ble_suspend_bg_conn(void) return FALSE; } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** @@ -713,12 +721,15 @@ BOOLEAN btm_ble_suspend_bg_conn(void) *******************************************************************************/ static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state) { +#if (BLE_GATT_BGCONN == TRUE) if (wl_state & BTM_BLE_WL_INIT) { btm_ble_start_auto_conn(FALSE); } if (wl_state & BTM_BLE_WL_SCAN) { btm_ble_start_select_conn(FALSE, NULL); } +#endif // (BLE_GATT_BGCONN == TRUE) + #if (BLE_42_ADV_EN == TRUE) if (wl_state & BTM_BLE_WL_ADV) { btm_ble_stop_adv(); @@ -736,9 +747,9 @@ static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state) *******************************************************************************/ void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) { -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) btm_ble_resume_bg_conn(); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) if (wl_state & BTM_BLE_WL_ADV) { #if (BLE_42_ADV_EN == TRUE) btm_ble_start_adv(); @@ -765,7 +776,7 @@ static void btm_wl_update_to_controller(void) btm_execute_wl_dev_operation(); } -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** ** Function btm_ble_resume_bg_conn @@ -795,7 +806,7 @@ BOOLEAN btm_ble_resume_bg_conn(void) return ret; } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** @@ -821,13 +832,16 @@ tBTM_BLE_CONN_ST btm_ble_get_conn_st(void) *******************************************************************************/ void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st) { + BTM_TRACE_DEBUG("%s old=%u new=%u", __func__, btm_cb.ble_ctr_cb.conn_state, new_st); btm_cb.ble_ctr_cb.conn_state = new_st; +#if (BLE_TOPOLOGY_CHECK == TRUE) if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN) { btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT); } else { btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT); } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) } /******************************************************************************* diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c b/components/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c index 4b68fe807b..671662e8be 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c @@ -20,91 +20,5 @@ #include "common/bt_target.h" #if (BLE_INCLUDED == TRUE) -#if (BLE_HOST_ENERGY_INFO_EN == TRUE) -#include "stack/bt_types.h" -#include "stack/hcimsgs.h" -#include "stack/btu.h" -#include "btm_int.h" -//#include "bt_utils.h" -#include "stack/hcidefs.h" -#include "stack/btm_ble_api.h" - -tBTM_BLE_ENERGY_INFO_CB ble_energy_info_cb; - -/******************************************************************************* -** -** Function btm_ble_cont_energy_cmpl_cback -** -** Description Controller VSC complete callback -** -** Parameters -** -** Returns void -** -*******************************************************************************/ -void btm_ble_cont_energy_cmpl_cback (tBTM_VSC_CMPL *p_params) -{ - UINT8 *p = p_params->p_param_buf; - UINT16 len = p_params->param_len; - UINT8 status = 0; - UINT32 total_tx_time = 0, total_rx_time = 0, total_idle_time = 0, total_energy_used = 0; - - if (len < 17) { - BTM_TRACE_ERROR("wrong length for btm_ble_cont_energy_cmpl_cback"); - return; - } - - STREAM_TO_UINT8(status, p); - STREAM_TO_UINT32(total_tx_time, p); - STREAM_TO_UINT32(total_rx_time, p); - STREAM_TO_UINT32(total_idle_time, p); - STREAM_TO_UINT32(total_energy_used, p); - - BTM_TRACE_DEBUG("energy_info status=%d,tx_t=%u, rx_t=%u, ener_used=%u, idle_t=%u", - status, total_tx_time, total_rx_time, total_energy_used, total_idle_time); - - if (NULL != ble_energy_info_cb.p_ener_cback) { - ble_energy_info_cb.p_ener_cback(total_tx_time, total_rx_time, total_idle_time, - total_energy_used, status); - } - - return; -} - -/******************************************************************************* -** -** Function BTM_BleGetEnergyInfo -** -** Description This function obtains the energy info -** -** Parameters p_ener_cback - Callback pointer -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS BTM_BleGetEnergyInfo(tBTM_BLE_ENERGY_INFO_CBACK *p_ener_cback) -{ - tBTM_STATUS status = BTM_ILLEGAL_VALUE; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - BTM_TRACE_EVENT("BTM_BleGetEnergyInfo\n"); - - if (0 == cmn_ble_vsc_cb.energy_support) { - BTM_TRACE_ERROR("Controller does not support get energy info\n"); - return BTM_ERR_PROCESSING; - } - - ble_energy_info_cb.p_ener_cback = p_ener_cback; - if ((status = BTM_VendorSpecificCommand (HCI_BLE_ENERGY_INFO_OCF, 0, NULL, - btm_ble_cont_energy_cmpl_cback)) != BTM_CMD_STARTED) { - BTM_TRACE_ERROR("BTM_BleGetEnergyInfo status: %d", status); - return BTM_ILLEGAL_VALUE; - } - - return status; -} -#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) #endif diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_cte.c b/components/bt/host/bluedroid/stack/btm/btm_ble_cte.c index a79932de2f..2e9c06da45 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_cte.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_cte.c @@ -38,8 +38,6 @@ void BTM_CteBleCallbackTrigger(tBTM_BLE_5_GAP_EVENT event, tBTM_BLE_CTE_CB_PARAM #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) tBTM_STATUS BTM_BleSetCteTransParams(uint8_t adv_handle, uint8_t cte_len, uint8_t cte_type, uint8_t cte_count, uint8_t switching_pattern_len, uint8_t *antenna_ids) { - - tHCI_STATUS err = HCI_SUCCESS; tBTM_STATUS status = BTM_SUCCESS; tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c index e43185e72d..831dbf7c0a 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -59,16 +59,6 @@ #define BTM_BLE_GAP_ADV_RPT_BATCH_SIZE (10) -#if BTM_DYNAMIC_MEMORY == FALSE -static tBTM_BLE_VSC_CB cmn_ble_gap_vsc_cb; -#else -static tBTM_BLE_VSC_CB *cmn_ble_gap_vsc_cb_ptr; -#define cmn_ble_gap_vsc_cb (*cmn_ble_gap_vsc_cb_ptr) -#endif - -#if BLE_VND_INCLUDED == TRUE -static tBTM_BLE_CTRL_FEATURES_CBACK *p_ctrl_le_feature_rd_cmpl_cback = NULL; -#endif tBTM_CallbackFunc conn_callback_func; // BLE vendor HCI event callback @@ -79,7 +69,9 @@ static tBTM_BLE_VENDOR_HCI_EVT_CBACK *ble_vs_evt_callback = NULL; ** Local functions *******************************************************************************/ static void btm_ble_update_adv_flag(UINT8 flag); +#if (BLE_42_SCAN_EN == TRUE) static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p); +#endif // (BLE_42_SCAN_EN == TRUE) UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data); @@ -88,7 +80,6 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb, BD_ADDR_PTR p_peer_addr_ptr, tBLE_ADDR_TYPE *p_peer_addr_type, tBLE_ADDR_TYPE *p_own_addr_type); -static void btm_ble_stop_observe(void); static void btm_ble_stop_discover(void); #if (BLE_42_SCAN_EN == TRUE) static void btm_adv_pkt_handler(void *arg); @@ -112,6 +103,7 @@ bool btm_ble_inter_get(void) return is_ble50_inter; } +#if (BLE_TOPOLOGY_CHECK == TRUE) /* LE states combo bit to check */ const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] = { {/* single state support */ @@ -253,6 +245,7 @@ const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] = { }; /* check LE combo state supported */ #define BTM_LE_STATES_SUPPORTED(x, y, z) ((x)[(z)] & (y)) +#endif // (BLE_TOPOLOGY_CHECK == TRUE) #if (BLE_42_ADV_EN == TRUE) static osi_mutex_t adv_enable_lock; @@ -390,192 +383,6 @@ void BTM_BleClearWhitelist(tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb) btm_ble_clear_white_list(update_wl_cb); } -/******************************************************************************* -** -** Function BTM_BleUpdateAdvFilterPolicy -** -** Description This function update the filter policy of advertiser. -** -** Parameter adv_policy: advertising filter policy -** -** Return void -*******************************************************************************/ -void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy) -{ - tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; - tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC; - BD_ADDR p_addr_ptr = {0}; - UINT8 adv_mode = p_cb->adv_mode; - - BTM_TRACE_EVENT ("BTM_BleUpdateAdvFilterPolicy\n"); - - if (!controller_get_interface()->supports_ble()) { - return; - } - - if (p_cb->afp != adv_policy) { - p_cb->afp = adv_policy; - -#if (BLE_42_ADV_EN == TRUE) - /* if adv active, stop and restart */ - btm_ble_stop_adv (); -#endif // #if (BLE_42_ADV_EN == TRUE) - - if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE) { - p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, - &p_cb->adv_addr_type); - } - - uint8_t null_addr[BD_ADDR_LEN] = {0}; - if ((p_cb->evt_type == 0x01 || p_cb->evt_type == 0x04) && memcmp(p_addr_ptr, null_addr, BD_ADDR_LEN) == 0) { - /* directed advertising */ - return; - } - - btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : - BTM_BLE_GAP_ADV_SLOW_INT), - (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : - BTM_BLE_GAP_ADV_SLOW_INT), - p_cb->evt_type, - p_cb->adv_addr_type, - init_addr_type, - p_addr_ptr, - p_cb->adv_chnl_map, - p_cb->afp); - - if (adv_mode == BTM_BLE_ADV_ENABLE) { -#if (BLE_42_ADV_EN == TRUE) - btm_ble_start_adv (); -#endif // #if (BLE_42_ADV_EN == TRUE) - } - - } -} - -/******************************************************************************* -** -** Function btm_ble_send_extended_scan_params -** -** Description This function sends out the extended scan parameters command to the controller -** -** Parameters scan_type - Scan type -** scan_int - Scan interval -** scan_win - Scan window -** addr_type_own - Own address type -** scan_filter_policy - Scan filter policy -** -** Returns TRUE or FALSE -** -*******************************************************************************/ -BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int, - UINT32 scan_win, UINT8 addr_type_own, - UINT8 scan_filter_policy) -{ - UINT8 scan_param[HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_PARAM]; - UINT8 *pp_scan = scan_param; - - memset(scan_param, 0, HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_PARAM); - - UINT8_TO_STREAM(pp_scan, scan_type); - UINT32_TO_STREAM(pp_scan, scan_int); - UINT32_TO_STREAM(pp_scan, scan_win); - UINT8_TO_STREAM(pp_scan, addr_type_own); - UINT8_TO_STREAM(pp_scan, scan_filter_policy); - - BTM_TRACE_DEBUG("%s, %d, %d", __func__, scan_int, scan_win); - if ((BTM_VendorSpecificCommand(HCI_BLE_EXTENDED_SCAN_PARAMS_OCF, - HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_PARAM, scan_param, NULL)) != BTM_SUCCESS) { - BTM_TRACE_ERROR("%s error sending extended scan parameters", __func__); - return FALSE; - } - return TRUE; -} - -/******************************************************************************* -** -** Function BTM_BleObserve -** -** Description This procedure keep the device listening for advertising -** events from a broadcast device. -** -** Parameters start: start or stop observe. -** white_list: use white list in observer mode or not. -** -** Returns void -** -*******************************************************************************/ -tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration, - tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb) -{ - tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; - tBTM_STATUS status = BTM_WRONG_MODE; - - UINT32 scan_interval = !p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval; - UINT32 scan_window = !p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window; - - BTM_TRACE_EVENT ("%s : scan_type:%d, %d, %d\n", __func__, btm_cb.btm_inq_vars.scan_type, - p_inq->scan_interval, p_inq->scan_window); - - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - - if (start) { - /* shared inquiry database, do not allow observe if any inquiry is active */ - if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) { - BTM_TRACE_ERROR("%s Observe Already Active", __func__); - return status; - } - - btm_cb.ble_ctr_cb.p_obs_results_cb = p_results_cb; - btm_cb.ble_ctr_cb.p_obs_cmpl_cb = p_cmpl_cb; - status = BTM_CMD_STARTED; - - /* scan is not started */ - if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) { - /* allow config of scan type */ - p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? - BTM_BLE_SCAN_MODE_ACTI : p_inq->scan_type; - /* assume observe always not using white list */ -#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) - /* enable resolving list */ - //btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN); -#endif - - if (cmn_ble_gap_vsc_cb.extended_scan_support == 0) { - btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval, - (UINT16)scan_window, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, - BTM_BLE_DEFAULT_SFP); - } else { - btm_ble_send_extended_scan_params(p_inq->scan_type, scan_interval, scan_window, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, - BTM_BLE_DEFAULT_SFP); - } -#if (BLE_42_SCAN_EN == TRUE) - status = btm_ble_start_scan(); -#endif // #if (BLE_42_SCAN_EN == TRUE) - } - - if (status == BTM_CMD_STARTED) { - btm_cb.ble_ctr_cb.scan_activity |= BTM_LE_OBSERVE_ACTIVE; - if (duration != 0) - /* start observer timer */ - { - btu_start_timer (&btm_cb.ble_ctr_cb.obs_timer_ent, BTU_TTYPE_BLE_OBSERVE, duration); - } - } - } else if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) { - status = BTM_CMD_STARTED; - btm_ble_stop_observe(); - } else { - BTM_TRACE_ERROR("%s Observe not active\n", __func__); - } - - return status; - -} - #if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** @@ -609,7 +416,9 @@ tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration, btm_cb.ble_ctr_cb.p_scan_results_cb = p_results_cb; btm_cb.ble_ctr_cb.p_scan_cmpl_cb = p_cmpl_cb; +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) btm_cb.ble_ctr_cb.p_obs_discard_cb = p_discard_cb; +#endif // (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) status = BTM_CMD_STARTED; /* scan is not started */ @@ -671,9 +480,9 @@ tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration, tBTM_STATUS BTM_BleBroadcast(BOOLEAN start, tBTM_START_STOP_ADV_CMPL_CBACK *p_stop_adv_cback) { tBTM_STATUS status = BTM_NO_RESOURCES; - tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; + // tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; - UINT8 evt_type = p_cb->scan_rsp ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT; + //UINT8 evt_type = p_cb->scan_rsp ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT; if (!controller_get_interface()->supports_ble()) { return BTM_ILLEGAL_VALUE; @@ -686,6 +495,8 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start, tBTM_START_STOP_ADV_CMPL_CBACK *p_s #endif if (start) { +// "start" should not be true +#if (0) /* update adv params */ if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT), @@ -705,6 +516,7 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start, tBTM_START_STOP_ADV_CMPL_CBACK *p_s } status = btm_ble_start_adv (); +#endif // } else { //save the stop adv callback to the BTM env. p_cb->p_stop_adv_cb = p_stop_adv_cback; @@ -716,138 +528,8 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start, tBTM_START_STOP_ADV_CMPL_CBACK *p_s return status; } #endif // #if (BLE_42_ADV_EN == TRUE) -#if BLE_VND_INCLUDED == TRUE -/******************************************************************************* -** -** Function btm_vsc_brcm_features_complete -** -** Description Command Complete callback for HCI_BLE_VENDOR_CAP_OCF -** -** Returns void -** -*******************************************************************************/ -static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_params) -{ - UINT8 status = 0xFF; - UINT8 *p; - - BTM_TRACE_DEBUG("%s", __func__); - - /* Check status of command complete event */ - if ((p_vcs_cplt_params->opcode == HCI_BLE_VENDOR_CAP_OCF) && - (p_vcs_cplt_params->param_len > 0)) { - p = p_vcs_cplt_params->p_param_buf; - STREAM_TO_UINT8(status, p); - } - - if (status == HCI_SUCCESS) { - STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p); - STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p); - STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p); - STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, p); - STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.filter_support, p); - STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.max_filter, p); - STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.energy_support, p); - - if (p_vcs_cplt_params->param_len > BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE) { - STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.version_supported, p); - } else { - btm_cb.cmn_ble_vsc_cb.version_supported = BTM_VSC_CHIP_CAPABILITY_L_VERSION; - } - - if (btm_cb.cmn_ble_vsc_cb.version_supported >= BTM_VSC_CHIP_CAPABILITY_M_VERSION) { - STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p); - STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p); - STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p); - } - btm_cb.cmn_ble_vsc_cb.values_read = TRUE; - } - - BTM_TRACE_DEBUG("%s: stat=%d, irk=%d, ADV ins:%d, rpa=%d, ener=%d, ext_scan=%d", - __func__, status, btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, - btm_cb.cmn_ble_vsc_cb.adv_inst_max, btm_cb.cmn_ble_vsc_cb.rpa_offloading, - btm_cb.cmn_ble_vsc_cb.energy_support, btm_cb.cmn_ble_vsc_cb.extended_scan_support); -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - if (BTM_BleMaxMultiAdvInstanceCount() > 0) { - btm_ble_multi_adv_init(); - } -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - if (btm_cb.cmn_ble_vsc_cb.max_filter > 0) { - btm_ble_adv_filter_init(); - } - -#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) - /* VS capability included and non-4.2 device */ - if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz > 0 && - controller_get_interface()->get_ble_resolving_list_max_size() == 0) { - btm_ble_resolving_list_init(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz); - } -#endif - - if (btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg > 0) { - btm_ble_batchscan_init(); - } - - if (p_ctrl_le_feature_rd_cmpl_cback != NULL) { - p_ctrl_le_feature_rd_cmpl_cback(status); - } -} -#endif - -/******************************************************************************* -** -** Function BTM_BleGetVendorCapabilities -** -** Description This function reads local LE features -** -** Parameters p_cmn_vsc_cb : Locala LE capability structure -** -** Returns void -** -*******************************************************************************/ -extern void BTM_BleGetVendorCapabilities(tBTM_BLE_VSC_CB *p_cmn_vsc_cb) -{ - BTM_TRACE_DEBUG("BTM_BleGetVendorCapabilities"); - - if (NULL != p_cmn_vsc_cb) { - *p_cmn_vsc_cb = btm_cb.cmn_ble_vsc_cb; - } -} - -/****************************************************************************** -** -** Function BTM_BleReadControllerFeatures -** -** Description Reads BLE specific controller features -** -** Parameters: tBTM_BLE_CTRL_FEATURES_CBACK : Callback to notify when features are read -** -** Returns void -** -*******************************************************************************/ -extern void BTM_BleReadControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK *p_vsc_cback) -{ - if (TRUE == btm_cb.cmn_ble_vsc_cb.values_read) { - return; - } - -#if BLE_VND_INCLUDED == TRUE - BTM_TRACE_DEBUG("BTM_BleReadControllerFeatures"); - - p_ctrl_le_feature_rd_cmpl_cback = p_vsc_cback; - if ( BTM_VendorSpecificCommand (HCI_BLE_VENDOR_CAP_OCF, - 0, - NULL, - btm_ble_vendor_capability_vsc_cmpl_cback) - != BTM_CMD_STARTED) { - BTM_TRACE_ERROR("LE Get_Vendor Capabilities Command Failed."); - } -#else - UNUSED(p_vsc_cback); -#endif - return ; -} +#if (BLE_VENDOR_HCI_EN == TRUE) void BTM_VendorHciEchoCmdCallback(tBTM_VSC_CMPL *p1) { #if (!CONFIG_BT_STACK_NO_LOG) @@ -880,6 +562,7 @@ void BTM_VendorHciEchoCmdTest(uint8_t echo) &echo, BTM_VendorHciEchoCmdCallback); } +#endif // (BLE_VENDOR_HCI_EN == TRUE) /******************************************************************************* ** @@ -949,12 +632,6 @@ BOOLEAN BTM_BleConfigPrivacy(BOOLEAN privacy_mode, tBTM_SET_LOCAL_PRIVACY_CBACK btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low); #endif -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - if (BTM_BleMaxMultiAdvInstanceCount() > 0) { - btm_ble_multi_adv_enb_privacy(privacy_mode); - } -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - /* 4.2 controller only allow privacy 1.2 or mixed mode, resolvable private address in controller */ if (controller_get_interface()->supports_ble_privacy()) { #if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE && GATTS_INCLUDED == TRUE) @@ -1164,6 +841,39 @@ void BTM_BleConfigLocalIcon(uint16_t icon) #endif } +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +/******************************************************************************* +** +** Function BTM_BleSetKeyMaterial +** +** Description Set the Encrypted Data Key Material in GAP service +** +** Parameters session_key: 16-byte session key (must not be NULL) +** iv: 8-byte initialization vector (must not be NULL) +** +** Returns void +** +*******************************************************************************/ +void BTM_BleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv) +{ +#if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE && GATTS_INCLUDED == TRUE) + tGAP_BLE_ATTR_VALUE p_value; + + if (session_key == NULL || iv == NULL) { + BTM_TRACE_ERROR("%s: NULL pointer parameter", __func__); + return; + } + + memset(&p_value, 0, sizeof(tGAP_BLE_ATTR_VALUE)); + memcpy(p_value.key_material.session_key, session_key, GAP_KEY_MATERIAL_SESSION_KEY_SIZE); + memcpy(p_value.key_material.iv, iv, GAP_KEY_MATERIAL_IV_SIZE); + GAP_BleAttrDBUpdate(GATT_UUID_GAP_KEY_MATERIAL, &p_value); +#else + BTM_TRACE_ERROR("%s\n", __func__); +#endif +} +#endif + /******************************************************************************* ** ** Function BTM_BleConfigConnParams @@ -1191,24 +901,8 @@ void BTM_BleConfigConnParams(uint16_t int_min, uint16_t int_max, uint16_t latenc #endif } -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleMaxMultiAdvInstanceCount -** -** Description Returns max number of multi adv instances supported by controller -** -** Returns Max multi adv instance count -** -*******************************************************************************/ -extern UINT8 BTM_BleMaxMultiAdvInstanceCount(void) -{ - return btm_cb.cmn_ble_vsc_cb.adv_inst_max < BTM_BLE_MULTI_ADV_MAX ? - btm_cb.cmn_ble_vsc_cb.adv_inst_max : BTM_BLE_MULTI_ADV_MAX; -} -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - #if BLE_PRIVACY_SPT == TRUE +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** ** Function btm_ble_resolve_random_addr_on_adv @@ -1249,6 +943,7 @@ static void btm_ble_resolve_random_addr_on_adv(void *p_rec, void *p) return; } +#endif // #if (BLE_42_SCAN_EN == TRUE) #endif /******************************************************************************* @@ -1269,6 +964,7 @@ BOOLEAN BTM_BleLocalPrivacyEnabled(void) #endif } +#if (BLE_GATT_BGCONN == TRUE) /******************************************************************************* ** ** Function BTM_BleSetBgConnType @@ -1327,7 +1023,9 @@ BOOLEAN BTM_BleSetBgConnType(tBTM_BLE_CONN_TYPE bg_conn_type, } return started; } +#endif // (BLE_GATT_BGCONN == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** ** Function BTM_BleClearBgConnDev @@ -1345,10 +1043,9 @@ void BTM_BleClearBgConnDev(void) { btm_ble_start_auto_conn(FALSE); btm_ble_clear_white_list(NULL); -#if (tGATT_BG_CONN_DEV == TRUE) gatt_reset_bgdev_list(); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) } +#endif // #if (GATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** @@ -1530,6 +1227,7 @@ tBTM_STATUS BTM_BleSetAdvParamsAll(UINT16 adv_int_min, UINT16 adv_int_max, UINT8 btm_ble_stop_adv(); osi_mutex_lock(&adv_param_lock, OSI_MUTEX_MAX_TIMEOUT); +#if (BLE_TOPOLOGY_CHECK == TRUE) if(adv_type == BTM_BLE_CONNECT_DIR_EVT){ btm_ble_set_topology_mask(BTM_BLE_STATE_HI_DUTY_DIR_ADV_BIT); }else if(adv_type == BTM_BLE_CONNECT_LO_DUTY_DIR_EVT){ @@ -1537,7 +1235,7 @@ tBTM_STATUS BTM_BleSetAdvParamsAll(UINT16 adv_int_min, UINT16 adv_int_max, UINT8 }else if(adv_type == BTM_BLE_NON_CONNECT_EVT){ btm_ble_set_topology_mask(BTM_BLE_STATE_NON_CONN_ADV_BIT); } - +#endif // (BLE_TOPOLOGY_CHECK == TRUE) p_cb->adv_interval_min = adv_int_min; p_cb->adv_interval_max = adv_int_max; p_cb->adv_chnl_map = chnl_map; @@ -1587,99 +1285,6 @@ tBTM_STATUS BTM_BleStartAdv(void) return status; } #endif // #if (BLE_42_ADV_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleReadAdvParams -** -** Description This function is called to set advertising parameters. -** -** Parameters adv_int_min: minimum advertising interval -** adv_int_max: maximum advertising interval -** p_dir_bda: connectable direct initiator's LE device address -** chnl_map: advertising channel map. -** -** Returns void -** -*******************************************************************************/ -void BTM_BleReadAdvParams (UINT16 *adv_int_min, UINT16 *adv_int_max, - tBLE_BD_ADDR *p_dir_bda, tBTM_BLE_ADV_CHNL_MAP *p_chnl_map) -{ - tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; - - BTM_TRACE_EVENT ("BTM_BleReadAdvParams "); - if (!controller_get_interface()->supports_ble()) { - return ; - } - - *adv_int_min = p_cb->adv_interval_min; - *adv_int_max = p_cb->adv_interval_max; - *p_chnl_map = p_cb->adv_chnl_map; - - if (p_dir_bda != NULL) { - memcpy(p_dir_bda, &p_cb->direct_bda, sizeof(tBLE_BD_ADDR)); - } -} - -#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) -/******************************************************************************* -** -** Function BTM_BleSetScanParams -** -** Description This function is called to set scan parameters. -** -** Parameters client_if - Client IF -** scan_interval - Scan interval -** scan_window - Scan window -** scan_mode - Scan mode -** scan_setup_status_cback - Scan param setup status callback -** -** Returns void -** -*******************************************************************************/ -void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, - tBLE_SCAN_MODE scan_mode, - tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback) -{ - tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; - UINT32 max_scan_interval; - UINT32 max_scan_window; - - BTM_TRACE_EVENT ("%s\n", __func__); - if (!controller_get_interface()->supports_ble()) { - return; - } - - /* If not supporting extended scan support, use the older range for checking */ - if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0) { - max_scan_interval = BTM_BLE_SCAN_INT_MAX; - max_scan_window = BTM_BLE_SCAN_WIN_MAX; - } else { - /* If supporting extended scan support, use the new extended range for checking */ - max_scan_interval = BTM_BLE_EXT_SCAN_INT_MAX; - max_scan_window = BTM_BLE_EXT_SCAN_WIN_MAX; - } - - if (BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN, max_scan_interval) && - BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN, max_scan_window) && - (scan_mode == BTM_BLE_SCAN_MODE_ACTI || scan_mode == BTM_BLE_SCAN_MODE_PASS)) { - p_cb->scan_type = scan_mode; - p_cb->scan_interval = scan_interval; - p_cb->scan_window = scan_window; - - if (scan_setup_status_cback != NULL) { - scan_setup_status_cback(client_if, BTM_SUCCESS); - } - } else { - if (scan_setup_status_cback != NULL) { - scan_setup_status_cback(client_if, BTM_ILLEGAL_VALUE); - } - - BTM_TRACE_ERROR("Illegal params: scan_interval = %d scan_window = %d\n", - scan_interval, scan_window); - } - -} -#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) #if (BLE_42_SCAN_EN == TRUE) tBTM_STATUS BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, @@ -1698,15 +1303,10 @@ tBTM_STATUS BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, if (BTM_BleUpdateOwnType(&addr_type_own, NULL) != 0) { return BTM_ILLEGAL_VALUE; } - /* If not supporting extended scan support, use the older range for checking */ - if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0) { - max_scan_interval = BTM_BLE_SCAN_INT_MAX; - max_scan_window = BTM_BLE_SCAN_WIN_MAX; - } else { - /* If supporting extended scan support, use the new extended range for checking */ - max_scan_interval = BTM_BLE_EXT_SCAN_INT_MAX; - max_scan_window = BTM_BLE_EXT_SCAN_WIN_MAX; - } + + max_scan_interval = BTM_BLE_SCAN_INT_MAX; + max_scan_window = BTM_BLE_SCAN_WIN_MAX; + osi_mutex_lock(&scan_param_lock, OSI_MUTEX_MAX_TIMEOUT); @@ -1816,6 +1416,7 @@ tBTM_STATUS BTM_BleWriteScanRspRaw(UINT8 *p_raw_scan_rsp, UINT32 raw_scan_rsp_le } #endif // #if (BLE_42_ADV_EN == TRUE) +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) /******************************************************************************* ** ** Function BTM_UpdateBleDuplicateExceptionalList @@ -1880,6 +1481,7 @@ tBTM_STATUS BTM_UpdateBleDuplicateExceptionalList(uint8_t subcode, uint32_t type return status; } +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* @@ -2136,6 +1738,7 @@ void BTM_Recovery_Pre_State(void) { #if ((BLE_42_ADV_EN == TRUE) || (BLE_42_SCAN_EN == TRUE)) tBTM_BLE_INQ_CB *ble_inq_cb = &btm_cb.ble_ctr_cb.inq_var; + BTM_TRACE_DEBUG("%s state=0x%x", __func__, ble_inq_cb->state); #endif // #if ((BLE_42_ADV_EN == TRUE) || (BLE_42_SCAN_EN == TRUE)) #if (BLE_42_ADV_EN == TRUE) if (ble_inq_cb->state & BTM_BLE_ADVERTISING) { @@ -2752,82 +2355,6 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) return status; } - -/******************************************************************************* -** -** Function btm_ble_start_inquiry -** -** Description This function is called to start BLE inquiry procedure. -** If the duration is zero, the periodic inquiry mode is cancelled. -** -** Parameters: mode - GENERAL or LIMITED inquiry -** p_inq_params - pointer to the BLE inquiry parameter. -** p_results_cb - callback returning pointer to results (tBTM_INQ_RESULTS) -** p_cmpl_cb - callback indicating the end of an inquiry -** -** -** -** Returns BTM_CMD_STARTED if successfully started -** BTM_NO_RESOURCES if could not allocate a message buffer -** BTM_BUSY - if an inquiry is already active -** -*******************************************************************************/ -tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration) -{ - tBTM_STATUS status = BTM_CMD_STARTED; - tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb; - tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; - - BTM_TRACE_DEBUG("btm_ble_start_inquiry: mode = %02x inq_active = 0x%02x", mode, btm_cb.btm_inq_vars.inq_active); - - /* if selective connection is active, or inquiry is already active, reject it */ - if (BTM_BLE_IS_INQ_ACTIVE(p_ble_cb->scan_activity) || - BTM_BLE_IS_SEL_CONN_ACTIVE (p_ble_cb->scan_activity)) { - BTM_TRACE_ERROR("LE Inquiry is active, can not start inquiry"); - return (BTM_BUSY); - } - - if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { - btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI, - BTM_BLE_LOW_LATENCY_SCAN_INT, - BTM_BLE_LOW_LATENCY_SCAN_WIN, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, - SP_ADV_ALL); -#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) - /* enable IRK list */ - //btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN); -#endif -#if (BLE_42_SCAN_EN == TRUE) - status = btm_ble_start_scan(); -#endif // #if (BLE_42_SCAN_EN == TRUE) - } else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) || - (p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) { - BTM_TRACE_DEBUG("%s, restart LE scan with low latency scan params", __FUNCTION__); - btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); - btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_ACTI, - BTM_BLE_LOW_LATENCY_SCAN_INT, - BTM_BLE_LOW_LATENCY_SCAN_WIN, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, - SP_ADV_ALL); - btsnd_hcic_ble_set_scan_enable(BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE); - } - - if (status == BTM_CMD_STARTED) { - p_inq->inq_active |= mode; - p_ble_cb->scan_activity |= mode; - - BTM_TRACE_DEBUG("btm_ble_start_inquiry inq_active = 0x%02x", p_inq->inq_active); - - if (duration != 0) { - /* start inquiry timer */ - btu_start_timer (&p_ble_cb->inq_var.inq_timer_ent, BTU_TTYPE_BLE_INQUIRY, duration); - } - } - - return status; - -} - /******************************************************************************* ** ** Function btm_ble_read_remote_name_cmpl @@ -3471,6 +2998,7 @@ void btm_clear_all_pending_le_entry(void) } } +#if (BLE_GATT_BGCONN == TRUE) /******************************************************************************* ** ** Function btm_send_sel_conn_callback @@ -3514,6 +3042,7 @@ void btm_send_sel_conn_callback(BD_ADDR remote_bda, UINT8 evt_type, UINT8 *p_dat btm_ble_initiate_select_conn(remote_bda); } } +#endif // #if (BLE_GATT_BGCONN == TRUE) #if (BLE_42_SCAN_EN == TRUE) static void btm_adv_pkt_handler(void *arg) @@ -3558,7 +3087,6 @@ static void btm_adv_pkt_handler(void *arg) UNUSED(hci_evt_code); UNUSED(hci_evt_len); } -#endif // #if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** @@ -3653,9 +3181,6 @@ static void btm_ble_process_last_adv_pkt(void) { UINT8 result = 0; UINT8 null_bda[6] = {0}; - tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; - tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb; - tBTM_INQ_RESULTS_CB *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb; tBTM_INQ_RESULTS_CB *p_scan_results_cb = btm_cb.ble_ctr_cb.p_scan_results_cb; tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var; tINQ_DB_ENT *p_i = btm_inq_db_find (p_le_inq_cb->adv_addr); @@ -3674,24 +3199,13 @@ static void btm_ble_process_last_adv_pkt(void) __func__); return; } +#if (BLE_GATT_BGCONN == TRUE) /* background connection in selective connection mode */ if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE) { //do nothing - } else { - if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT)) { - (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); - p_le_inq_cb->adv_len = 0; - memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN); - p_i->inq_info.results.adv_data_len = 0; - p_i->inq_info.results.scan_rsp_len = 0; - } - if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT)) { - (p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); - p_le_inq_cb->adv_len = 0; - memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN); - p_i->inq_info.results.adv_data_len = 0; - p_i->inq_info.results.scan_rsp_len = 0; - } + } else +#endif // (BLE_GATT_BGCONN == TRUE) + { if (p_scan_results_cb && (result & BTM_BLE_DISCO_RESULT)) { (p_scan_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); p_le_inq_cb->adv_len = 0; @@ -3719,8 +3233,6 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt tINQ_DB_ENT *p_i; tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; - tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb; - tBTM_INQ_RESULTS_CB *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb; tBTM_INQ_RESULTS_CB *p_scan_results_cb = btm_cb.ble_ctr_cb.p_scan_results_cb; tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var; BOOLEAN update = TRUE; @@ -3797,19 +3309,11 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt /* assume a DUMO device, BR/EDR inquiry is always active */ ((p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE && p_i->scan_rsp)) { - BTM_TRACE_WARNING("INQ RES: Extra Response Received...cancelling inquiry.."); - - /* if is non-periodic inquiry active, cancel now */ - if ((p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK) != 0 && - (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) == 0) { - btsnd_hcic_inq_cancel(); - } - - btm_ble_stop_inquiry(); btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT); } } +#if (BLE_GATT_BGCONN == TRUE) /* background connection in selective connection mode */ if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE) { if (result & BTM_BLE_SEL_CONN_RESULT) { @@ -3817,21 +3321,9 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt } else { BTM_TRACE_DEBUG("None LE device, can not initiate selective connection\n"); } - } else { - if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT)) { - (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); - p_le_inq_cb->adv_len = 0; - memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN); - p_i->inq_info.results.adv_data_len = 0; - p_i->inq_info.results.scan_rsp_len = 0; - } - if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT)) { - (p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); - p_le_inq_cb->adv_len = 0; - memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN); - p_i->inq_info.results.adv_data_len = 0; - p_i->inq_info.results.scan_rsp_len = 0; - } + } else +#endif // (BLE_GATT_BGCONN == TRUE) + { if (p_scan_results_cb && (result & BTM_BLE_DISCO_RESULT)) { (p_scan_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); p_le_inq_cb->adv_len = 0; @@ -3861,7 +3353,7 @@ void btm_ble_process_direct_adv_pkt(UINT8 *p) // TODO } -#if (BLE_42_SCAN_EN == TRUE) + /******************************************************************************* ** ** Function btm_ble_start_scan @@ -3890,11 +3382,13 @@ tBTM_STATUS btm_ble_start_scan(void) status = BTM_NO_RESOURCES; } btm_cb.ble_ctr_cb.inq_var.state |= BTM_BLE_SCANNING; +#if (BLE_TOPOLOGY_CHECK == TRUE) if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) { btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); } else { btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) } osi_mutex_unlock(&scan_enable_lock); return status; @@ -3925,73 +3419,6 @@ void btm_ble_stop_scan(void) btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN; } -/******************************************************************************* -** -** Function btm_ble_stop_inquiry -** -** Description Stop the BLE Inquiry. -** -** Returns void -** -*******************************************************************************/ -void btm_ble_stop_inquiry(void) -{ - tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; - tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb; - - btu_stop_timer (&p_ble_cb->inq_var.inq_timer_ent); - - p_ble_cb->scan_activity &= ~BTM_BLE_INQUIRY_MASK; - - /* If no more scan activity, stop LE scan now */ - if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { - btm_ble_stop_scan(); - } else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) || - (p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) { - BTM_TRACE_DEBUG("%s: setting default params for ongoing observe", __FUNCTION__); -#if (BLE_42_SCAN_EN == TRUE) - btm_ble_stop_scan(); - btm_ble_start_scan(); -#endif // #if (BLE_42_SCAN_EN == TRUE) - } - - /* If we have a callback registered for inquiry complete, call it */ - BTM_TRACE_DEBUG ("BTM Inq Compl Callback: status 0x%02x, num results %d", - p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp); - - btm_process_inq_complete(HCI_SUCCESS, (UINT8)(p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK)); -} - -/******************************************************************************* -** -** Function btm_ble_stop_observe -** -** Description Stop the BLE Observe. -** -** Returns void -** -*******************************************************************************/ -static void btm_ble_stop_observe(void) -{ - tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb; - tBTM_CMPL_CB *p_obs_cb = p_ble_cb->p_obs_cmpl_cb; - - btu_stop_timer (&p_ble_cb->obs_timer_ent); - - p_ble_cb->scan_activity &= ~BTM_LE_OBSERVE_ACTIVE; - - p_ble_cb->p_obs_results_cb = NULL; - p_ble_cb->p_obs_cmpl_cb = NULL; - - if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { - btm_ble_stop_scan(); - } - - if (p_obs_cb) { - (p_obs_cb)((tBTM_INQUIRY_CMPL *) &btm_cb.btm_inq_vars.inq_cmpl_info); - } -} - /******************************************************************************* ** ** Function btm_ble_stop_observe @@ -4021,9 +3448,11 @@ static void btm_ble_stop_discover(void) if(btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE)) { osi_sem_take(&scan_enable_sem, OSI_SEM_MAX_TIMEOUT); } +#if (BLE_TOPOLOGY_CHECK == TRUE) /* reset status */ btm_ble_clear_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); btm_ble_clear_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); +#endif // (BLE_TOPOLOGY_CHECK == TRUE) } if (p_scan_cb) { @@ -4044,6 +3473,7 @@ static void btm_ble_stop_discover(void) *******************************************************************************/ typedef BOOLEAN (BTM_TOPOLOGY_FUNC_PTR)(tBTM_BLE_STATE_MASK); #if (BLE_42_ADV_EN == TRUE) +#if (BLE_TOPOLOGY_CHECK == TRUE) static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UINT8 adv_evt) { BOOLEAN rt = FALSE; @@ -4075,6 +3505,7 @@ static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UI return rt; } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) /******************************************************************************* ** @@ -4091,10 +3522,11 @@ tBTM_STATUS btm_ble_start_adv(void) tBTM_STATUS rt = BTM_NO_RESOURCES; BTM_TRACE_EVENT ("btm_ble_start_adv\n"); - +#if (BLE_TOPOLOGY_CHECK == TRUE) if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type)) { return BTM_WRONG_MODE; } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) osi_mutex_lock(&adv_enable_lock, OSI_MUTEX_MAX_TIMEOUT); @@ -4118,7 +3550,9 @@ tBTM_STATUS btm_ble_start_adv(void) UINT8 adv_mode = p_cb->adv_mode; p_cb->adv_mode = BTM_BLE_ADV_ENABLE; p_cb->state |= BTM_BLE_ADVERTISING; +#if (BLE_TOPOLOGY_CHECK == TRUE) btm_ble_adv_states_operation(btm_ble_set_topology_mask, p_cb->evt_type); +#endif // (BLE_TOPOLOGY_CHECK == TRUE) if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE)) { osi_sem_take(&adv_enable_sem, OSI_SEM_MAX_TIMEOUT); rt = adv_enable_status; @@ -4127,7 +3561,9 @@ tBTM_STATUS btm_ble_start_adv(void) p_cb->adv_mode = BTM_BLE_ADV_DISABLE; p_cb->state = temp_state; p_cb->adv_mode = adv_mode; +#if (BLE_TOPOLOGY_CHECK == TRUE) btm_ble_adv_states_operation(btm_ble_clear_topology_mask, p_cb->evt_type); +#endif // (BLE_TOPOLOGY_CHECK == TRUE) btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; } @@ -4157,16 +3593,18 @@ tBTM_STATUS btm_ble_stop_adv(void) BOOLEAN temp_fast_adv_on = p_cb->fast_adv_on; tBTM_BLE_GAP_STATE temp_state = p_cb->state; tBTM_BLE_WL_STATE temp_wl_state = btm_cb.ble_ctr_cb.wl_state; +#if (BLE_TOPOLOGY_CHECK == TRUE) tBTM_BLE_STATE_MASK temp_mask = btm_ble_get_topology_mask (); +#endif // (BLE_TOPOLOGY_CHECK == TRUE) p_cb->fast_adv_on = FALSE; p_cb->adv_mode = BTM_BLE_ADV_DISABLE; p_cb->state &= ~BTM_BLE_ADVERTISING; btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; - +#if (BLE_TOPOLOGY_CHECK == TRUE) /* clear all adv states */ btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK); - +#endif // (BLE_TOPOLOGY_CHECK == TRUE) if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) { osi_sem_take(&adv_enable_sem, OSI_SEM_MAX_TIMEOUT); rt = adv_enable_status; @@ -4176,8 +3614,9 @@ tBTM_STATUS btm_ble_stop_adv(void) p_cb->adv_mode = temp_adv_mode; p_cb->state = temp_state; btm_cb.ble_ctr_cb.wl_state = temp_wl_state; +#if (BLE_TOPOLOGY_CHECK == TRUE) btm_ble_set_topology_mask (temp_mask); - +#endif // (BLE_TOPOLOGY_CHECK == TRUE) rt = BTM_NO_RESOURCES; } if(adv_enable_status != HCI_SUCCESS) { @@ -4307,13 +3746,11 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle) switch (p_tle->event) { case BTU_TTYPE_BLE_OBSERVE: - btm_ble_stop_observe(); break; case BTU_TTYPE_BLE_SCAN: btm_ble_stop_discover(); break; case BTU_TTYPE_BLE_INQUIRY: - btm_ble_stop_inquiry(); break; case BTU_TTYPE_BLE_GAP_LIM_DISC: @@ -4329,12 +3766,6 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle) /* refresh the random addr */ btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low); #endif - } else { -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - if (BTM_BleMaxMultiAdvInstanceCount() > 0) { - btm_ble_multi_adv_configure_rpa((tBTM_BLE_MULTI_ADV_INST *)p_tle->param); - } -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) } } break; @@ -4443,6 +3874,7 @@ void btm_ble_dir_adv_tout(void) btm_cb.ble_ctr_cb.inq_var.directed_conn = FALSE; } +#if (BLE_TOPOLOGY_CHECK == TRUE) /******************************************************************************* ** ** Function btm_ble_set_topology_mask @@ -4524,6 +3956,7 @@ void btm_ble_update_link_topology_mask(UINT8 link_role, BOOLEAN increase) btm_ble_clear_topology_mask(BTM_BLE_STATE_ALL_ADV_MASK); } } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) /******************************************************************************* ** @@ -4542,8 +3975,10 @@ BOOLEAN btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 st btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE; /* make device fall back into undirected adv mode by default */ btm_cb.ble_ctr_cb.inq_var.directed_conn = BTM_BLE_CONNECT_EVT; +#if (BLE_TOPOLOGY_CHECK == TRUE) /* clear all adv states */ btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK); +#endif // (BLE_TOPOLOGY_CHECK == TRUE) } if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE) { @@ -4556,9 +3991,9 @@ BOOLEAN btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 st now in order */ if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES && !btm_send_pending_direct_conn()) { -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) bg_con = btm_ble_resume_bg_conn(); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) } return bg_con; @@ -4599,24 +4034,15 @@ void btm_ble_init (void) { BTM_TRACE_DEBUG("%s", __func__); -#if BTM_DYNAMIC_MEMORY == TRUE - cmn_ble_gap_vsc_cb_ptr = (tBTM_BLE_VSC_CB *)osi_malloc(sizeof(tBTM_BLE_VSC_CB)); - if (cmn_ble_gap_vsc_cb_ptr == NULL) { - BTM_TRACE_ERROR("%s malloc failed", __func__); - return; - } -#endif - tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; - - btu_free_timer(&p_cb->obs_timer_ent); +#if (BLE_42_SCAN_EN == TRUE) btu_free_timer(&p_cb->scan_timer_ent); +#endif // (BLE_42_SCAN_EN == TRUE) btu_free_timer(&p_cb->inq_var.fast_adv_timer); memset(p_cb, 0, sizeof(tBTM_BLE_CB)); - memset(&(btm_cb.cmn_ble_vsc_cb), 0 , sizeof(tBTM_BLE_VSC_CB)); - btm_cb.cmn_ble_vsc_cb.values_read = FALSE; +#if (BLE_TOPOLOGY_CHECK == TRUE) p_cb->cur_states = 0; - +#endif // (BLE_TOPOLOGY_CHECK == TRUE) p_cb->conn_pending_q = fixed_queue_new(QUEUE_SIZE_MAX); p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE; @@ -4639,11 +4065,7 @@ void btm_ble_init (void) assert(p_cb->adv_rpt_ready != NULL); osi_event_bind(p_cb->adv_rpt_ready, btu_get_current_thread(), 0); #endif // #if (BLE_42_SCAN_EN == TRUE) -#if BLE_VND_INCLUDED == FALSE -#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE - btm_ble_adv_filter_init(); -#endif // #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE -#endif + #if (BLE_VENDOR_HCI_EN == TRUE) BTM_RegisterForVSEvents(btm_ble_vs_evt_callback, TRUE); #endif // #if (BLE_VENDOR_HCI_EN == TRUE) @@ -4672,10 +4094,6 @@ void btm_ble_free (void) osi_event_delete(p_cb->adv_rpt_ready); p_cb->adv_rpt_ready = NULL; #endif // #if (BLE_42_SCAN_EN == TRUE) -#if BTM_DYNAMIC_MEMORY == TRUE - osi_free(cmn_ble_gap_vsc_cb_ptr); - cmn_ble_gap_vsc_cb_ptr = NULL; -#endif } static bool enable_topology_check_flag = true; @@ -4684,6 +4102,8 @@ void esp_qa_enable_topology_check(bool enable) // This is a workaround: If the topology check is disabled, the 'Supported States' will not be checked. enable_topology_check_flag = enable; } + +#if (BLE_TOPOLOGY_CHECK == TRUE) /******************************************************************************* ** ** Function btm_ble_topology_check @@ -4748,7 +4168,7 @@ BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request_state_mask) } return rt; } - +#endif // (BLE_TOPOLOGY_CHECK == TRUE) /******************************************************************************* ** ** Function BTM_Ble_Authorization diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_iso.c b/components/bt/host/bluedroid/stack/btm/btm_ble_iso.c index c66f10b9c0..f0aa7ca56c 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_iso.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_iso.c @@ -85,11 +85,20 @@ void btm_ble_iso_read_iso_link_quality_complete(UINT8 *p) void btm_ble_iso_set_cig_params_complete(UINT8 *p) { tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + UINT8 cis_count; STREAM_TO_UINT8(cb_params.btm_set_cig_params.status, p); STREAM_TO_UINT8(cb_params.btm_set_cig_params.cig_id, p); - STREAM_TO_UINT8(cb_params.btm_set_cig_params.cis_count, p); - for (uint8_t i = 0; i < cb_params.btm_set_cig_params.cis_count; i++) + STREAM_TO_UINT8(cis_count, p); + + // Validate cis_count to prevent buffer overflow + if (cis_count > BLE_ISO_CIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, cis_count %d exceeds BLE_ISO_CIS_MAX_COUNT %d", __func__, cis_count, BLE_ISO_CIS_MAX_COUNT); + cis_count = BLE_ISO_CIS_MAX_COUNT; + } + cb_params.btm_set_cig_params.cis_count = cis_count; + + for (uint8_t i = 0; i < cis_count; i++) { STREAM_TO_UINT16(cb_params.btm_set_cig_params.conn_hdl[i], p); BTM_TRACE_DEBUG("i = %d, conn_hdl = %d", i, cb_params.btm_set_cig_params.conn_hdl[i]); @@ -158,6 +167,8 @@ void btm_ble_big_create_cmpl_evt(tBTM_BLE_BIG_CREATE_CMPL *params) { BTM_TRACE_DEBUG("%s", __func__); tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + UINT8 num_bis; + if (!params) { BTM_TRACE_ERROR("%s, Invalid params.", __func__); return; @@ -167,6 +178,13 @@ void btm_ble_big_create_cmpl_evt(tBTM_BLE_BIG_CREATE_CMPL *params) params->status = (params->status | BTM_HCI_ERROR); } + // Validate num_bis to prevent buffer overflow + num_bis = params->num_bis; + if (num_bis > BLE_ISO_BIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); + num_bis = BLE_ISO_BIS_MAX_COUNT; + } + cb_params.btm_big_cmpl.status = params->status; cb_params.btm_big_cmpl.big_handle = params->big_handle; cb_params.btm_big_cmpl.big_sync_delay = params->big_sync_delay; @@ -178,14 +196,12 @@ void btm_ble_big_create_cmpl_evt(tBTM_BLE_BIG_CREATE_CMPL *params) cb_params.btm_big_cmpl.irc = params->irc; cb_params.btm_big_cmpl.max_pdu = params->max_pdu; cb_params.btm_big_cmpl.iso_interval = params->iso_interval; - cb_params.btm_big_cmpl.num_bis = params->num_bis; - // for (uint8_t i = 0; i < params->num_bis; i++) - // { - // cb_params.btm_big_cmpl.bis_handle[i] = params->bis_handle[i]; - // } - memcpy(&cb_params.btm_big_cmpl.bis_handle[0], ¶ms->bis_handle[0], params->num_bis * 2); + cb_params.btm_big_cmpl.num_bis = num_bis; - //memcpy(&cb_params.btm_big_cmpl, params, sizeof(tBTM_BLE_BIG_CREATE_CMPL)); + // Copy bis_handle array with bounds checking + if (num_bis > 0) { + memcpy(&cb_params.btm_big_cmpl.bis_handle[0], ¶ms->bis_handle[0], num_bis * sizeof(UINT16)); + } BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_CREATE_COMPLETE_EVT, &cb_params); } @@ -207,6 +223,8 @@ void btm_ble_big_terminate_cmpl_evt(tBTM_BLE_BIG_TERMINATE_CMPL *params) void btm_ble_big_sync_estab_evt(tBTM_BLE_BIG_SYNC_ESTAB_CMPL *params) { tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + UINT8 num_bis; + if (!params) { BTM_TRACE_ERROR("%s, Invalid params.", __func__); return; @@ -216,7 +234,28 @@ void btm_ble_big_sync_estab_evt(tBTM_BLE_BIG_SYNC_ESTAB_CMPL *params) params->status = (params->status | BTM_HCI_ERROR); } - memcpy(&cb_params.btm_big_sync_estab, params, sizeof(tBTM_BLE_BIG_SYNC_ESTAB_CMPL)); + // Validate num_bis to prevent buffer overflow + num_bis = params->num_bis; + if (num_bis > BLE_ISO_BIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); + num_bis = BLE_ISO_BIS_MAX_COUNT; + } + + cb_params.btm_big_sync_estab.status = params->status; + cb_params.btm_big_sync_estab.big_handle = params->big_handle; + cb_params.btm_big_sync_estab.transport_latency_big = params->transport_latency_big; + cb_params.btm_big_sync_estab.nse = params->nse; + cb_params.btm_big_sync_estab.bn = params->bn; + cb_params.btm_big_sync_estab.pto = params->pto; + cb_params.btm_big_sync_estab.irc = params->irc; + cb_params.btm_big_sync_estab.max_pdu = params->max_pdu; + cb_params.btm_big_sync_estab.iso_interval = params->iso_interval; + cb_params.btm_big_sync_estab.num_bis = num_bis; + + // Copy bis_handle array with bounds checking + if (num_bis > 0) { + memcpy(&cb_params.btm_big_sync_estab.bis_handle[0], ¶ms->bis_handle[0], num_bis * sizeof(uint16_t)); + } BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT, &cb_params); } @@ -286,6 +325,11 @@ tBTM_STATUS BTM_BleBigCreate(uint8_t big_handle, uint8_t adv_handle, uint8_t num rtn %d phy %d packing %d framing %d encryption %d broadcast_code %d", big_handle, adv_handle, num_bis, sdu_interval, max_sdu, max_transport_latency,\ rtn, phy, packing, framing, encryption, broadcast_code); + if (num_bis > BLE_ISO_BIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); + return BTM_ILLEGAL_VALUE; + } + btsnd_hcic_ble_big_create(big_handle, adv_handle, num_bis, sdu_interval, max_sdu, max_transport_latency, rtn, phy, packing, framing, encryption, broadcast_code); @@ -299,6 +343,11 @@ tBTM_STATUS BTM_BleBigCreateTest(uint8_t big_handle, uint8_t adv_handle, uint8_t uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc, uint8_t pto, uint8_t encryption, uint8_t *broadcast_code) { + if (num_bis > BLE_ISO_BIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); + return BTM_ILLEGAL_VALUE; + } + btsnd_hcic_ble_big_create_test(big_handle, adv_handle, num_bis, sdu_interval, iso_interval, nse, max_sdu, max_pdu, phy, packing, framing, bn, irc, pto, encryption, broadcast_code); @@ -331,6 +380,11 @@ tBTM_STATUS BTM_BleBigSyncCreate(uint8_t big_handle, uint16_t sync_handle, uint8_t mse, uint16_t big_sync_timeout, uint8_t num_bis, uint8_t *bis) { + if (num_bis > BLE_ISO_BIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); + return BTM_ILLEGAL_VALUE; + } + btsnd_hcic_ble_big_sync_create(big_handle, sync_handle, encryption, bc_code, mse, big_sync_timeout, num_bis, bis); return BTM_SUCCESS; @@ -430,6 +484,11 @@ tBTM_STATUS BTM_BleSetCigParams(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_ tHCI_STATUS err = HCI_SUCCESS; tBTM_STATUS status = BTM_SUCCESS; + if (cis_cnt > BLE_ISO_CIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, cis_cnt %d exceeds BLE_ISO_CIS_MAX_COUNT %d", __func__, cis_cnt, BLE_ISO_CIS_MAX_COUNT); + return BTM_ILLEGAL_VALUE; + } + if ((err = btsnd_hcic_ble_iso_set_cig_params(cig_id, sdu_int_c_to_p, sdu_int_p_to_c, worse_case_SCA, packing, framing, mtl_c_to_p, mtl_p_to_c, cis_cnt, (struct ble_hci_le_cis_params *)cis_params)) != HCI_SUCCESS) { BTM_TRACE_ERROR("iso set cig params, cmd err=0x%x", err); @@ -445,6 +504,11 @@ tBTM_STATUS BTM_BleSetCigParamsTest(uint8_t cig_id, uint32_t sdu_int_c_to_p, uin tHCI_STATUS err = HCI_SUCCESS; tBTM_STATUS status = BTM_SUCCESS; + if (cis_cnt > BLE_ISO_CIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, cis_cnt %d exceeds BLE_ISO_CIS_MAX_COUNT %d", __func__, cis_cnt, BLE_ISO_CIS_MAX_COUNT); + return BTM_ILLEGAL_VALUE; + } + if ((err = btsnd_hcic_ble_iso_set_cig_params_test(cig_id, sdu_int_c_to_p, sdu_int_p_to_c,ft_c_to_p, ft_p_to_c, iso_interval, worse_case_SCA, packing, framing, cis_cnt, (struct ble_hci_le_cis_params_test *)cis_params)) != HCI_SUCCESS) { BTM_TRACE_ERROR("iso set cig params test, cmd err=0x%x", err); @@ -461,6 +525,11 @@ void btm_ble_create_cis_cmd_status(tBTM_BLE_ISO_CB_PARAMS *cb_params) tBTM_STATUS BTM_BleCreateCis(uint8_t cis_count, uint8_t *cis_hdls) { + if (cis_count > BLE_ISO_CIS_MAX_COUNT) { + BTM_TRACE_ERROR("%s, cis_count %d exceeds BLE_ISO_CIS_MAX_COUNT %d", __func__, cis_count, BLE_ISO_CIS_MAX_COUNT); + return BTM_ILLEGAL_VALUE; + } + btsnd_hcic_ble_iso_create_cis(cis_count, (struct ble_hci_cis_hdls *)cis_hdls); return BTM_SUCCESS; diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c b/components/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c index 31d60546f1..75b5e9e1bc 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c @@ -23,848 +23,5 @@ #if (BLE_INCLUDED == TRUE) -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -#include "stack/bt_types.h" -#include "stack/hcimsgs.h" -#include "stack/btu.h" -#include "btm_int.h" -//#include "bt_utils.h" -#include "stack/hcidefs.h" -#include "stack/btm_ble_api.h" -/************************************************************************************ -** Constants & Macros -************************************************************************************/ -/* length of each multi adv sub command */ -#define BTM_BLE_MULTI_ADV_ENB_LEN 3 -#define BTM_BLE_MULTI_ADV_SET_PARAM_LEN 24 -#define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN (BTM_BLE_AD_DATA_LEN + 3) -#define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN 8 - -#define BTM_BLE_MULTI_ADV_CB_EVT_MASK 0xF0 -#define BTM_BLE_MULTI_ADV_SUBCODE_MASK 0x0F - -/************************************************************************************ -** Static variables -************************************************************************************/ -#if BTM_DYNAMIC_MEMORY == FALSE -tBTM_BLE_MULTI_ADV_CB btm_multi_adv_cb; -tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q; -#else -tBTM_BLE_MULTI_ADV_CB *btm_multi_adv_cb_ptr; -tBTM_BLE_MULTI_ADV_INST_IDX_Q *btm_multi_adv_idx_q_ptr; -#define btm_multi_adv_cb (*btm_multi_adv_cb_ptr) -#define btm_multi_adv_idx_q (*btm_multi_adv_idx_q_ptr) -#endif - -/************************************************************************************ -** Externs -************************************************************************************/ -extern void btm_ble_update_dmt_flag_bits(UINT8 *flag_value, - const UINT16 connect_mode, const UINT16 disc_mode); - -/******************************************************************************* -** -** Function btm_ble_multi_adv_enq_op_q -** -** Description enqueue a multi adv operation in q to check command complete -** status. -** -** Returns void -** -*******************************************************************************/ -void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt) -{ - tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q; - - p_op_q->p_inst_id[p_op_q->next_idx] = inst_id; - - p_op_q->p_sub_code[p_op_q->next_idx] = (opcode | (cb_evt << 4)); - - p_op_q->next_idx = (p_op_q->next_idx + 1) % BTM_BleMaxMultiAdvInstanceCount(); -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_deq_op_q -** -** Description dequeue a multi adv operation from q when command complete -** is received. -** -** Returns void -** -*******************************************************************************/ -void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt) -{ - tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q; - - *p_inst_id = p_op_q->p_inst_id[p_op_q->pending_idx] & 0x7F; - *p_cb_evt = (p_op_q->p_sub_code[p_op_q->pending_idx] >> 4); - *p_opcode = (p_op_q->p_sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK); - - p_op_q->pending_idx = (p_op_q->pending_idx + 1) % BTM_BleMaxMultiAdvInstanceCount(); -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_vsc_cmpl_cback -** -** Description Multi adv VSC complete callback -** -** Parameters -** -** Returns void -** -*******************************************************************************/ -void btm_ble_multi_adv_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params) -{ - UINT8 status, subcode; - UINT8 *p = p_params->p_param_buf, inst_id; - UINT16 len = p_params->param_len; - tBTM_BLE_MULTI_ADV_INST *p_inst ; - UINT8 cb_evt = 0, opcode; - - if (len < 2) { - BTM_TRACE_ERROR("wrong length for btm_ble_multi_adv_vsc_cmpl_cback"); - return; - } - - STREAM_TO_UINT8(status, p); - STREAM_TO_UINT8(subcode, p); - - btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt); - - BTM_TRACE_DEBUG("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt); - - if (opcode != subcode || inst_id == 0) { - BTM_TRACE_ERROR("get unexpected VSC cmpl, expect: %d get: %d", subcode, opcode); - return; - } - - p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; - - switch (subcode) { - case BTM_BLE_MULTI_ADV_ENB: { - BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_ENB status = %d", status); - - /* Mark as not in use here, if instance cannot be enabled */ - if (HCI_SUCCESS != status && BTM_BLE_MULTI_ADV_ENB_EVT == cb_evt) { - btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE; - } - break; - } - - case BTM_BLE_MULTI_ADV_SET_PARAM: { - BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_PARAM status = %d", status); - break; - } - - case BTM_BLE_MULTI_ADV_WRITE_ADV_DATA: { - BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_ADV_DATA status = %d", status); - break; - } - - case BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA: { - BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA status = %d", status); - break; - } - - case BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR: { - BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR status = %d", status); - break; - } - - default: - break; - } - - if (cb_evt != 0 && p_inst->p_cback != NULL) { - (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status); - } - return; -} - -/******************************************************************************* -** -** Function btm_ble_enable_multi_adv -** -** Description This function enable the customer specific feature in controller -** -** Parameters enable: enable or disable -** inst_id: adv instance ID, can not be 0 -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_evt) -{ - UINT8 param[BTM_BLE_MULTI_ADV_ENB_LEN], *pp; - UINT8 enb = enable ? 1 : 0; - tBTM_STATUS rt; - - pp = param; - memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN); - - UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_ENB); - UINT8_TO_STREAM (pp, enb); - UINT8_TO_STREAM (pp, inst_id); - - BTM_TRACE_EVENT (" btm_ble_enable_multi_adv: enb %d, Inst ID %d", enb, inst_id); - - if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, - BTM_BLE_MULTI_ADV_ENB_LEN, - param, - btm_ble_multi_adv_vsc_cmpl_cback)) - == BTM_CMD_STARTED) { - btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id, cb_evt); - } - return rt; -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_set_params -** -** Description This function enable the customer specific feature in controller -** -** Parameters advertise parameters used for this instance. -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst, - tBTM_BLE_ADV_PARAMS *p_params, - UINT8 cb_evt) -{ - UINT8 param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN], *pp; - tBTM_STATUS rt; - BD_ADDR dummy = {0, 0, 0, 0, 0, 0}; - - pp = param; - memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN); - - UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM); - - UINT16_TO_STREAM (pp, p_params->adv_int_min); - UINT16_TO_STREAM (pp, p_params->adv_int_max); - UINT8_TO_STREAM (pp, p_params->adv_type); - -#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) - if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) { - UINT8_TO_STREAM (pp, BLE_ADDR_RANDOM); - BDADDR_TO_STREAM (pp, p_inst->rpa); - } else -#endif - { - UINT8_TO_STREAM (pp, BLE_ADDR_PUBLIC); - BDADDR_TO_STREAM (pp, controller_get_interface()->get_address()->address); - } - - BTM_TRACE_EVENT (" btm_ble_multi_adv_set_params,Min %d, Max %d,adv_type %d", - p_params->adv_int_min, p_params->adv_int_max, p_params->adv_type); - - UINT8_TO_STREAM (pp, 0); - BDADDR_TO_STREAM (pp, dummy); - - if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP) { - p_params->channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP; - } - UINT8_TO_STREAM (pp, p_params->channel_map); - - if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX) { - p_params->adv_filter_policy = AP_SCAN_CONN_ALL; - } - UINT8_TO_STREAM (pp, p_params->adv_filter_policy); - - UINT8_TO_STREAM (pp, p_inst->inst_id); - - if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX) { - p_params->tx_power = BTM_BLE_ADV_TX_POWER_MAX; - } - UINT8_TO_STREAM (pp, btm_ble_map_adv_tx_power(p_params->tx_power)); - - BTM_TRACE_EVENT("set_params:Chnl Map %d,adv_fltr policy %d,ID:%d, TX Power%d", - p_params->channel_map, p_params->adv_filter_policy, p_inst->inst_id, p_params->tx_power); - - if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, - BTM_BLE_MULTI_ADV_SET_PARAM_LEN, - param, - btm_ble_multi_adv_vsc_cmpl_cback)) - == BTM_CMD_STARTED) { - p_inst->adv_evt = p_params->adv_type; - -#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) - if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) { - /* start timer */ - p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst; - btu_start_timer_oneshot(&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR, - BTM_BLE_PRIVATE_ADDR_INT); - } -#endif - btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, p_inst->inst_id, cb_evt); - } - return rt; -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_write_rpa -** -** Description This function write the random address for the adv instance into -** controller -** -** Parameters -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr) -{ - UINT8 param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param; - tBTM_STATUS rt; - - BTM_TRACE_EVENT ("%s-BD_ADDR:%02x-%02x-%02x-%02x-%02x-%02x,inst_id:%d", - __FUNCTION__, random_addr[5], random_addr[4], random_addr[3], random_addr[2], - random_addr[1], random_addr[0], p_inst->inst_id); - - memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN); - - UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR); - BDADDR_TO_STREAM(pp, random_addr); - UINT8_TO_STREAM(pp, p_inst->inst_id); - - if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, - BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN, - param, - btm_ble_multi_adv_vsc_cmpl_cback)) == BTM_CMD_STARTED) { - /* start a periodical timer to refresh random addr */ - btu_stop_timer_oneshot(&p_inst->raddr_timer_ent); - p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst; - btu_start_timer_oneshot(&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR, - BTM_BLE_PRIVATE_ADDR_INT); - - btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR, p_inst->inst_id, 0); - } - return rt; -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_gen_rpa_cmpl -** -** Description RPA generation completion callback for each adv instance. Will -** continue write the new RPA into controller. -** -** Returns none. -** -*******************************************************************************/ -void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p) -{ -#if (SMP_INCLUDED == TRUE) - tSMP_ENC output; - UINT8 index = 0; - tBTM_BLE_MULTI_ADV_INST *p_inst = NULL; - - /* Retrieve the index of adv instance from stored Q */ - if (btm_multi_adv_idx_q.front == -1) { - BTM_TRACE_ERROR(" %s can't locate advertise instance", __FUNCTION__); - return; - } else { - index = btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.front]; - if (btm_multi_adv_idx_q.front == btm_multi_adv_idx_q.rear) { - btm_multi_adv_idx_q.front = -1; - btm_multi_adv_idx_q.rear = -1; - } else { - btm_multi_adv_idx_q.front = (btm_multi_adv_idx_q.front + 1) % BTM_BLE_MULTI_ADV_MAX; - } - } - - p_inst = &(btm_multi_adv_cb.p_adv_inst[index]); - - BTM_TRACE_EVENT ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id); - if (p) { - p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK); - p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB; - - p_inst->rpa[2] = p->param_buf[0]; - p_inst->rpa[1] = p->param_buf[1]; - p_inst->rpa[0] = p->param_buf[2]; - - if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output)) { - BTM_TRACE_DEBUG("generate random address failed"); - } else { - /* set hash to be LSB of rpAddress */ - p_inst->rpa[5] = output.param_buf[0]; - p_inst->rpa[4] = output.param_buf[1]; - p_inst->rpa[3] = output.param_buf[2]; - } - - if (p_inst->inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD && - p_inst->inst_id < BTM_BleMaxMultiAdvInstanceCount()) { - /* set it to controller */ - btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa); - } - } -#endif -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_configure_rpa -** -** Description This function set the random address for the adv instance -** -** Parameters advertise parameters used for this instance. -** -** Returns none -** -*******************************************************************************/ -void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst) -{ - if (btm_multi_adv_idx_q.front == (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX) { - BTM_TRACE_ERROR("outstanding rand generation exceeded max allowed "); - return; - } else { - if (btm_multi_adv_idx_q.front == -1) { - btm_multi_adv_idx_q.front = 0; - btm_multi_adv_idx_q.rear = 0; - } else { - btm_multi_adv_idx_q.rear = (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX; - } - btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.rear] = p_inst->index; - } - btm_gen_resolvable_private_addr((void *)btm_ble_multi_adv_gen_rpa_cmpl); -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_reenable -** -** Description This function re-enable adv instance upon a connection establishment. -** -** Parameters advertise parameters used for this instance. -** -** Returns none. -** -*******************************************************************************/ -void btm_ble_multi_adv_reenable(UINT8 inst_id) -{ - tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; - - if (TRUE == p_inst->in_use) { - if (p_inst->adv_evt != BTM_BLE_CONNECT_DIR_EVT) { - btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, 0); - } else - /* mark directed adv as disabled if adv has been stopped */ - { - (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT, p_inst->inst_id, p_inst->p_ref, 0); - p_inst->in_use = FALSE; - } - } -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_enb_privacy -** -** Description This function enable/disable privacy setting in multi adv -** -** Parameters enable: enable or disable the adv instance. -** -** Returns none. -** -*******************************************************************************/ -void btm_ble_multi_adv_enb_privacy(BOOLEAN enable) -{ - UINT8 i; - tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0]; - - for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) { - p_inst->in_use = FALSE; - if (enable) { - btm_ble_multi_adv_configure_rpa (p_inst); - } else { - btu_stop_timer_oneshot(&p_inst->raddr_timer_ent); - } - } -} - -/******************************************************************************* -** -** Function BTM_BleEnableAdvInstance -** -** Description This function enable a Multi-ADV instance with the specified -** adv parameters -** -** Parameters p_params: pointer to the adv parameter structure, set as default -** adv parameter when the instance is enabled. -** p_cback: callback function for the adv instance. -** p_ref: reference data attach to the adv instance to be enabled. -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params, - tBTM_BLE_MULTI_ADV_CBACK *p_cback, void *p_ref) -{ - UINT8 i; - tBTM_STATUS rt = BTM_NO_RESOURCES; - tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0]; - - BTM_TRACE_EVENT("BTM_BleEnableAdvInstance called"); - - if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max) { - BTM_TRACE_ERROR("Controller does not support Multi ADV"); - return BTM_ERR_PROCESSING; - } - - if (NULL == p_inst) { - BTM_TRACE_ERROR("Invalid instance in BTM_BleEnableAdvInstance"); - return BTM_ERR_PROCESSING; - } - - for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) { - if (FALSE == p_inst->in_use) { - p_inst->in_use = TRUE; - /* configure adv parameter */ - if (p_params) { - rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0); - } else { - rt = BTM_CMD_STARTED; - } - - /* enable adv */ - BTM_TRACE_EVENT("btm_ble_enable_multi_adv being called with inst_id:%d", - p_inst->inst_id); - - if (BTM_CMD_STARTED == rt) { - if ((rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, - BTM_BLE_MULTI_ADV_ENB_EVT)) == BTM_CMD_STARTED) { - p_inst->p_cback = p_cback; - p_inst->p_ref = p_ref; - } - } - - if (BTM_CMD_STARTED != rt) { - p_inst->in_use = FALSE; - BTM_TRACE_ERROR("BTM_BleEnableAdvInstance failed"); - } - break; - } - } - return rt; -} - -/******************************************************************************* -** -** Function BTM_BleUpdateAdvInstParam -** -** Description This function update a Multi-ADV instance with the specified -** adv parameters. -** -** Parameters inst_id: adv instance ID -** p_params: pointer to the adv parameter structure. -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params) -{ - tBTM_STATUS rt = BTM_ILLEGAL_VALUE; - tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; - - BTM_TRACE_EVENT("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id); - - if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max) { - BTM_TRACE_ERROR("Controller does not support Multi ADV"); - return BTM_ERR_PROCESSING; - } - - if (inst_id < BTM_BleMaxMultiAdvInstanceCount() && - inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD && - p_params != NULL) { - if (FALSE == p_inst->in_use) { - BTM_TRACE_DEBUG("adv instance %d is not active", inst_id); - return BTM_WRONG_MODE; - } else { - btm_ble_enable_multi_adv(FALSE, inst_id, 0); - } - - if (BTM_CMD_STARTED == btm_ble_multi_adv_set_params(p_inst, p_params, 0)) { - rt = btm_ble_enable_multi_adv(TRUE, inst_id, BTM_BLE_MULTI_ADV_PARAM_EVT); - } - } - return rt; -} - -/******************************************************************************* -** -** Function BTM_BleCfgAdvInstData -** -** Description This function configure a Multi-ADV instance with the specified -** adv data or scan response data. -** -** Parameters inst_id: adv instance ID -** is_scan_rsp: is this scan response. if no, set as adv data. -** data_mask: adv data mask. -** p_data: pointer to the adv data structure. -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp, - tBTM_BLE_AD_MASK data_mask, - tBTM_BLE_ADV_DATA *p_data) -{ - UINT8 param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param; - UINT8 sub_code = (is_scan_rsp) ? - BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA : BTM_BLE_MULTI_ADV_WRITE_ADV_DATA; - UINT8 *p_len; - tBTM_STATUS rt; - UINT8 *pp_temp = (UINT8 *)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN - 1); - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - if (0 == cmn_ble_vsc_cb.adv_inst_max) { - BTM_TRACE_ERROR("Controller does not support Multi ADV"); - return BTM_ERR_PROCESSING; - } - - btm_ble_update_dmt_flag_bits(&p_data->flag, btm_cb.btm_inq_vars.connectable_mode, - btm_cb.btm_inq_vars.discoverable_mode); - - BTM_TRACE_EVENT("BTM_BleCfgAdvInstData called with inst_id:%d", inst_id); - if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD) { - return BTM_ILLEGAL_VALUE; - } - - memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN); - - UINT8_TO_STREAM(pp, sub_code); - p_len = pp ++; - btm_ble_build_adv_data(&data_mask, &pp, p_data); - *p_len = (UINT8)(pp - param - 2); - UINT8_TO_STREAM(pp_temp, inst_id); - - if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF, - (UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, - param, - btm_ble_multi_adv_vsc_cmpl_cback)) - == BTM_CMD_STARTED) { - btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT); - } - return rt; -} - -/******************************************************************************* -** -** Function BTM_BleDisableAdvInstance -** -** Description This function disables a Multi-ADV instance. -** -** Parameters inst_id: adv instance ID -** -** Returns status -** -*******************************************************************************/ -tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id) -{ - tBTM_STATUS rt = BTM_ILLEGAL_VALUE; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; - - BTM_TRACE_EVENT("BTM_BleDisableAdvInstance with inst_id:%d", inst_id); - - BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb); - - if (0 == cmn_ble_vsc_cb.adv_inst_max) { - BTM_TRACE_ERROR("Controller does not support Multi ADV"); - return BTM_ERR_PROCESSING; - } - - if (inst_id < BTM_BleMaxMultiAdvInstanceCount() && - inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD) { - if ((rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT)) - == BTM_CMD_STARTED) { - btm_ble_multi_adv_configure_rpa(&btm_multi_adv_cb.p_adv_inst[inst_id - 1]); - btu_stop_timer_oneshot(&btm_multi_adv_cb.p_adv_inst[inst_id - 1].raddr_timer_ent); - btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE; - } - } - return rt; -} -/******************************************************************************* -** -** Function btm_ble_multi_adv_vse_cback -** -** Description VSE callback for multi adv events. -** -** Returns -** -*******************************************************************************/ -void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p) -{ - UINT8 sub_event; - UINT8 adv_inst; - UINT16 conn_handle; - tACL_CONN *p_acl_cb = NULL; - /* Check if this is a BLE RSSI vendor specific event */ - STREAM_TO_UINT8(sub_event, p); - len--; - - BTM_TRACE_EVENT("btm_ble_multi_adv_vse_cback called with event:%d", sub_event); - if ((sub_event == HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG) && (len >= 4)) { - STREAM_TO_UINT8(adv_inst, p); - ++p; - STREAM_TO_UINT16(conn_handle, p); - - if ((p_acl_cb = btm_handle_to_acl(conn_handle)) != NULL) { -#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) - if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE && - adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) { - memcpy(p_acl_cb->conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa, - BD_ADDR_LEN); - } -#endif - } - - if (adv_inst < BTM_BleMaxMultiAdvInstanceCount() && - adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) { - BTM_TRACE_EVENT("btm_ble_multi_adv_reenable called"); - btm_ble_multi_adv_reenable(adv_inst); - } - /* re-enable connectibility */ - else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD) { - if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE) { - btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode ); - } - } - - } - -} -/******************************************************************************* -** -** Function btm_ble_multi_adv_init -** -** Description This function initialize the multi adv control block. -** -** Parameters None -** -** Returns void -** -*******************************************************************************/ -void btm_ble_multi_adv_init(void) -{ -#if BTM_DYNAMIC_MEMORY == TRUE - btm_multi_adv_cb_ptr = (tBTM_BLE_MULTI_ADV_CB *)osi_malloc(sizeof(tBTM_BLE_MULTI_ADV_CB)); - btm_multi_adv_idx_q_ptr = (tBTM_BLE_MULTI_ADV_INST_IDX_Q *)osi_malloc(sizeof(tBTM_BLE_MULTI_ADV_INST_IDX_Q)); - if (btm_multi_adv_cb_ptr == NULL || btm_multi_adv_idx_q_ptr == NULL) { - BTM_TRACE_ERROR("%s malloc failed", __func__); - return; - } -#endif - - UINT8 i = 0; - memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB)); - memset (&btm_multi_adv_idx_q, 0, sizeof (tBTM_BLE_MULTI_ADV_INST_IDX_Q)); - btm_multi_adv_idx_q.front = -1; - btm_multi_adv_idx_q.rear = -1; - - if (btm_cb.cmn_ble_vsc_cb.adv_inst_max > 0) { - btm_multi_adv_cb.p_adv_inst = osi_malloc( sizeof(tBTM_BLE_MULTI_ADV_INST) * - (btm_cb.cmn_ble_vsc_cb.adv_inst_max)); - memset(btm_multi_adv_cb.p_adv_inst, 0, sizeof(tBTM_BLE_MULTI_ADV_INST) * - (btm_cb.cmn_ble_vsc_cb.adv_inst_max)); - - btm_multi_adv_cb.op_q.p_sub_code = osi_malloc( sizeof(UINT8) * - (btm_cb.cmn_ble_vsc_cb.adv_inst_max)); - memset(btm_multi_adv_cb.op_q.p_sub_code, 0, - sizeof(UINT8) * (btm_cb.cmn_ble_vsc_cb.adv_inst_max)); - - btm_multi_adv_cb.op_q.p_inst_id = osi_malloc( sizeof(UINT8) * - (btm_cb.cmn_ble_vsc_cb.adv_inst_max)); - memset(btm_multi_adv_cb.op_q.p_inst_id, 0, - sizeof(UINT8) * (btm_cb.cmn_ble_vsc_cb.adv_inst_max)); - } - - /* Initialize adv instance indices and IDs. */ - for (i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) { - btm_multi_adv_cb.p_adv_inst[i].index = i; - btm_multi_adv_cb.p_adv_inst[i].inst_id = i + 1; - } - - BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE); -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_cleanup -** -** Description This function cleans up multi adv control block. -** -** Parameters -** Returns void -** -*******************************************************************************/ -void btm_ble_multi_adv_cleanup(void) -{ -#if BTM_DYNAMIC_MEMORY == TRUE - if (btm_multi_adv_cb_ptr == NULL) - { - BTM_TRACE_WARNING("%s memory has been freed", __func__); - return; - } -#endif - if (btm_multi_adv_cb.p_adv_inst) { - osi_free(btm_multi_adv_cb.p_adv_inst); - btm_multi_adv_cb.p_adv_inst = NULL; - } - - if (btm_multi_adv_cb.op_q.p_sub_code) { - osi_free(btm_multi_adv_cb.op_q.p_sub_code); - btm_multi_adv_cb.op_q.p_sub_code = NULL; - } - - if (btm_multi_adv_cb.op_q.p_inst_id) { - osi_free(btm_multi_adv_cb.op_q.p_inst_id); - btm_multi_adv_cb.op_q.p_inst_id = NULL; - } - -#if BTM_DYNAMIC_MEMORY == TRUE - if(btm_multi_adv_cb_ptr) { - osi_free(btm_multi_adv_cb_ptr); - btm_multi_adv_cb_ptr = NULL; - } - if(btm_multi_adv_idx_q_ptr) { - osi_free(btm_multi_adv_idx_q_ptr); - btm_multi_adv_idx_q_ptr = NULL; - } -#endif -} - -/******************************************************************************* -** -** Function btm_ble_multi_adv_get_ref -** -** Description This function obtains the reference pointer for the instance ID provided -** -** Parameters inst_id - Instance ID -** -** Returns void* -** -*******************************************************************************/ -void *btm_ble_multi_adv_get_ref(UINT8 inst_id) -{ - tBTM_BLE_MULTI_ADV_INST *p_inst = NULL; - - if (inst_id < BTM_BleMaxMultiAdvInstanceCount()) { - p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1]; - if (NULL != p_inst) { - return p_inst->p_ref; - } - } - - return NULL; -} -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) #endif diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_privacy.c b/components/bt/host/bluedroid/stack/btm/btm_ble_privacy.c index ccc7f6e0b7..633d15e253 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_privacy.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_privacy.c @@ -499,6 +499,7 @@ void btm_ble_set_privacy_mode_complete(UINT8 *p, UINT16 evt_len) } } +#if (0) /******************************************************************************* VSC that implement controller based privacy ********************************************************************************/ @@ -534,7 +535,7 @@ void btm_ble_resolving_list_vsc_op_cmpl (tBTM_VSC_CMPL *p_params) /* RPA offloading enable/disabled */ } } - +#endif /******************************************************************************* ** ** Function btm_ble_remove_resolving_list_entry @@ -569,6 +570,7 @@ tBTM_STATUS btm_ble_remove_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec) * send key to the controller, but to resolve the random address in host. */ #endif } else { +#if (0) UINT8 param[20] = {0}; UINT8 *p = param; @@ -580,6 +582,7 @@ tBTM_STATUS btm_ble_remove_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec) BTM_BLE_META_REMOVE_IRK_LEN, param, btm_ble_resolving_list_vsc_op_cmpl); +#endif } if (st == BTM_CMD_STARTED) { @@ -609,6 +612,7 @@ tBTM_STATUS btm_ble_clear_resolving_list(void) st = BTM_SUCCESS; } } else { +#if (0) UINT8 param[20] = {0}; UINT8 *p = param; @@ -617,6 +621,7 @@ tBTM_STATUS btm_ble_clear_resolving_list(void) BTM_BLE_META_CLEAR_IRK_LEN, param, btm_ble_resolving_list_vsc_op_cmpl); +#endif } return st; @@ -647,6 +652,7 @@ tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec) st = BTM_CMD_STARTED; } } else { +#if (0) UINT8 param[20] = {0}; UINT8 *p = param; @@ -657,6 +663,7 @@ tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec) BTM_BLE_META_READ_IRK_LEN, param, btm_ble_resolving_list_vsc_op_cmpl); +#endif } if (st == BTM_CMD_STARTED) { @@ -711,11 +718,11 @@ BOOLEAN btm_ble_suspend_resolving_list_activity(void) btm_ble_stop_scan(); p_ble_cb->suspended_rl_state |= BTM_BLE_RL_SCAN; } -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) if (btm_ble_suspend_bg_conn()) { p_ble_cb->suspended_rl_state |= BTM_BLE_RL_INIT; } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) return TRUE; } @@ -743,14 +750,15 @@ void btm_ble_resume_resolving_list_activity(void) btm_ble_start_scan(); } #endif // #if (BLE_42_SCAN_EN == TRUE) -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_INIT) { btm_ble_resume_bg_conn(); } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) p_ble_cb->suspended_rl_state = BTM_BLE_RL_IDLE; } +#if (0) /******************************************************************************* ** ** Function btm_ble_vendor_enable_irk_feature @@ -780,6 +788,7 @@ tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable) return st; } +#endif /******************************************************************************* ** @@ -797,7 +806,9 @@ BOOLEAN btm_ble_exe_disable_resolving_list(void) } if (!controller_get_interface()->supports_ble_privacy()) { +#if (0) btm_ble_vendor_enable_irk_feature(FALSE); +#endif } else { //btsnd_hcic_ble_set_addr_resolution_enable(FALSE); } @@ -821,7 +832,9 @@ void btm_ble_exe_enable_resolving_list(void) } if (!controller_get_interface()->supports_ble_privacy()) { +#if (0) btm_ble_vendor_enable_irk_feature(TRUE); +#endif } else { //btsnd_hcic_ble_set_addr_resolution_enable(TRUE); } @@ -930,6 +943,7 @@ BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec) #endif } else { +#if (0) UINT8 param[40] = {0}; UINT8 *p = param; @@ -945,6 +959,7 @@ BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec) == BTM_CMD_STARTED) { rt = TRUE; } +#endif } if (rt) { diff --git a/components/bt/host/bluedroid/stack/btm/btm_dev.c b/components/bt/host/bluedroid/stack/btm/btm_dev.c index 1784d4a353..cc5ad3358b 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_dev.c +++ b/components/bt/host/bluedroid/stack/btm/btm_dev.c @@ -73,9 +73,11 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, /* There is no device record, allocate one. * If we can not find an empty spot for this one, let it fail. */ if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS) { - p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); - if(p_dev_rec) { - list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); + p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); + if(p_dev_rec) { + BTM_TRACE_DEBUG("%s alloc a new dev rec %p bd_addr="MACSTR"", + __func__, p_dev_rec, MAC2STR(bd_addr)); + list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); /* Mark this record as in use and initialize */ memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC)); p_dev_rec->sec_flags = BTM_SEC_IN_USE; @@ -360,6 +362,8 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr) if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS){ p_dev_new_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); if (p_dev_new_rec) { + BTM_TRACE_DEBUG("%s alloc a new dev rec %p bd_addr="MACSTR"", + __func__, p_dev_new_rec, MAC2STR(bd_addr)); new_entry_found = TRUE; malloc_new_entry = TRUE; } else { diff --git a/components/bt/host/bluedroid/stack/btm/btm_devctl.c b/components/bt/host/bluedroid/stack/btm/btm_devctl.c index 63c26e881e..057eba2dbb 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -88,18 +88,21 @@ void btm_dev_init (void) #endif btm_cb.devcb.reset_timer.param = (TIMER_PARAM_TYPE)TT_DEV_RESET; +#if (CLASSIC_BT_INCLUDED == TRUE) btm_cb.devcb.rln_timer.param = (TIMER_PARAM_TYPE)TT_DEV_RLN; +#endif // (CLASSIC_BT_INCLUDED == TRUE) btm_cb.btm_acl_pkt_types_supported = BTM_ACL_PKT_TYPES_MASK_DH1 + BTM_ACL_PKT_TYPES_MASK_DM1 + BTM_ACL_PKT_TYPES_MASK_DH3 + BTM_ACL_PKT_TYPES_MASK_DM3 + BTM_ACL_PKT_TYPES_MASK_DH5 + BTM_ACL_PKT_TYPES_MASK_DM5; - +#if (CLASSIC_BT_INCLUDED == TRUE) btm_cb.btm_sco_pkt_types_supported = BTM_SCO_PKT_TYPES_MASK_HV1 + BTM_SCO_PKT_TYPES_MASK_HV2 + BTM_SCO_PKT_TYPES_MASK_HV3 + BTM_SCO_PKT_TYPES_MASK_EV3 + BTM_SCO_PKT_TYPES_MASK_EV4 + BTM_SCO_PKT_TYPES_MASK_EV5; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } @@ -121,6 +124,7 @@ static void btm_db_reset (void) btm_inq_db_reset(); +#if (CLASSIC_BT_INCLUDED == TRUE) if (btm_cb.devcb.p_rln_cmpl_cb) { p_cb = btm_cb.devcb.p_rln_cmpl_cb; btm_cb.devcb.p_rln_cmpl_cb = NULL; @@ -129,6 +133,7 @@ static void btm_db_reset (void) (*p_cb)((void *) NULL); } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) if (btm_cb.devcb.p_rssi_cmpl_cb) { p_cb = btm_cb.devcb.p_rssi_cmpl_cb; @@ -169,17 +174,18 @@ static void reset_complete(void) #if (BLE_INCLUDED == TRUE) btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE; +#if (BLE_GATT_BGCONN == TRUE) btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE; btm_cb.ble_ctr_cb.p_select_cback = NULL; -#if (tGATT_BG_CONN_DEV == TRUE) +#endif // (BLE_GATT_BGCONN == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) gatt_reset_bgdev_list(); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - btm_ble_multi_adv_init(); -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -#endif +#endif // #if (GATT_BG_CONN_DEV == TRUE) +#endif +#if (CLASSIC_BT_INCLUDED == TRUE) btm_pm_reset(); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) l2c_link_processs_num_bufs(controller->get_acl_buffer_count_classic()); #if BTM_SCO_HCI_INCLUDED == TRUE @@ -247,6 +253,7 @@ BOOLEAN BTM_IsDeviceUp (void) return controller_get_interface()->get_is_ready(); } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_dev_timeout @@ -270,6 +277,7 @@ void btm_dev_timeout (TIMER_LIST_ENT *p_tle) } } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -330,7 +338,7 @@ static void btm_decode_ext_features_page (UINT8 page_number, const BD_FEATURES p BTM_TRACE_DEBUG("Local supported ACL packet types: 0x%04x", btm_cb.btm_acl_pkt_types_supported); - +#if (CLASSIC_BT_INCLUDED == TRUE) /* Create (e)SCO supported packet types mask */ btm_cb.btm_sco_pkt_types_supported = 0; #if BTM_SCO_INCLUDED == TRUE @@ -411,9 +419,9 @@ static void btm_decode_ext_features_page (UINT8 page_number, const BD_FEATURES p } else { btm_cb.btm_def_link_policy &= ~HCI_ENABLE_PARK_MODE; } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) btm_sec_dev_reset (); - +#if (CLASSIC_BT_INCLUDED == TRUE) if (HCI_LMP_INQ_RSSI_SUPPORTED(p_features)) { if (HCI_EXT_INQ_RSP_SUPPORTED(p_features)) { BTM_SetInquiryMode (BTM_INQ_RESULT_EXTENDED); @@ -421,7 +429,7 @@ static void btm_decode_ext_features_page (UINT8 page_number, const BD_FEATURES p BTM_SetInquiryMode (BTM_INQ_RESULT_WITH_RSSI); } } - +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE if ( HCI_NON_FLUSHABLE_PB_SUPPORTED(p_features)) { l2cu_set_non_flushable_pbf(TRUE); @@ -552,7 +560,7 @@ tBTM_STATUS BTM_ReadLocalDeviceName (char **p_name, tBT_DEVICE_TYPE name_type) #endif } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_ReadLocalDeviceNameFromController @@ -610,7 +618,7 @@ void btm_read_local_name_complete (UINT8 *p, UINT16 evt_len) } } } - +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_SetDeviceClass @@ -764,6 +772,7 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, tBTM_BLE_CB *ble_cb = &btm_cb.ble_ctr_cb; switch(opcode) { case HCI_VENDOR_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST: { +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) uint8_t subcode, status; uint32_t length; STREAM_TO_UINT8(status, p); STREAM_TO_UINT8(subcode, p); @@ -772,6 +781,7 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, (*ble_cb->update_exceptional_list_cmp_cb)(status, subcode, length, p); } break; +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) } case HCI_VENDOR_BLE_CLEAR_ADV: { uint8_t status; @@ -1090,65 +1100,6 @@ tBTM_STATUS BTM_WriteVoiceSettings(UINT16 settings) return (BTM_NO_RESOURCES); } -#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) -/******************************************************************************* -** -** Function BTM_EnableTestMode -** -** Description Send HCI the enable device under test command. -** -** Note: Controller can only be taken out of this mode by -** resetting the controller. -** -** Returns -** BTM_SUCCESS Command sent. -** BTM_NO_RESOURCES If out of resources to send the command. -** -** -*******************************************************************************/ -tBTM_STATUS BTM_EnableTestMode(void) -{ - UINT8 cond; - - BTM_TRACE_EVENT ("BTM: BTM_EnableTestMode"); - - /* set auto accept connection as this is needed during test mode */ - /* Allocate a buffer to hold HCI command */ - cond = HCI_DO_AUTO_ACCEPT_CONNECT; - if (!btsnd_hcic_set_event_filter(HCI_FILTER_CONNECTION_SETUP, - HCI_FILTER_COND_NEW_DEVICE, - &cond, sizeof(cond))) { - return (BTM_NO_RESOURCES); - } - - /* put device to connectable mode */ - if (BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW, - BTM_DEFAULT_CONN_INTERVAL) != BTM_SUCCESS) { - return BTM_NO_RESOURCES; - } - - /* put device to discoverable mode */ - if (BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW, - BTM_DEFAULT_DISC_INTERVAL) != BTM_SUCCESS) { - return BTM_NO_RESOURCES; - } - - /* mask off all of event from controller */ - hci_layer_get_interface()->transmit_command( - hci_packet_factory_get_interface()->make_set_event_mask((const bt_event_mask_t *)("\x00\x00\x00\x00\x00\x00\x00\x00")), - NULL, - NULL, - NULL); - - /* Send the HCI command */ - if (btsnd_hcic_enable_test_mode ()) { - return (BTM_SUCCESS); - } else { - return (BTM_NO_RESOURCES); - } -} -#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) - #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** diff --git a/components/bt/host/bluedroid/stack/btm/btm_inq.c b/components/bt/host/bluedroid/stack/btm/btm_inq.c index c74f2b4396..db93304a4e 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_inq.c +++ b/components/bt/host/bluedroid/stack/btm/btm_inq.c @@ -718,9 +718,6 @@ tBTM_STATUS BTM_CancelInquiry(void) { tBTM_STATUS status = BTM_SUCCESS; tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - UINT8 active_mode = p_inq->inq_active; -#endif BTM_TRACE_API ("BTM_CancelInquiry called\n"); /*** Make sure the device is ready ***/ @@ -745,23 +742,11 @@ tBTM_STATUS BTM_CancelInquiry(void) /* Initiate the cancel inquiry */ else { if (((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0) -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - && (active_mode & BTM_BR_INQUIRY_MASK) -#endif ) { if (!btsnd_hcic_inq_cancel()) { status = BTM_NO_RESOURCES; } } -#if BLE_INCLUDED == TRUE - if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - && (active_mode & BTM_BLE_INQ_ACTIVE_MASK) -#endif - ) { - btm_ble_stop_inquiry(); - } -#endif } /* Do not send the BUSY_LEVEL event yet. Wait for the cancel_complete event @@ -819,16 +804,6 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p /* Only one active inquiry is allowed in this implementation. Also do not allow an inquiry if the inquiry filter is being updated */ if (p_inq->inq_active || p_inq->inqfilt_active) { -#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) - /*check if LE observe is already running*/ - if (p_inq->scan_type == INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb != NULL) { - BTM_TRACE_API("BTM_StartInquiry: LE observe in progress"); - p_inq->scan_type = INQ_GENERAL; - p_inq->inq_active = BTM_INQUIRY_INACTIVE; - btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; - btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); - } else -#endif { return (BTM_BUSY); BTM_TRACE_API("BTM_StartInquiry: return BUSY\n"); @@ -852,13 +827,6 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p return (BTM_ILLEGAL_VALUE); } -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - if (p_inq->next_state == BTM_FINISH) { - return BTM_ILLEGAL_VALUE; - } -#endif - - /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */ p_inq->inqparms = *p_inqparms; @@ -870,85 +838,12 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p p_inq->inq_active = p_inqparms->mode; BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x\n", p_inq->inq_active); - - /* interleave scan minimal conditions */ -#if (BLE_INCLUDED==TRUE && (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)) - - /* check if both modes are present */ - if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) && (p_inqparms->mode & BTM_BR_INQUIRY_MASK)) { - BTM_TRACE_API("BTM:Interleave Inquiry Mode Set\n"); - p_inqparms->duration = p_inqparms->intl_duration[p_inq->next_state]; - p_inq->inqparms.duration = p_inqparms->duration; - } else { - BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x\n", p_inqparms->mode); - p_inq->next_state = BTM_NO_INTERLEAVING; - } -#endif - - - - /* start LE inquiry here if requested */ -#if BLE_INCLUDED == TRUE - if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - && (p_inq->next_state == BTM_BLE_ONE || p_inq->next_state == BTM_BLE_TWO || - p_inq->next_state == BTM_NO_INTERLEAVING) -#endif - ) - - { -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK); - BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x\n", - p_inqparms->duration, (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)); -#endif - if (!controller_get_interface()->supports_ble()) { - p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK; - status = BTM_ILLEGAL_VALUE; - } - /* BLE for now does not support filter condition for inquiry */ - else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK), - p_inqparms->duration)) != BTM_CMD_STARTED) { - BTM_TRACE_ERROR("Err Starting LE Inquiry.\n"); - p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK; - } -#if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE) - p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK; -#endif - -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - if (p_inq->next_state == BTM_NO_INTERLEAVING) { - p_inq->next_state = BTM_FINISH; - } else { - BTM_TRACE_API("BTM:Interleaving: started LE scan, Advancing to next state: %d\n", - p_inq->next_state + 1); - p_inq->next_state += 1; - } - /* reset next_state if status <> BTM_Started */ - if (status != BTM_CMD_STARTED) { - p_inq->next_state = BTM_BR_ONE; - } - - /* if interleave scan..return here */ - return status; -#endif - - - BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x\n", p_inqparms->mode); - } -#endif /* end of BLE_INCLUDED */ - /* we're done with this routine if BR/EDR inquiry is not desired. */ if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE) { return status; } /* BR/EDR inquiry portion */ -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - if ((p_inq->next_state == BTM_BR_ONE || p_inq->next_state == BTM_BR_TWO || - p_inq->next_state == BTM_NO_INTERLEAVING )) { - p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK); -#endif /* If a filter is specified, then save it for later and clear the current filter. The setting of the filter is done upon completion of clearing of the previous filter. @@ -977,25 +872,6 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p p_inq->state = BTM_INQ_INACTIVE_STATE; } -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - if (p_inq->next_state == BTM_NO_INTERLEAVING) { - p_inq->next_state = BTM_FINISH; - } else { - BTM_TRACE_API("BTM:Interleaving: Started BTM inq, Advancing to next state: %d\n", - p_inq->next_state + 1); - p_inq->next_state += 1; - } - } - if (status != BTM_CMD_STARTED) { - /* Some error beginning the scan process. - Reset the next_state parameter.. Do we need to reset the inq_active also? - */ - BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x\n", status); - p_inq->next_state = BTM_BR_ONE; - } -#endif - - return (status); } @@ -1210,6 +1086,7 @@ tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda) return (BTM_SUCCESS); } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_ReadInquiryRspTxPower @@ -1240,6 +1117,7 @@ tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb) return (BTM_CMD_STARTED); } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) /********************************************************************************* ********************************************************************************** @@ -1968,11 +1846,6 @@ void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode) /* BTM_TRACE_DEBUG("BTMINQ: Found devices, cancelling inquiry..."); */ btsnd_hcic_inq_cancel(); -#if BLE_INCLUDED == TRUE - if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0) { - btm_ble_stop_inquiry(); - } -#endif btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT); } /* Initialize flag to FALSE. This flag is set/used by application */ @@ -2053,27 +1926,10 @@ void btm_process_inq_complete (UINT8 status, UINT8 mode) tBTM_CMPL_CB *p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb; tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - /* inquiry inactive case happens when inquiry is cancelled. - Make mode 0 for no further inquiries from the current inquiry process - */ - if (status != HCI_SUCCESS || p_inq->next_state == BTM_FINISH || !p_inq->inq_active) { - /* re-initialize for next inquiry request */ - p_inq->next_state = BTM_BR_ONE; - /* make the mode 0 here */ - p_inq->inqparms.mode &= ~(p_inq->inqparms.mode); - - } -#endif - -#if (!defined(BTA_HOST_INTERLEAVE_SEARCH) || BTA_HOST_INTERLEAVE_SEARCH == FALSE) p_inq->inqparms.mode &= ~(mode); -#endif if (p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active) { /*end of LE observe*/ - p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL; - p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL; p_inq->scan_type = INQ_NONE; } @@ -2117,24 +1973,9 @@ void btm_process_inq_complete (UINT8 status, UINT8 mode) (p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info); } } -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - if (p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)) { - /* make inquiry inactive for next iteration */ - p_inq->inq_active = BTM_INQUIRY_INACTIVE; - /* call the inquiry again */ - BTM_StartInquiry(&p_inq->inqparms, p_inq->p_inq_results_cb, p_inq->p_inq_cmpl_cb); - } -#endif } if (p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL) { //this inquiry is complete p_inq->scan_type = INQ_NONE; -#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) - /* check if the LE observe is pending */ - if (p_inq->p_inq_ble_results_cb != NULL) { - BTM_TRACE_DEBUG("BTM Inq Compl: resuming a pending LE scan"); - BTM_BleObserve(1, 0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb); - } -#endif } #if (BTM_INQ_DEBUG == TRUE) BTM_TRACE_DEBUG ("inq_active:0x%x state:%d inqfilt_active:%d\n", @@ -2342,6 +2183,8 @@ void btm_inq_rmt_name_failed (void) btm_sec_rmt_name_request_complete (NULL, NULL, HCI_ERR_UNSPECIFIED); #endif ///SMP_INCLUDED == TRUE } + +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_read_linq_tx_power_complete @@ -2377,6 +2220,7 @@ void btm_read_linq_tx_power_complete(UINT8 *p) } } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_WriteEIR diff --git a/components/bt/host/bluedroid/stack/btm/btm_main.c b/components/bt/host/bluedroid/stack/btm/btm_main.c index b109e5395b..5543047786 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_main.c +++ b/components/bt/host/bluedroid/stack/btm/btm_main.c @@ -64,9 +64,12 @@ void btm_init (void) #endif /* #if BTM_DYNAMIC_MEMORY */ /* All fields are cleared; nonzero fields are reinitialized in appropriate function */ memset(&btm_cb, 0, sizeof(tBTM_CB)); +#if (CLASSIC_BT_INCLUDED == TRUE) btm_cb.page_queue = fixed_queue_new(QUEUE_SIZE_MAX); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (SMP_INCLUDED == TRUE) btm_cb.sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX); - +#endif // (SMP_INCLUDED == TRUE) #if defined(BTM_INITIAL_TRACE_LEVEL) btm_cb.trace_level = BTM_INITIAL_TRACE_LEVEL; #else @@ -86,7 +89,9 @@ void btm_init (void) #if BLE_INCLUDED == TRUE btm_ble_lock_init(); btm_ble_sem_init(); +#if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) btm_cb.addr_res_en = TRUE; +#endif // ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) #endif btm_sec_dev_init(); #if (BLE_50_FEATURE_SUPPORT == TRUE) @@ -110,8 +115,12 @@ void btm_init (void) *******************************************************************************/ void btm_free(void) { +#if (CLASSIC_BT_INCLUDED == TRUE) fixed_queue_free(btm_cb.page_queue, osi_free_func); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (SMP_INCLUDED == TRUE) fixed_queue_free(btm_cb.sec_pending_q, osi_free_func); +#endif // (SMP_INCLUDED == TRUE) btm_acl_free(); btm_sec_dev_free(); #if BTM_SCO_INCLUDED == TRUE @@ -151,7 +160,7 @@ uint8_t btm_ble_acl_active_count(void) return count; } - +#if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) // Address resolution status uint8_t btm_get_ble_addr_resolve_disable_status(void) { @@ -163,4 +172,5 @@ void btm_ble_addr_resolve_enable(bool enable) { btm_cb.addr_res_en = enable; } +#endif // ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) #endif /*BLE_INCLUDED*/ diff --git a/components/bt/host/bluedroid/stack/btm/btm_pm.c b/components/bt/host/bluedroid/stack/btm/btm_pm.c index de48a2dad6..9391976a4e 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_pm.c +++ b/components/bt/host/bluedroid/stack/btm/btm_pm.c @@ -45,6 +45,8 @@ //#include "bt_utils.h" //#include "osi/include/log.h" #include "osi/allocator.h" + +#if (CLASSIC_BT_INCLUDED == TRUE) /*****************************************************************************/ /* to handle different modes */ /*****************************************************************************/ @@ -820,9 +822,10 @@ void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode, U (*btm_cb.pm_reg_db[yy].cback)( p->remote_addr, mode, interval, hci_status); } } - +#if (CLASSIC_BT_INCLUDED == TRUE) /* If mode change was because of an active role switch or change link key */ btm_cont_rswitch(p, btm_find_dev(p->remote_addr), hci_status); +#endif // (CLASSIC_BT_INCLUDED == TRUE) } /******************************************************************************* @@ -901,7 +904,7 @@ BOOLEAN btm_pm_device_in_active_or_sniff_mode(void) return FALSE; } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_pm_device_in_scan_state @@ -930,7 +933,7 @@ BOOLEAN btm_pm_device_in_scan_state(void) return FALSE; } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_PM_ReadControllerState @@ -944,9 +947,13 @@ tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void) { if (TRUE == btm_pm_device_in_active_or_sniff_mode()) { return BTM_CONTRL_ACTIVE; - } else if (TRUE == btm_pm_device_in_scan_state()) { + } +#if (CLASSIC_BT_INCLUDED == TRUE) + else if (TRUE == btm_pm_device_in_scan_state()) { return BTM_CONTRL_SCAN; - } else { + } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + else { return BTM_CONTRL_IDLE; } } @@ -963,3 +970,5 @@ static const char *mode_to_string(tBTM_PM_MODE mode) } } #endif + +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/stack/btm/btm_sec.c b/components/bt/host/bluedroid/stack/btm/btm_sec.c index 35337e40a3..4dcfaffe52 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_sec.c +++ b/components/bt/host/bluedroid/stack/btm/btm_sec.c @@ -211,7 +211,7 @@ static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC * } return (FALSE); } -#endif ///SMP_INCLUDED == TRUE + /******************************************************************************* ** ** Function BTM_SecRegister @@ -274,6 +274,7 @@ BOOLEAN BTM_SecRegisterLinkKeyNotificationCallback (tBTM_LINK_KEY_CALLBACK *p_ca btm_cb.api.p_link_key_callback = p_callback; return TRUE; } +#endif ///SMP_INCLUDED == TRUE /******************************************************************************* ** @@ -410,6 +411,7 @@ void BTM_SetPinType (UINT8 pin_type, PIN_CODE pin_code, UINT8 pin_code_len) } #endif ///CLASSIC_BT_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_SetPairableMode @@ -455,6 +457,8 @@ void BTM_SetSecureConnectionsOnly (BOOLEAN secure_connections_only_mode) btm_cb.devcb.secure_connections_only = secure_connections_only_mode; btm_cb.security_mode = BTM_SEC_MODE_SC; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + #define BTM_NO_AVAIL_SEC_SERVICES ((UINT16) 0xffff) /******************************************************************************* @@ -2641,6 +2645,7 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o ** Returns void ** *******************************************************************************/ +#if (CLASSIC_BT_INCLUDED == TRUE) #if (SMP_INCLUDED == TRUE) void btm_sec_conn_req (UINT8 *bda, UINT8 *dc) { @@ -2701,7 +2706,7 @@ void btm_sec_conn_req (UINT8 *bda, UINT8 *dc) } } #endif ///SMP_INCLUDED == TRUE - +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_sec_bond_cancel_complete @@ -2778,10 +2783,12 @@ void btm_create_conn_cancel_complete (UINT8 *p, UINT16 evt_len) case HCI_ERR_CONNECTION_EXISTS: case HCI_ERR_NO_CONNECTION: default: +#if (SMP_INCLUDED == TRUE) /* Notify application of the error */ if (btm_cb.api.p_bond_cancel_cmpl_callback) { btm_cb.api.p_bond_cancel_cmpl_callback(BTM_ERR_PROCESSING); } +#endif // #if (SMP_INCLUDED == TRUE) break; } } @@ -3007,7 +3014,9 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete\n"); if (((p_bd_addr == NULL) && !BTM_ACL_IS_CONNECTED(btm_cb.connecting_bda)) || ((p_bd_addr != NULL) && !BTM_ACL_IS_CONNECTED(p_bd_addr))) { +#if (CLASSIC_BT_INCLUDED == TRUE) btm_acl_resubmit_page(); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } /* If remote name request failed, p_bd_addr is null and we need to search */ @@ -4303,8 +4312,9 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) BOOLEAN is_pairing_device = FALSE; tACL_CONN *p_acl_cb; UINT8 bit_shift = 0; - +#if (CLASSIC_BT_INCLUDED == TRUE) btm_acl_resubmit_page(); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda); @@ -4545,10 +4555,11 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) /* commands events and data at the same time. */ /* Set the packet types to the default allowed by the device */ btm_set_packet_types (p_acl_cb, btm_cb.btm_acl_pkt_types_supported); - +#if (CLASSIC_BT_INCLUDED == TRUE) if (btm_cb.btm_def_link_policy) { BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif } btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, BT_TRANSPORT_BR_EDR); @@ -4635,10 +4646,10 @@ BOOLEAN btm_sec_disconnected (UINT16 handle, UINT8 reason) tBTM_SEC_CALLBACK *p_callback = NULL; tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; +#if (CLASSIC_BT_INCLUDED == TRUE) /* If page was delayed for disc complete, can do it now */ btm_cb.discing = FALSE; -#if (CLASSIC_BT_INCLUDED == TRUE) btm_acl_resubmit_page(); #endif diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h index de25c6fa3e..76b34bcefe 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h @@ -331,26 +331,27 @@ typedef struct { ** BLE Inquiry *****************************************************/ tBTM_BLE_INQ_CB inq_var; - - /* observer callback and timer */ - tBTM_INQ_RESULTS_CB *p_obs_results_cb; - tBTM_CMPL_CB *p_obs_cmpl_cb; +#if (BLE_42_SCAN_EN == TRUE) +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + // /* observer callback and timer */ tBTM_INQ_DIS_CB *p_obs_discard_cb; - TIMER_LIST_ENT obs_timer_ent; - +#endif // (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) /* scan callback and timer */ tBTM_INQ_RESULTS_CB *p_scan_results_cb; tBTM_CMPL_CB *p_scan_cmpl_cb; TIMER_LIST_ENT scan_timer_ent; -#if (BLE_42_SCAN_EN == TRUE) struct pkt_queue *adv_rpt_queue; struct osi_event *adv_rpt_ready; #endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_GATT_BGCONN == TRUE) /* background connection procedure cb value */ tBTM_BLE_CONN_TYPE bg_conn_type; +#endif // (BLE_GATT_BGCONN == TRUE) UINT32 scan_int; UINT32 scan_win; +#if (BLE_GATT_BGCONN == TRUE) tBTM_BLE_SEL_CBACK *p_select_cback; +#endif // (BLE_GATT_BGCONN == TRUE) /* white list information */ UINT8 white_list_avail_size; #if (BLE_50_EXTEND_SYNC_EN == TRUE) @@ -380,12 +381,18 @@ typedef struct { tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM]; +#if (BLE_TOPOLOGY_CHECK == TRUE) /* current BLE link state */ tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */ UINT8 link_count[2]; /* total link count master and slave*/ +#endif // (BLE_TOPOLOGY_CHECK == TRUE) +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) tBTM_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK *update_exceptional_list_cmp_cb; +#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) +#if (BLE_VENDOR_HCI_EN == TRUE) tBTM_SET_CSA_SUPPORT_CMPL_CBACK *set_csa_support_cmpl_cb; tBTM_SET_VENDOR_EVT_MASK_CBACK *set_vendor_evt_mask_cmpl_cb; +#endif // (BLE_VENDOR_HCI_EN == TRUE) } tBTM_BLE_CB; #ifdef __cplusplus @@ -406,12 +413,9 @@ BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda); tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode); tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode); -tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration); void btm_ble_stop_scan(void); void btm_clear_all_pending_le_entry(void); -BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int, UINT32 scan_win, UINT8 addr_type_own, UINT8 scan_filter_policy); -void btm_ble_stop_inquiry(void); void btm_ble_init (void); void btm_ble_free (void); void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched); @@ -470,11 +474,11 @@ void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len); void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len); void btm_ble_white_list_init(UINT8 white_list_size); -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) /* background connection function */ BOOLEAN btm_ble_suspend_bg_conn(void); BOOLEAN btm_ble_resume_bg_conn(void); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) void btm_ble_initiate_select_conn(BD_ADDR bda); BOOLEAN btm_ble_start_auto_conn(BOOLEAN start); @@ -518,23 +522,13 @@ void btm_ble_add_default_entry_to_resolving_list(void); void btm_ble_set_privacy_mode_complete(UINT8 *p, UINT16 evt_len); #endif -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst); -void btm_ble_multi_adv_init(void); -void *btm_ble_multi_adv_get_ref(UINT8 inst_id); -void btm_ble_multi_adv_cleanup(void); -void btm_ble_multi_adv_reenable(UINT8 inst_id); -void btm_ble_multi_adv_enb_privacy(BOOLEAN enable); -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) char btm_ble_map_adv_tx_power(int tx_power_index); -void btm_ble_batchscan_init(void); -void btm_ble_batchscan_cleanup(void); -void btm_ble_adv_filter_init(void); -void btm_ble_adv_filter_cleanup(void); +#if (BLE_TOPOLOGY_CHECK == TRUE) BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request); BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state); BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state); tBTM_BLE_STATE_MASK btm_ble_get_topology_mask(void); +#endif // (BLE_TOPOLOGY_CHECK == TRUE) #if BTM_BLE_CONFORMANCE_TESTING == TRUE void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc); @@ -606,6 +600,21 @@ void btm_ble_transmit_power_report_evt(tBTM_BLE_TRANS_POWER_REPORT_EVT *params); #if (BLE_FEAT_CONN_SUBRATING == TRUE) void btm_ble_subrate_change_evt(tBTM_BLE_SUBRATE_CHANGE_EVT *params); #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +void btm_ble_pa_subevt_data_req_evt(tBTM_BLE_PA_SUBEVT_DATA_REQ_EVT *params); +void btm_ble_pa_rsp_rpt_evt(tBTM_BLE_PA_RSP_REPORT_EVT *params); +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void btm_ble_cs_read_remote_supp_caps_cmpl_evt(tBTM_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT *cs_read_remote_supp_caps); +void btm_ble_cs_read_remote_fae_tab_cmpl_evt(tBTM_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT *cs_read_remote_fae_tab); +void btm_ble_cs_securuty_enable_cmpl_evt(tBTM_BLE_CS_SEC_ENABLE_CMPL_EVT *cs_security_enable); +void btm_ble_cs_config_cmpl_evt(tBTM_BLE_CS_CONFIG_CMPL_EVT *config_cmpl); +void btm_ble_cs_proc_enable_cmpl_evt(tBTM_BLE_CS_PROC_ENABLE_CMPL_EVT *proc_en); +void btm_ble_cs_subevt_result_evt(tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT *subevt_result); +void btm_ble_cs_subevt_continue_result_evt(tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT *subevt_continue_result); +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + /* #ifdef __cplusplus diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_int.h index e1036b9174..25a45d2e88 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_int.h @@ -140,7 +140,10 @@ UINT8 legacy_auth_state; #define BTM_ACL_SWKEY_STATE_SWITCHING 3 #define BTM_ACL_SWKEY_STATE_ENCRYPTION_ON 4 #define BTM_ACL_SWKEY_STATE_IN_PROGRESS 5 + +#if (CLASSIC_BT_INCLUDED == TRUE) UINT8 switch_role_state; +#endif // (CLASSIC_BT_INCLUDED == TRUE) #define BTM_ACL_ENCRYPT_STATE_IDLE 0 #define BTM_ACL_ENCRYPT_STATE_ENCRYPT_OFF 1 /* encryption turning off */ @@ -180,40 +183,49 @@ typedef struct { tBTM_DEV_STATUS_CB *p_dev_status_cb; /* Device status change callback */ tBTM_VS_EVT_CB *p_vend_spec_cb[BTM_MAX_VSE_CALLBACKS]; /* Register for vendor specific events */ +#if (CLASSIC_BT_INCLUDED == TRUE) tBTM_CMPL_CB *p_stored_link_key_cmpl_cb; /* Read/Write/Delete stored link key */ +#endif // (CLASSIC_BT_INCLUDED == TRUE) TIMER_LIST_ENT reset_timer; tBTM_CMPL_CB *p_reset_cmpl_cb; +#if (CLASSIC_BT_INCLUDED == TRUE) TIMER_LIST_ENT rln_timer; tBTM_CMPL_CB *p_rln_cmpl_cb; /* Callback function to be called when */ +#endif // (CLASSIC_BT_INCLUDED == TRUE) + /* read local name function complete */ TIMER_LIST_ENT rssi_timer; tBTM_CMPL_CB *p_rssi_cmpl_cb; /* Callback function to be called when */ /* read rssi function completes */ - +#if BLE_INCLUDED == TRUE tBTM_CMPL_CB *p_ble_ch_map_cmpl_cb; /* Callback function to be called when */ +#endif // #if BLE_INCLUDED == TRUE /* read channel map function completes */ - +#if (CLASSIC_BT_INCLUDED == TRUE) TIMER_LIST_ENT lnk_quality_timer; tBTM_CMPL_CB *p_lnk_qual_cmpl_cb;/* Callback function to be called when */ +#endif // (CLASSIC_BT_INCLUDED == TRUE) + +#if (CLASSIC_BT_INCLUDED == TRUE) /* read link quality function completes */ TIMER_LIST_ENT txpwer_timer; tBTM_CMPL_CB *p_txpwer_cmpl_cb; /* Callback function to be called when */ -/* read inq tx power function completes */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +/* read inq tx power function completes */ +#if (CLASSIC_BT_INCLUDED == TRUE) TIMER_LIST_ENT qossu_timer; tBTM_CMPL_CB *p_qossu_cmpl_cb; /* Callback function to be called when */ /* qos setup function completes */ +#endif // (CLASSIC_BT_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) tBTM_ROLE_SWITCH_CMPL switch_role_ref_data; tBTM_CMPL_CB *p_switch_role_cb; /* Callback function to be called when */ /* requested switch role is completed */ - -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -TIMER_LIST_ENT tx_power_timer; -tBTM_CMPL_CB *p_tx_power_cmpl_cb;/* Callback function to be called */ -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if CLASSIC_BT_INCLUDED == TRUE TIMER_LIST_ENT afh_channels_timer; @@ -265,10 +277,11 @@ UINT32 test_local_sign_cntr; #endif #endif /* BLE_INCLUDED */ - tBTM_IO_CAP loc_io_caps; /* IO capability of the local device */ +#if (SMP_INCLUDED == TRUE) tBTM_AUTH_REQ loc_auth_req; /* the auth_req flag */ BOOLEAN secure_connections_only; /* Rejects service level 0 connections if */ +#endif // #if (SMP_INCLUDED == TRUE) /* itself or peer device doesn't support */ /* secure connections */ } tBTM_DEVCB; @@ -347,8 +360,6 @@ typedef struct { tBTM_CMPL_CB *p_inq_cmpl_cb; tBTM_INQ_RESULTS_CB *p_inq_results_cb; - tBTM_CMPL_CB *p_inq_ble_cmpl_cb; /*completion callback exclusively for LE Observe*/ - tBTM_INQ_RESULTS_CB *p_inq_ble_results_cb;/*results callback exclusively for LE observe*/ tBTM_CMPL_CB *p_inqfilter_cmpl_cb; /* Called (if not NULL) after inquiry filter completed */ UINT32 inq_counter; /* Counter incremented each time an inquiry completes */ /* Used for determining whether or not duplicate devices */ @@ -378,9 +389,6 @@ typedef struct { UINT8 state; /* Current state that the inquiry process is in */ UINT8 inq_active; /* Bit Mask indicating type of inquiry is active */ BOOLEAN no_inc_ssp; /* TRUE, to stop inquiry on incoming SSP */ -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - btm_inq_state next_state; /*interleaving state to determine next mode to be inquired*/ -#endif } tBTM_INQUIRY_VAR_ST; /* The MSB of the clock offset field indicates that the offset is valid if TRUE */ @@ -702,6 +710,9 @@ struct tBTM_SEC_DEV_REC{ #if (BLE_50_FEATURE_SUPPORT == TRUE) tBTM_EXT_CONN_PARAMS ext_conn_params; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + BOOLEAN is_pawr_synced; + UINT8 adv_handle; + UINT8 subevent; #endif // btla-specific ++ @@ -860,8 +871,9 @@ typedef struct { list_t *p_acl_db_list; #if (CLASSIC_BT_INCLUDED == TRUE) UINT8 btm_scn[BTM_MAX_SCN]; /* current SCNs: TRUE if SCN is in use */ -#endif ///CLASSIC_BT_INCLUDED == TRUE + UINT16 btm_def_link_policy; +#endif ///CLASSIC_BT_INCLUDED == TRUE UINT16 btm_def_link_super_tout; tBTM_ACL_LINK_STAT_CB *p_acl_link_stat_cb; /* Callback for when ACL link related events came */ @@ -872,11 +884,12 @@ typedef struct { /**************************************************** ** Power Management ****************************************************/ +#if (CLASSIC_BT_INCLUDED == TRUE) list_t *p_pm_mode_db_list; tBTM_PM_RCB pm_reg_db[BTM_MAX_PM_RECORDS + 1]; /* per application/module */ UINT16 pm_pend_link_hdl; /* the index of acl_db, which has a pending PM cmd */ UINT8 pm_pend_id; /* the id pf the module, which has a pending PM cmd */ - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /***************************************************** ** Device control *****************************************************/ @@ -887,18 +900,22 @@ typedef struct { *****************************************************/ #if (BLE_INCLUDED == TRUE) tBTM_BLE_CB ble_ctr_cb; - +#if (SMP_INCLUDED == TRUE) UINT16 enc_handle; BT_OCTET8 enc_rand; /* received rand value from LTK request*/ UINT16 ediv; /* received ediv value from LTK request */ UINT8 key_size; - tBTM_BLE_VSC_CB cmn_ble_vsc_cb; +#endif // (SMP_INCLUDED == TRUE) +#if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) BOOLEAN addr_res_en; /* internal use for test: address resolution enable/disable */ +#endif // ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) #endif /* Packet types supported by the local device */ UINT16 btm_acl_pkt_types_supported; +#if (CLASSIC_BT_INCLUDED == TRUE) UINT16 btm_sco_pkt_types_supported; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /***************************************************** @@ -912,7 +929,7 @@ typedef struct { #if BTM_SCO_INCLUDED == TRUE tSCO_CB sco_cb; #endif - +#if (SMP_INCLUDED == TRUE) /***************************************************** ** Security Management *****************************************************/ @@ -921,18 +938,22 @@ typedef struct { #define BTM_SEC_MAX_RMT_NAME_CALLBACKS 2 tBTM_RMT_NAME_CALLBACK *p_rmt_name_callback[BTM_SEC_MAX_RMT_NAME_CALLBACKS]; +#endif // #if (SMP_INCLUDED == TRUE) #if (SMP_INCLUDED == TRUE) tBTM_SEC_DEV_REC *p_collided_dev_rec; #endif ///SMP_INCLUDED == TRUE + UINT8 security_mode; + UINT32 dev_rec_count; /* Counter used for device record timestamp */ +#if (SMP_INCLUDED == TRUE) TIMER_LIST_ENT sec_collision_tle; UINT32 collision_start_time; UINT32 max_collision_delay; - UINT32 dev_rec_count; /* Counter used for device record timestamp */ - UINT8 security_mode; BOOLEAN pairing_disabled; BOOLEAN connect_only_paired; BOOLEAN security_mode_changed; /* mode changed during bonding */ BOOLEAN sec_req_pending; /* TRUE if a request is pending */ +#endif // #if (SMP_INCLUDED == TRUE) + #if (CLASSIC_BT_INCLUDED == TRUE) BOOLEAN pin_type_changed; /* pin type changed during bonding */ #endif ///CLASSIC_BT_INCLUDED == TRUE @@ -949,10 +970,12 @@ typedef struct { UINT8 disc_reason; /* for legacy devices */ UINT16 disc_handle; /* for legacy devices */ #endif ///CLASSIC_BT_INCLUDED == TRUE +#if (SMP_INCLUDED == TRUE) tBTM_PAIRING_STATE pairing_state; /* The current pairing state */ UINT8 pairing_flags; /* The current pairing flags */ BD_ADDR pairing_bda; /* The device currently pairing */ TIMER_LIST_ENT pairing_tle; /* Timer for pairing process */ +#endif // #if (SMP_INCLUDED == TRUE) #endif ///SMP_INCLUDED == TRUE #if SMP_INCLUDED == TRUE || CLASSIC_BT_INCLUDED == TRUE @@ -968,12 +991,18 @@ typedef struct { UINT8 acl_disc_reason; UINT8 trace_level; UINT8 busy_level; /* the current busy level */ +#if (CLASSIC_BT_INCLUDED == TRUE) BOOLEAN is_paging; /* TRUE, if paging is in progress */ BOOLEAN is_inquiry; /* TRUE, if inquiry is in progress */ fixed_queue_t *page_queue; BOOLEAN paging; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) +#if (SMP_INCLUDED == TRUE && CLASSIC_BT_INCLUDED == TRUE) BOOLEAN discing; +#endif // (SMP_INCLUDED == TRUE && CLASSIC_BT_INCLUDED == TRUE) +#if (SMP_INCLUDED == TRUE) fixed_queue_t *sec_pending_q; /* pending sequrity requests in tBTM_SEC_QUEUE_ENTRY format */ +#endif // (SMP_INCLUDED == TRUE) #if (!defined(BT_TRACE_VERBOSE) || (BT_TRACE_VERBOSE == FALSE)) char state_temp_buffer[BTM_STATE_BUFFER_SIZE]; #endif @@ -1134,6 +1163,14 @@ void btm_read_remote_trans_pwr_level_cmpl(UINT8 status); void btm_subrate_req_cmd_status(UINT8 status); #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void btm_ble_cs_read_local_supp_caps_cmpl_evt(UINT8 *p); +void btm_ble_cs_read_remote_supp_caps_cmd_status(UINT8 status); +void btm_ble_cs_security_enable_cmd_status(UINT8 status); +void btm_ble_cs_read_remote_fae_table_cmd_status(UINT8 status); +void btm_ble_cs_update_config_cmd_status(UINT8 status, BOOLEAN create); +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + /* Internal functions provided by btm_sco.c ******************************************** */ diff --git a/components/bt/host/bluedroid/stack/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index 2ff53852e0..75b62e5b59 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -52,6 +52,17 @@ extern void btm_process_cancel_complete(UINT8 status, UINT8 mode); extern void btm_ble_test_command_complete(UINT8 *p); +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +// BLE Channel Sounding parameter validation macros per BLE spec +#define BTM_BLE_CS_MAX_STEPS_REPORTED 0xA0 // Range: 0x00 to 0xA0 (0 to 160) +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +// BLE CTE parameter validation macros per BLE spec +#define BTM_BLE_CTE_MAX_SAMPLE_COUNT 0x52 // Maximum sample count per BLE spec: 0x52 (82) +#endif // (BLE_FEAT_CTE_EN == TRUE) + + /********************************************************************************/ /* L O C A L F U N C T I O N P R O T O T Y P E S */ /********************************************************************************/ @@ -161,8 +172,8 @@ static void btu_ble_phy_update_complete_evt(UINT8 *p); static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len); #endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) #if (BLE_50_EXTEND_SYNC_EN == TRUE) -static void btu_ble_periodic_adv_sync_establish_evt(UINT8 *p); -static void btu_ble_periodic_adv_report_evt(UINT8 *p, UINT8 evt_len); +static void btu_ble_periodic_adv_sync_establish_evt(UINT8 *p, bool v2_evt); +static void btu_ble_periodic_adv_report_evt(UINT8 *p, UINT8 evt_len, bool v2_evt); static void btu_ble_periodic_adv_sync_lost_evt(UINT8 *p); #endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #if (BLE_50_EXTEND_SCAN_EN == TRUE) @@ -202,7 +213,7 @@ static void btu_ble_accept_cis_req_cmd_status(UINT8 status); static void btu_ble_cis_request_evt(UINT8 *p); #endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) #if (BLE_FEAT_ISO_CIG_EN == TRUE) -static void btu_ble_cis_established_evt(UINT8 *p); +static void btu_ble_cis_established_evt(UINT8 *p, bool v2_evt); static void btu_ble_cis_disconnected(UINT16 handle, UINT8 reason); #endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) @@ -228,6 +239,21 @@ static void btu_ble_transmit_power_report_evt(UINT8 *p); static void btu_ble_subrate_change_evt(UINT8 *p); #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +static void btu_ble_pa_subevt_data_request_evt(UINT8 *p); +static void btu_ble_pa_response_report_evt(UINT8 *p); +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +static void btu_ble_cs_read_remote_supp_caps_evt(UINT8 *p); +static void btu_ble_cs_read_remote_fae_tab_evt(UINT8 *p); +static void btu_ble_cs_security_enable_cmpl_evt(UINT8 *p); +static void btu_ble_cs_config_cmpl_evt(UINT8 *p); +static void btu_ble_cs_proc_enable_cmpl_evt(UINT8 *p); +static void btu_ble_cs_subevt_result_evt(UINT8 *p); +static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p); +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + #if (BLE_42_ADV_EN == TRUE) extern osi_sem_t adv_enable_sem; extern osi_sem_t adv_data_sem; @@ -493,10 +519,16 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) #if (BLE_50_EXTEND_SYNC_EN == TRUE) case HCI_BLE_PERIOD_ADV_SYNC_ESTAB_EVT: - btu_ble_periodic_adv_sync_establish_evt(p); + btu_ble_periodic_adv_sync_establish_evt(p, false); + break; + case HCI_BLE_PERIOD_ADV_SYNC_ESTAB_EVT_V2: + btu_ble_periodic_adv_sync_establish_evt(p, true); break; case HCI_BLE_PERIOD_ADV_REPORT_EVT: - btu_ble_periodic_adv_report_evt(p, hci_evt_len); + btu_ble_periodic_adv_report_evt(p, hci_evt_len, false); + break; + case HCI_BLE_PERIOD_ADV_REPORT_EVT_V2: + btu_ble_periodic_adv_report_evt(p, hci_evt_len, true); break; case HCI_BLE_PERIOD_ADV_SYNC_LOST_EVT: btu_ble_periodic_adv_sync_lost_evt(p); @@ -527,8 +559,10 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_CIG_EN == TRUE) case HCI_BLE_CIS_ESTABLISHED_V1_EVT: + btu_ble_cis_established_evt(p, false); + break; case HCI_BLE_CIS_ESTABLISHED_V2_EVT: - btu_ble_cis_established_evt(p); + btu_ble_cis_established_evt(p, true); break; #endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) @@ -586,6 +620,37 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) btu_ble_subrate_change_evt(p); break; #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + case HCI_BLE_PA_SUBEVT_DATA_REQUEST_EVT: + btu_ble_pa_subevt_data_request_evt(p); + break; + case HCI_BLE_PA_RESPONSE_REPORT_EVT: + btu_ble_pa_response_report_evt(p); + break; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + case HCI_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT: + btu_ble_cs_read_remote_supp_caps_evt(p); + break; + case HCI_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT: + btu_ble_cs_read_remote_fae_tab_evt(p); + break; + case HCI_BLE_CS_SECURITY_ENABLE_CMPL_EVT: + btu_ble_cs_security_enable_cmpl_evt(p); + break; + case HCI_BLE_CS_CONFIG_CMPL_EVT: + btu_ble_cs_config_cmpl_evt(p); + break; + case HCI_BLE_CS_PROC_ENABLE_CMPL_EVT: + btu_ble_cs_proc_enable_cmpl_evt(p); + break; + case HCI_BLE_CS_SUBEVENT_RESULT_EVT: + btu_ble_cs_subevt_result_evt(p); + break; + case HCI_BLE_CS_SUBEVENT_RESULT_CONTINUE_EVT: + btu_ble_cs_subevt_result_continue_evt(p); + break; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) } break; #endif /* BLE_INCLUDED */ @@ -960,8 +1025,9 @@ static void btu_hcif_encryption_change_evt (UINT8 *p) STREAM_TO_UINT8 (status, p); STREAM_TO_UINT16 (handle, p); STREAM_TO_UINT8 (encr_enable, p); - +#if (CLASSIC_BT_INCLUDED == TRUE) btm_acl_encrypt_change (handle, status, encr_enable); +#endif // (CLASSIC_BT_INCLUDED == TRUE) btm_sec_encrypt_change (handle, status, encr_enable); } #endif ///SMP_INCLUDED == TRUE @@ -1146,22 +1212,25 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l break; case HCI_GET_LINK_QUALITY: +#if (CLASSIC_BT_INCLUDED == TRUE) btm_read_link_quality_complete (p); +#endif // (CLASSIC_BT_INCLUDED == TRUE) break; #endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_READ_LOCAL_NAME: +#if (CLASSIC_BT_INCLUDED == TRUE) btm_read_local_name_complete (p, evt_len); +#endif // (CLASSIC_BT_INCLUDED == TRUE) break; case HCI_READ_RSSI: btm_read_rssi_complete (p, evt_len); break; case HCI_BLE_READ_CHNL_MAP: +#if BLE_INCLUDED == TRUE btm_read_channel_map_complete (p); +#endif // #if BLE_INCLUDED == TRUE break; case HCI_READ_TRANSMIT_POWER_LEVEL: -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) - btm_read_tx_power_complete(p, evt_len, FALSE); -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) break; #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_CREATE_CONNECTION_CANCEL: @@ -1241,9 +1310,6 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l break; case HCI_BLE_READ_ADV_CHNL_TX_POWER: -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) - btm_read_tx_power_complete(p, evt_len, TRUE); -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) break; #if (BLE_42_ADV_EN == TRUE) case HCI_BLE_WRITE_ADV_ENABLE: @@ -1390,7 +1456,11 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l btm_enh_read_trans_pwr_level_cmpl_evt(p); break; #endif //#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) - +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + case HCI_BLE_CS_READ_LOCAL_SUPP_CAPS: + btm_ble_cs_read_local_supp_caps_cmpl_evt(p); + break; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) #endif /* (BLE_INCLUDED == TRUE) */ default: { @@ -1598,6 +1668,23 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c btm_subrate_req_cmd_status(status); break; #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + case HCI_BLE_CS_READ_REMOTE_SUPP_CAPS: + btm_ble_cs_read_remote_supp_caps_cmd_status(status); + break; + case HCI_BLE_CS_SECURITY_ENABLE: + btm_ble_cs_security_enable_cmd_status(status); + break; + case HCI_BLE_CS_READ_REMOTE_FAE_TABLE: + btm_ble_cs_read_remote_fae_table_cmd_status(status); + break; + case HCI_BLE_CS_CREATE_CONFIG: + btm_ble_cs_update_config_cmd_status(status, true); + break; + case HCI_BLE_CS_REMOVE_CONFIG: + btm_ble_cs_update_config_cmd_status(status, false); + break; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) default: /* If command failed to start, we may need to tell BTM */ if (status != HCI_SUCCESS) { @@ -1616,13 +1703,16 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c break; case HCI_QOS_SETUP_COMP_EVT: + #if (CLASSIC_BT_INCLUDED == TRUE) /* Tell qos setup that we are done */ btm_qos_setup_complete(status, 0, NULL); + #endif // (CLASSIC_BT_INCLUDED == TRUE) break; case HCI_SWITCH_ROLE: /* Tell BTM that the command failed */ /* read bd addr out of stored command */ + #if (CLASSIC_BT_INCLUDED == TRUE) if (p_cmd != NULL) { p_cmd++; STREAM_TO_BDADDR (bd_addr, p_cmd); @@ -1631,6 +1721,7 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c btm_acl_role_changed(status, NULL, BTM_ROLE_UNDEFINED); } l2c_link_role_changed (NULL, BTM_ROLE_UNDEFINED, HCI_ERR_COMMAND_DISALLOWED); + #endif // (CLASSIC_BT_INCLUDED == TRUE) break; case HCI_CREATE_CONNECTION: @@ -2540,7 +2631,7 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len) #endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) #if (BLE_50_EXTEND_SYNC_EN == TRUE) -static void btu_ble_periodic_adv_sync_establish_evt(UINT8 *p) +static void btu_ble_periodic_adv_sync_establish_evt(UINT8 *p, bool v2_evt) { tBTM_BLE_PERIOD_ADV_SYNC_ESTAB sync_estab = {0}; @@ -2557,15 +2648,24 @@ static void btu_ble_periodic_adv_sync_establish_evt(UINT8 *p) STREAM_TO_UINT8(sync_estab.adv_phy, p); STREAM_TO_UINT16(sync_estab.period_adv_interval, p); STREAM_TO_UINT8(sync_estab.adv_clk_accuracy, p); +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + if (v2_evt) { + STREAM_TO_UINT8(sync_estab.num_subevt, p); + STREAM_TO_UINT8(sync_estab.subevt_interval, p); + STREAM_TO_UINT8(sync_estab.rsp_slot_delay, p); + STREAM_TO_UINT8(sync_estab.rsp_slot_spacing, p); + } +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) btm_ble_periodic_adv_sync_establish_evt(&sync_estab); } -static void btu_ble_periodic_adv_report_evt(UINT8 *p, UINT8 evt_len) +static void btu_ble_periodic_adv_report_evt(UINT8 *p, UINT8 evt_len, bool v2_evt) { tBTM_PERIOD_ADV_REPORT adv_report = {0}; /* This parameter is intended to be used in a future feature. */ UINT8 unused = 0; + UINT8 min_len = MIN_BLE_PERIODIC_ADV_REPORT_LEN; if (!p) { HCI_TRACE_ERROR("%s, Invalid params.", __func__); @@ -2581,10 +2681,17 @@ static void btu_ble_periodic_adv_report_evt(UINT8 *p, UINT8 evt_len) STREAM_TO_UINT8(adv_report.tx_power, p); STREAM_TO_UINT8(adv_report.rssi, p); STREAM_TO_UINT8(adv_report.cte_type, p); +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + if (v2_evt) { + STREAM_TO_UINT16(adv_report.periodic_evt_cnt, p); + STREAM_TO_UINT8(adv_report.subevt, p); + min_len += 3; + } +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) STREAM_TO_UINT8(adv_report.data_status, p); STREAM_TO_UINT8(adv_report.data_length, p); - if ((evt_len - MIN_BLE_PERIODIC_ADV_REPORT_LEN) != adv_report.data_length) { + if ((evt_len - min_len) != adv_report.data_length) { HCI_TRACE_ERROR("%s, Invalid ev_len = %d is less than adv len = %d", __func__, evt_len, adv_report.data_length); return; } @@ -2742,7 +2849,7 @@ static void btu_ble_cis_disconnected(UINT16 handle, UINT8 reason) btm_ble_cis_disconnected_evt(&cis_disconnected_evt); } -static void btu_ble_cis_established_evt(UINT8 *p) +static void btu_ble_cis_established_evt(UINT8 *p, bool v2_evt) { HCI_TRACE_DEBUG("%s", __func__); tBTM_BLE_CIS_ESTABLISHED_CMPL cis_estab_evt = {0}; @@ -2769,12 +2876,14 @@ static void btu_ble_cis_established_evt(UINT8 *p) STREAM_TO_UINT16(cis_estab_evt.max_pdu_p_to_c, p); STREAM_TO_UINT16(cis_estab_evt.iso_interval, p); #if (BLE_FEAT_ISO_60_EN == TRUE) - STREAM_TO_UINT24(cis_estab_evt.sub_interval, p); - STREAM_TO_UINT16(cis_estab_evt.max_sdu_c_to_p, p); - STREAM_TO_UINT16(cis_estab_evt.max_sdu_p_to_c, p); - STREAM_TO_UINT24(cis_estab_evt.sdu_int_c_to_p, p); - STREAM_TO_UINT24(cis_estab_evt.sdu_int_p_to_c, p); - STREAM_TO_UINT8(cis_estab_evt.framing, p); + if (v2_evt) { + STREAM_TO_UINT24(cis_estab_evt.sub_interval, p); + STREAM_TO_UINT16(cis_estab_evt.max_sdu_c_to_p, p); + STREAM_TO_UINT16(cis_estab_evt.max_sdu_p_to_c, p); + STREAM_TO_UINT24(cis_estab_evt.sdu_int_c_to_p, p); + STREAM_TO_UINT24(cis_estab_evt.sdu_int_p_to_c, p); + STREAM_TO_UINT8(cis_estab_evt.framing, p); + } #endif // #if (BLE_FEAT_ISO_60_EN == TRUE) btm_ble_cis_established_evt(&cis_estab_evt); @@ -2807,6 +2916,7 @@ void btu_ble_create_big_cmd_status(UINT8 status) { if (status != HCI_SUCCESS) { tBTM_BLE_BIG_CREATE_CMPL big_cmpl = {0}; + big_cmpl.status = status; btm_ble_big_create_cmpl_evt(&big_cmpl); } } @@ -2815,6 +2925,7 @@ static void btu_ble_big_create_complete_evt(UINT8 *p) { HCI_TRACE_DEBUG("%s", __func__); tBTM_BLE_BIG_CREATE_CMPL big_cmpl = {0}; + UINT8 num_bis; if (!p) { HCI_TRACE_ERROR("%s, Invalid params.", __func__); @@ -2832,8 +2943,16 @@ static void btu_ble_big_create_complete_evt(UINT8 *p) STREAM_TO_UINT8(big_cmpl.irc, p); STREAM_TO_UINT16(big_cmpl.max_pdu, p); STREAM_TO_UINT16(big_cmpl.iso_interval, p); - STREAM_TO_UINT8(big_cmpl.num_bis, p); - for (uint8_t i = 0; i < big_cmpl.num_bis; i++) + STREAM_TO_UINT8(num_bis, p); + + // Validate num_bis to prevent buffer overflow + if (num_bis > BLE_ISO_BIS_MAX_COUNT) { + HCI_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); + num_bis = BLE_ISO_BIS_MAX_COUNT; + } + big_cmpl.num_bis = num_bis; + + for (uint8_t i = 0; i < num_bis; i++) { STREAM_TO_UINT16(big_cmpl.bis_handle[i], p); // only 12 bits meaningful @@ -2882,6 +3001,7 @@ void btu_ble_create_big_sync_cmd_status(UINT8 status) static void btu_ble_big_sync_establish_evt(UINT8 *p) { tBTM_BLE_BIG_SYNC_ESTAB_CMPL big_estb = {0}; + UINT8 num_bis; if (!p) { HCI_TRACE_ERROR("%s, Invalid params.", __func__); @@ -2897,8 +3017,16 @@ static void btu_ble_big_sync_establish_evt(UINT8 *p) STREAM_TO_UINT8(big_estb.irc, p); STREAM_TO_UINT16(big_estb.max_pdu, p); STREAM_TO_UINT16(big_estb.iso_interval, p); - STREAM_TO_UINT8(big_estb.num_bis, p); - for (uint8_t i = 0; i < big_estb.num_bis; i++) + STREAM_TO_UINT8(num_bis, p); + + // Validate num_bis to prevent buffer overflow + if (num_bis > BLE_ISO_BIS_MAX_COUNT) { + HCI_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT); + num_bis = BLE_ISO_BIS_MAX_COUNT; + } + big_estb.num_bis = num_bis; + + for (uint8_t i = 0; i < num_bis; i++) { STREAM_TO_UINT16(big_estb.bis_handle[i], p); } @@ -2954,6 +3082,7 @@ static void btu_ble_biginfo_adv_report_evt(UINT8 *p) static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) { tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT connless_iq_rpt = {0}; + UINT8 sample_count; if (!p) { HCI_TRACE_ERROR("%s, Invalid params.", __func__); @@ -2968,11 +3097,22 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) STREAM_TO_UINT8(connless_iq_rpt.slot_dur, p); STREAM_TO_UINT8(connless_iq_rpt.pkt_status, p); STREAM_TO_UINT16(connless_iq_rpt.periodic_evt_counter, p); - STREAM_TO_UINT8(connless_iq_rpt.sample_count, p); + STREAM_TO_UINT8(sample_count, p); - for (uint8_t i = 0; i < connless_iq_rpt.sample_count; i++) + // Validate sample_count to prevent buffer overflow + if (sample_count > BTM_BLE_CTE_MAX_SAMPLE_COUNT) { + HCI_TRACE_ERROR("%s, sample_count %d exceeds maximum %d", __func__, sample_count, BTM_BLE_CTE_MAX_SAMPLE_COUNT); + sample_count = BTM_BLE_CTE_MAX_SAMPLE_COUNT; + } + connless_iq_rpt.sample_count = sample_count; + + for (uint8_t i = 0; i < sample_count; i++) { STREAM_TO_UINT8(connless_iq_rpt.i_sample[i], p); + } + + for (uint8_t i = 0; i < sample_count; i++) + { STREAM_TO_UINT8(connless_iq_rpt.q_sample[i], p); } @@ -2984,6 +3124,7 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) static void btu_ble_cte_conn_iq_report_evt(UINT8 *p) { tBTM_BLE_CTE_CONN_IQ_REPORT_EVT conn_iq_rpt = {0}; + UINT8 sample_count; if (!p) { HCI_TRACE_ERROR("%s, Invalid params.", __func__); @@ -2999,11 +3140,22 @@ static void btu_ble_cte_conn_iq_report_evt(UINT8 *p) STREAM_TO_UINT8(conn_iq_rpt.slot_dur, p); STREAM_TO_UINT8(conn_iq_rpt.pkt_status, p); STREAM_TO_UINT16(conn_iq_rpt.conn_evt_counter, p); - STREAM_TO_UINT8(conn_iq_rpt.sample_count, p); + STREAM_TO_UINT8(sample_count, p); - for (uint8_t i = 0; i < conn_iq_rpt.sample_count; i++) + // Validate sample_count to prevent buffer overflow + if (sample_count > BTM_BLE_CTE_MAX_SAMPLE_COUNT) { + HCI_TRACE_ERROR("%s, sample_count %d exceeds maximum %d", __func__, sample_count, BTM_BLE_CTE_MAX_SAMPLE_COUNT); + sample_count = BTM_BLE_CTE_MAX_SAMPLE_COUNT; + } + conn_iq_rpt.sample_count = sample_count; + + for (uint8_t i = 0; i < sample_count; i++) { STREAM_TO_UINT8(conn_iq_rpt.i_sample[i], p); + } + + for (uint8_t i = 0; i < sample_count; i++) + { STREAM_TO_UINT8(conn_iq_rpt.q_sample[i], p); } @@ -3084,6 +3236,321 @@ static void btu_ble_subrate_change_evt(UINT8 *p) } #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +static void btu_ble_pa_subevt_data_request_evt(UINT8 *p) +{ + tBTM_BLE_PA_SUBEVT_DATA_REQ_EVT pa_subevt_req_evt = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(pa_subevt_req_evt.adv_handle, p); + STREAM_TO_UINT8(pa_subevt_req_evt.subevt_start, p); + STREAM_TO_UINT8(pa_subevt_req_evt.subevt_data_count, p); + + btm_ble_pa_subevt_data_req_evt(&pa_subevt_req_evt); +} + +static void btu_ble_pa_response_report_evt(UINT8 *p) +{ + tBTM_BLE_PA_RSP_REPORT_EVT pa_rsp_rpt_evt = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(pa_rsp_rpt_evt.adv_handle, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.subevt, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.tx_status, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.num_rsp, p); + + // num_rsp is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + if (pa_rsp_rpt_evt.num_rsp) { + pa_rsp_rpt_evt.rsp_data_info = osi_malloc(pa_rsp_rpt_evt.num_rsp * sizeof(tBTM_BLE_PA_RSP_DATA_INFO)); + if (pa_rsp_rpt_evt.rsp_data_info) + { + for (UINT8 i = 0; i < pa_rsp_rpt_evt.num_rsp; i++) + { + STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].tx_power, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].rssi, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].cte_type, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].rsp_slot, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].data_status, p); + STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].data_len, p); + // data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + if (pa_rsp_rpt_evt.rsp_data_info[i].data_len) { + pa_rsp_rpt_evt.rsp_data_info[i].data = osi_malloc(pa_rsp_rpt_evt.rsp_data_info[i].data_len); + if (pa_rsp_rpt_evt.rsp_data_info[i].data) { + STREAM_TO_ARRAY(pa_rsp_rpt_evt.rsp_data_info[i].data, p, pa_rsp_rpt_evt.rsp_data_info[i].data_len); + } else { + HCI_TRACE_ERROR("%s, no enough memory for data_len %d at index %d", __func__, pa_rsp_rpt_evt.rsp_data_info[i].data_len, i); + pa_rsp_rpt_evt.rsp_data_info[i].data_len = 0; + } + } else { + pa_rsp_rpt_evt.rsp_data_info[i].data = NULL; + } + } + } else { + HCI_TRACE_ERROR("%s, no memory for rsp_data_info", __func__); + } + } + + btm_ble_pa_rsp_rpt_evt(&pa_rsp_rpt_evt); + + if (pa_rsp_rpt_evt.rsp_data_info) + { + for (UINT8 i = 0; i < pa_rsp_rpt_evt.num_rsp; i++) + { + if (pa_rsp_rpt_evt.rsp_data_info[i].data) { + osi_free(pa_rsp_rpt_evt.rsp_data_info[i].data); + } + } + osi_free(pa_rsp_rpt_evt.rsp_data_info); + } +} +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +static void btu_ble_cs_read_remote_supp_caps_evt(UINT8 *p) +{ + tBTM_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT cs_read_remote_supp_caps = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(cs_read_remote_supp_caps.status, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.conn_handle, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.num_config_supported, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.max_consecutive_proc_supported, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.num_ant_supported, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.max_ant_paths_supported, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.roles_supported, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.modes_supported, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.rtt_capability, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.rtt_aa_only_n, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.rtt_sounding_n, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.rtt_random_payload_n, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.NADM_sounding_capability, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.NADM_random_capability, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.cs_sync_phys_supported, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.subfeatures_supported, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.T_IP1_times_supported, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.T_IP2_times_supported, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.T_FCS_times_supported, p); + STREAM_TO_UINT16(cs_read_remote_supp_caps.T_PM_times_supported, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.T_SW_times_supported, p); + STREAM_TO_UINT8(cs_read_remote_supp_caps.TX_SNR_capability, p); + + btm_ble_cs_read_remote_supp_caps_cmpl_evt(&cs_read_remote_supp_caps); +} + +static void btu_ble_cs_read_remote_fae_tab_evt(UINT8 *p) +{ + tBTM_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT cs_read_remote_fae_tab = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(cs_read_remote_fae_tab.status, p); + STREAM_TO_UINT16(cs_read_remote_fae_tab.conn_handle, p); + STREAM_TO_ARRAY(cs_read_remote_fae_tab.remote_fae_table, p, 72); + + btm_ble_cs_read_remote_fae_tab_cmpl_evt(&cs_read_remote_fae_tab); +} + +static void btu_ble_cs_security_enable_cmpl_evt(UINT8 *p) +{ + tBTM_BLE_CS_SEC_ENABLE_CMPL_EVT cs_security_enable = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + STREAM_TO_UINT8(cs_security_enable.status, p); + STREAM_TO_UINT16(cs_security_enable.conn_handle, p); + + btm_ble_cs_securuty_enable_cmpl_evt(&cs_security_enable); +} + +static void btu_ble_cs_config_cmpl_evt(UINT8 *p) +{ + tBTM_BLE_CS_CONFIG_CMPL_EVT config_cmpl = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + STREAM_TO_UINT8(config_cmpl.status, p); + STREAM_TO_UINT16(config_cmpl.conn_handle, p); + STREAM_TO_UINT8(config_cmpl.config_id, p); + STREAM_TO_UINT8(config_cmpl.action, p);; + STREAM_TO_UINT8(config_cmpl.main_mode_type, p); + STREAM_TO_UINT8(config_cmpl.sub_mode_type, p); + STREAM_TO_UINT8(config_cmpl.min_main_mode_steps, p); + STREAM_TO_UINT8(config_cmpl.max_main_mode_steps, p); + STREAM_TO_UINT8(config_cmpl.main_mode_repetition, p); + STREAM_TO_UINT8(config_cmpl.mode_0_steps, p); + STREAM_TO_UINT8(config_cmpl.role, p); + STREAM_TO_UINT8(config_cmpl.rtt_type, p); + STREAM_TO_UINT8(config_cmpl.cs_sync_phy, p); + STREAM_TO_ARRAY(config_cmpl.channel_map, p, 10); + STREAM_TO_UINT8(config_cmpl.channel_map_repetition, p); + STREAM_TO_UINT8(config_cmpl.channel_selection_type, p); + STREAM_TO_UINT8(config_cmpl.ch3c_shape, p); + STREAM_TO_UINT8(config_cmpl.ch3c_jump, p); + STREAM_TO_UINT8(config_cmpl.reserved, p); + STREAM_TO_UINT8(config_cmpl.t_ip1_time, p); + STREAM_TO_UINT8(config_cmpl.t_ip2_time, p); + STREAM_TO_UINT8(config_cmpl.t_fcs_time, p); + STREAM_TO_UINT8(config_cmpl.t_pm_time, p); + + btm_ble_cs_config_cmpl_evt(&config_cmpl); +} + +static void btu_ble_cs_proc_enable_cmpl_evt(UINT8 *p) +{ + tBTM_BLE_CS_PROC_ENABLE_CMPL_EVT proc_en = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(proc_en.status, p); + STREAM_TO_UINT16(proc_en.conn_handle, p); + STREAM_TO_UINT8(proc_en.config_id, p); + STREAM_TO_UINT8(proc_en.state, p); + STREAM_TO_UINT8(proc_en.tone_ant_config_select, p); + STREAM_TO_UINT8(proc_en.select_tx_power, p); + STREAM_TO_UINT24(proc_en.subevent_Len, p); + STREAM_TO_UINT8(proc_en.subevents_per_event, p); + STREAM_TO_UINT16(proc_en.subevent_interval, p); + STREAM_TO_UINT16(proc_en.event_interval, p); + STREAM_TO_UINT16(proc_en.procedure_interval, p); + STREAM_TO_UINT16(proc_en.procedure_count, p); + STREAM_TO_UINT16(proc_en.max_procedure_len, p); + + btm_ble_cs_proc_enable_cmpl_evt(&proc_en); +} + +static void btu_ble_cs_subevt_result_evt(UINT8 *p) +{ + tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT subevt_result = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + STREAM_TO_UINT16(subevt_result.conn_handle, p); + STREAM_TO_UINT8(subevt_result.config_id, p); + STREAM_TO_UINT16(subevt_result.start_acl_conn_event_counter, p); + STREAM_TO_UINT16(subevt_result.procedure_counter, p); + STREAM_TO_UINT16(subevt_result.frequency_compensation, p); + STREAM_TO_UINT8(subevt_result.reference_power_level, p); + STREAM_TO_UINT8(subevt_result.procedure_done_status, p); + STREAM_TO_UINT8(subevt_result.subevent_done_status, p); + STREAM_TO_UINT8(subevt_result.abort_reason, p); + STREAM_TO_UINT8(subevt_result.num_ant_paths, p); + UINT8 num_steps_reported; + STREAM_TO_UINT8(num_steps_reported, p); + + // Validate num_steps_reported per BLE spec: Range 0x00 to 0xA0 (0 to 160) + if (num_steps_reported > BTM_BLE_CS_MAX_STEPS_REPORTED) { + HCI_TRACE_ERROR("%s, num_steps_reported %d exceeds maximum %d", __func__, num_steps_reported, BTM_BLE_CS_MAX_STEPS_REPORTED); + num_steps_reported = BTM_BLE_CS_MAX_STEPS_REPORTED; + } + subevt_result.num_steps_reported = num_steps_reported; + + subevt_result.step_info = osi_malloc(subevt_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO)); + if (subevt_result.step_info) { + for (uint8_t i = 0; i < subevt_result.num_steps_reported; i++) + { + STREAM_TO_UINT8(subevt_result.step_info[i].step_mode, p); + STREAM_TO_UINT8(subevt_result.step_info[i].step_channel, p); + STREAM_TO_UINT8(subevt_result.step_info[i].step_data_len, p); + // step_data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + subevt_result.step_info[i].data = osi_malloc(subevt_result.step_info[i].step_data_len); + if (subevt_result.step_info[i].data) { + STREAM_TO_ARRAY(subevt_result.step_info[i].data, p, subevt_result.step_info[i].step_data_len); + } else if (subevt_result.step_info[i].step_data_len) { + HCI_TRACE_ERROR("%s, no memory.", __func__); + } + } + } + + btm_ble_cs_subevt_result_evt(&subevt_result); + + if (subevt_result.step_info) + { + for (UINT8 i = 0; i < subevt_result.num_steps_reported; i++) + { + if (subevt_result.step_info[i].data) { + osi_free(subevt_result.step_info[i].data); + } + } + osi_free(subevt_result.step_info); + } + +} + +static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p) +{ + tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT subevt_continue_result = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT16(subevt_continue_result.conn_handle, p); + STREAM_TO_UINT8(subevt_continue_result.config_id, p); + STREAM_TO_UINT8(subevt_continue_result.proc_done_status, p); + STREAM_TO_UINT8(subevt_continue_result.subevt_done_status, p); + STREAM_TO_UINT8(subevt_continue_result.abort_reason, p); + STREAM_TO_UINT8(subevt_continue_result.num_ant_paths, p); + UINT8 num_steps_reported; + STREAM_TO_UINT8(num_steps_reported, p); + + // Validate num_steps_reported per BLE spec: Range 0x00 to 0xA0 (0 to 160) + if (num_steps_reported > BTM_BLE_CS_MAX_STEPS_REPORTED) { + HCI_TRACE_ERROR("%s, num_steps_reported %d exceeds maximum %d", __func__, num_steps_reported, BTM_BLE_CS_MAX_STEPS_REPORTED); + num_steps_reported = BTM_BLE_CS_MAX_STEPS_REPORTED; + } + subevt_continue_result.num_steps_reported = num_steps_reported; + + subevt_continue_result.step_info = osi_malloc(subevt_continue_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO)); + if (subevt_continue_result.step_info) { + for (uint8_t i = 0; i < subevt_continue_result.num_steps_reported; i++) { + STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_mode, p); + STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_channel, p); + STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_data_len, p); + // step_data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate + subevt_continue_result.step_info[i].data = osi_malloc(subevt_continue_result.step_info[i].step_data_len); + if (subevt_continue_result.step_info[i].data) { + STREAM_TO_ARRAY(subevt_continue_result.step_info[i].data, p, subevt_continue_result.step_info[i].step_data_len); + } else if (subevt_continue_result.step_info[i].step_data_len) { + HCI_TRACE_ERROR("%s, no memory.", __func__); + } + } + } + + btm_ble_cs_subevt_continue_result_evt(&subevt_continue_result); + + if (subevt_continue_result.step_info) + { + for (UINT8 i = 0; i < subevt_continue_result.num_steps_reported; i++) + { + if (subevt_continue_result.step_info[i].data) { + osi_free(subevt_continue_result.step_info[i].data); + } + } + osi_free(subevt_continue_result.step_info); + } + +} +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + /********************************************** ** End of BLE Events Handler ***********************************************/ diff --git a/components/bt/host/bluedroid/stack/btu/btu_task.c b/components/bt/host/bluedroid/stack/btu/btu_task.c index bffa6837b0..f6ce7e4426 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_task.c +++ b/components/bt/host/bluedroid/stack/btu/btu_task.c @@ -315,7 +315,9 @@ static void btu_general_alarm_process(void *param) switch (p_tle->event) { case BTU_TTYPE_BTM_DEV_CTL: +#if (CLASSIC_BT_INCLUDED == TRUE) btm_dev_timeout(p_tle); +#endif // (CLASSIC_BT_INCLUDED == TRUE) break; case BTU_TTYPE_L2CAP_LINK: @@ -374,11 +376,15 @@ static void btu_general_alarm_process(void *param) break; case BTU_TTYPE_ATT_WAIT_FOR_RSP: +#if (GATTC_INCLUDED == TRUE) gatt_rsp_timeout(p_tle); +#endif // (GATTC_INCLUDED == TRUE) break; case BTU_TTYPE_ATT_WAIT_FOR_IND_ACK: +#if (GATTC_INCLUDED == TRUE) gatt_ind_ack_timeout(p_tle); +#endif // (GATTC_INCLUDED == TRUE) break; #if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/stack/gap/gap_ble.c b/components/bt/host/bluedroid/stack/gap/gap_ble.c index bf3d97d666..154fcca0b0 100644 --- a/components/bt/host/bluedroid/stack/gap/gap_ble.c +++ b/components/bt/host/bluedroid/stack/gap/gap_ble.c @@ -256,6 +256,19 @@ tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN i UINT8_TO_STREAM(p, p_db_attr->attr_value.addr_resolution); p_value->len = 1; break; +#if (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) + case GATT_UUID_GAP_GATT_SECURITY_LEVELS: + UINT16_TO_STREAM(p, p_db_attr->attr_value.security_level); + p_value->len = 2; + break; +#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + case GATT_UUID_GAP_KEY_MATERIAL: + ARRAY_TO_STREAM(p, p_db_attr->attr_value.key_material.session_key, GAP_KEY_MATERIAL_SESSION_KEY_SIZE); + ARRAY_TO_STREAM(p, p_db_attr->attr_value.key_material.iv, GAP_KEY_MATERIAL_IV_SIZE); + p_value->len = GAP_KEY_MATERIAL_SIZE; + break; +#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) } return GATT_SUCCESS; } @@ -464,6 +477,31 @@ void gap_attr_db_init(void) p_db_attr->attr_value.addr_resolution = 0; p_db_attr++; +#if (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) + /* Add LE Security Levels Characteristic */ + uuid.len = LEN_UUID_16; + uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_GATT_SECURITY_LEVELS; + p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, + GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ, + NULL, NULL); + p_db_attr->attr_value.security_level = 0x0101; + p_db_attr++; +#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) + +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + /* Add Encrypted Data Key Material Characteristic + * Per Bluetooth spec: readable only when authenticated and authorized, + * requires encrypted link to read. + */ + uuid.len = LEN_UUID_16; + uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_KEY_MATERIAL; + p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, + GATT_PERM_READ_ENCRYPTED, GATT_CHAR_PROP_BIT_READ, + NULL, NULL); + memset(&p_db_attr->attr_value.key_material, 0, sizeof(tGAP_BLE_KEY_MATERIAL)); + p_db_attr++; +#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + /* start service now */ memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128); @@ -495,6 +533,11 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value) GAP_TRACE_EVENT("GAP_BleAttrDBUpdate attr_uuid=0x%04x\n", attr_uuid); + if (p_value == NULL) { + GAP_TRACE_ERROR("GAP_BleAttrDBUpdate: NULL pointer parameter"); + return; + } + for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++) { if (p_db_attr->uuid == attr_uuid) { GAP_TRACE_EVENT("Found attr_uuid=0x%04x\n", attr_uuid); @@ -517,6 +560,19 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value) p_db_attr->attr_value.addr_resolution = p_value->addr_resolution; break; +#if (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) + case GATT_UUID_GAP_GATT_SECURITY_LEVELS: + p_db_attr->attr_value.security_level = p_value->security_level; + break; +#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) + +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + case GATT_UUID_GAP_KEY_MATERIAL: + memcpy(&p_db_attr->attr_value.key_material, &p_value->key_material, + sizeof(tGAP_BLE_KEY_MATERIAL)); + break; +#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + } break; } @@ -741,7 +797,7 @@ BOOLEAN gap_ble_accept_cl_operation(BD_ADDR peer_bda, UINT16 uuid, tGAP_BLE_CMPL } /* hold the link here */ - if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, BLE_ADDR_UNKNOWN_TYPE, TRUE, BT_TRANSPORT_LE, FALSE)) { + if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, BLE_ADDR_UNKNOWN_TYPE, TRUE, BT_TRANSPORT_LE, FALSE, FALSE, 0xFF, 0xFF)) { return started; } diff --git a/components/bt/host/bluedroid/stack/gap/gap_conn.c b/components/bt/host/bluedroid/stack/gap/gap_conn.c index cdd6a2d3a9..2fa54fa923 100644 --- a/components/bt/host/bluedroid/stack/gap/gap_conn.c +++ b/components/bt/host/bluedroid/stack/gap/gap_conn.c @@ -510,18 +510,19 @@ UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT } while (max_len) { + UINT16 length = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len; if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) { - if ((p_buf = (BT_HDR *)osi_malloc(L2CAP_FCR_ERTM_BUF_SIZE)) == NULL) { + if ((p_buf = (BT_HDR *)osi_malloc(BT_HDR_SIZE + length + L2CAP_MIN_OFFSET + L2CAP_FCS_LEN)) == NULL) { return (GAP_ERR_CONGESTED); } } else { - if ((p_buf = (BT_HDR *)osi_malloc(GAP_DATA_BUF_SIZE)) == NULL) { + if ((p_buf = (BT_HDR *)osi_malloc(BT_HDR_SIZE + length + L2CAP_MIN_OFFSET)) == NULL) { return (GAP_ERR_CONGESTED); } } p_buf->offset = L2CAP_MIN_OFFSET; - p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len; + p_buf->len = length; p_buf->event = BT_EVT_TO_BTU_SP_DATA; memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len); diff --git a/components/bt/host/bluedroid/stack/gap/include/gap_int.h b/components/bt/host/bluedroid/stack/gap/include/gap_int.h index 8a3ae0e2f0..dc6353c325 100644 --- a/components/bt/host/bluedroid/stack/gap/include/gap_int.h +++ b/components/bt/host/bluedroid/stack/gap/include/gap_int.h @@ -93,7 +93,11 @@ typedef struct { #if BLE_INCLUDED == TRUE -#define GAP_MAX_CHAR_NUM 4 +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +#define GAP_MAX_CHAR_NUM 6 +#else +#define GAP_MAX_CHAR_NUM 5 +#endif typedef struct { UINT16 handle; @@ -124,8 +128,9 @@ typedef struct { } tGAP_CLCB; typedef struct { +#if (CLASSIC_BT_INCLUDED == TRUE) tGAP_INFO blk[GAP_MAX_BLOCKS]; - tBTM_CMPL_CB *btm_cback[GAP_MAX_BLOCKS]; +#endif // (CLASSIC_BT_INCLUDED == TRUE) UINT8 trace_level; //tGAP_FINDADDR_CB findaddr_cb; /* Contains the control block for finding a device addr */ //tBTM_INQ_INFO *cur_inqptr; diff --git a/components/bt/host/bluedroid/stack/gatt/att_protocol.c b/components/bt/host/bluedroid/stack/gatt/att_protocol.c index ea7776e4c7..c16967c6ef 100644 --- a/components/bt/host/bluedroid/stack/gatt/att_protocol.c +++ b/components/bt/host/bluedroid/stack/gatt/att_protocol.c @@ -495,7 +495,7 @@ BT_HDR *attp_build_sr_msg(tGATT_TCB *p_tcb, UINT8 op_code, tGATT_SR_MSG *p_msg) ** Description This function sends the server response or indication message ** to client. ** -** Parameter p_tcb: pointer to the connection control block. +** Parameter p_tcb: pointer to the connection control block. ** p_msg: pointer to message parameters structure. ** ** Returns GATT_SUCCESS if successfully sent; otherwise error code. @@ -661,7 +661,7 @@ tGATT_STATUS attp_send_cl_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code, if (p_cmd != NULL) { status = attp_cl_send_cmd(p_tcb, clcb_idx, op_code, p_cmd); } - + GATT_TRACE_DEBUG("%s opcode=%x status=%x", __func__, op_code, status); } else { GATT_TRACE_ERROR("Peer device not connected"); } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_api.c b/components/bt/host/bluedroid/stack/gatt/gatt_api.c index 51e46e2274..a245247d56 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_api.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_api.c @@ -1044,11 +1044,13 @@ tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM default: break; } +#if (SMP_INCLUDED == TRUE) /* start security check */ if (gatt_security_check_start(p_clcb) == FALSE) { status = GATT_NO_RESOURCES; gatt_clcb_dealloc(p_clcb); } +#endif // (SMP_INCLUDED == TRUE) } else { status = GATT_NO_RESOURCES; } @@ -1108,10 +1110,11 @@ tGATT_STATUS GATTC_Write (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_ p_clcb->start_offset = p_write->offset; p->offset = 0; } - +#if (SMP_INCLUDED == TRUE) if (gatt_security_check_start(p_clcb) == FALSE) { status = GATT_NO_RESOURCES; } +#endif // (SMP_INCLUDED == TRUE) } else { status = GATT_NO_RESOURCES; } @@ -1388,13 +1391,9 @@ void GATT_Deregister (tGATT_IF gatt_if) } } } -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) gatt_deregister_bgdev_list(gatt_if); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) - /* update the listen mode */ -#if (defined(BLE_PERIPHERAL_MODE_SUPPORT) && (BLE_PERIPHERAL_MODE_SUPPORT == TRUE)) - GATT_Listen(gatt_if, FALSE, NULL); -#endif +#endif // #if (GATT_BG_CONN_DEV == TRUE) memset (p_reg, 0, sizeof(tGATT_REG)); } @@ -1453,7 +1452,8 @@ void GATT_StartIf (tGATT_IF gatt_if) ** *******************************************************************************/ BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_type, - BOOLEAN is_direct, tBT_TRANSPORT transport, BOOLEAN is_aux) + BOOLEAN is_direct, tBT_TRANSPORT transport, BOOLEAN is_aux, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent) { tGATT_REG *p_reg; BOOLEAN status = FALSE; @@ -1467,13 +1467,13 @@ BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_ } if (is_direct) { - status = gatt_act_connect (p_reg, bd_addr, bd_addr_type, transport, is_aux); + status = gatt_act_connect (p_reg, bd_addr, bd_addr_type, transport, is_aux, is_pawr_synced, adv_handle, subevent); } else { -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) if (transport == BT_TRANSPORT_LE) { status = gatt_update_auto_connect_dev(gatt_if, TRUE, bd_addr, TRUE); } else -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) { GATT_TRACE_ERROR("Unsupported transport for background connection"); } @@ -1531,7 +1531,7 @@ BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct status = gatt_cancel_open(gatt_if, bd_addr); } } else { -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) if (!gatt_if) { if (gatt_get_num_apps_for_bg_dev(bd_addr)) { while (gatt_find_app_for_bg_dev(bd_addr, &temp_gatt_if)) { @@ -1544,7 +1544,7 @@ BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct } else { status = gatt_remove_bg_dev_for_app(gatt_if, bd_addr); } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) } return status; @@ -1583,6 +1583,7 @@ tGATT_STATUS GATT_Disconnect (UINT16 conn_id) return ret; } +#if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** ** Function GATT_SendServiceChangeIndication @@ -1629,6 +1630,7 @@ tGATT_STATUS GATT_SendServiceChangeIndication (BD_ADDR bd_addr) return status; } +#endif // (GATTS_INCLUDED == TRUE) /******************************************************************************* ** @@ -1697,45 +1699,7 @@ BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_c return status; } - -/******************************************************************************* -** -** Function GATT_Listen -** -** Description This function start or stop LE advertisement and listen for -** connection. -** -** Parameters gatt_if: application interface -** p_bd_addr: listen for specific address connection, or NULL for -** listen to all device connection. -** start: start or stop listening. -** -** Returns TRUE if advertisement is started; FALSE if adv start failure. -** -*******************************************************************************/ -BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr) -{ - tGATT_REG *p_reg; - - GATT_TRACE_API ("GATT_Listen gatt_if=%d", gatt_if); - - /* Make sure app is registered */ - if ((p_reg = gatt_get_regcb(gatt_if)) == NULL) { - GATT_TRACE_ERROR("GATT_Listen - gatt_if =%d is not registered", gatt_if); - return (FALSE); - } - - if (bd_addr != NULL) { -#if (tGATT_BG_CONN_DEV == TRUE) - gatt_update_auto_connect_dev(gatt_if, start, bd_addr, FALSE); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) - } else { - p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE; - } - - return gatt_update_listen_mode(); -} - +#if (GATTS_INCLUDED == TRUE) tGATT_STATUS GATTS_SetServiceChangeMode(UINT8 mode) { if (mode > GATTS_SEND_SERVICE_CHANGE_MANUAL) { @@ -1747,6 +1711,8 @@ tGATT_STATUS GATTS_SetServiceChangeMode(UINT8 mode) return GATT_SUCCESS; } +#endif // (GATTS_INCLUDED == TRUE) + tGATT_STATUS GATTS_HandleMultiValueNotification (UINT16 conn_id, tGATT_HLV *tuples, UINT16 num_tuples) { tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER; diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_attr.c b/components/bt/host/bluedroid/stack/gatt/gatt_attr.c index 3ab573426a..27e80d605d 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_attr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_attr.c @@ -98,7 +98,7 @@ UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR remote_bda) ** ** Description find clcb by Connection ID ** -** Returns Pointer to the found link conenction control block. +** Returns Pointer to the found link connection control block. ** *******************************************************************************/ static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_conn_id(UINT16 conn_id) @@ -119,9 +119,9 @@ static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_conn_id(UINT16 conn_id) ** ** Function gatt_profile_find_clcb_by_bd_addr ** -** Description The function searches all LCBs with macthing bd address. +** Description The function searches all LCBs with matching bd address. ** -** Returns Pointer to the found link conenction control block. +** Returns Pointer to the found link connection control block. ** *******************************************************************************/ static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda, tBT_TRANSPORT transport) @@ -148,7 +148,7 @@ static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda, tBT_TR ** Returns NULL if not found. Otherwise pointer to the connection link block. ** *******************************************************************************/ -tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda, tBT_TRANSPORT tranport) +tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda, tBT_TRANSPORT transport) { UINT8 i_clcb = 0; tGATT_PROFILE_CLCB *p_clcb = NULL; @@ -158,7 +158,7 @@ tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda, tBT_TR p_clcb->in_use = TRUE; p_clcb->conn_id = conn_id; p_clcb->connected = TRUE; - p_clcb->transport = tranport; + p_clcb->transport = transport; memcpy (p_clcb->bda, bda, BD_ADDR_LEN); break; } @@ -435,7 +435,7 @@ static void gatt_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, ** ** Function gatt_profile_db_init ** -** Description Initializa the GATT profile attribute database. +** Description Initialize the GATT profile attribute database. ** *******************************************************************************/ void gatt_profile_db_init (void) @@ -684,7 +684,7 @@ void GATT_ConfigServiceChangeCCC (BD_ADDR remote_bda, BOOLEAN enable, tBT_TRANSP p_clcb->connected = TRUE; } /* hold the link here */ - GATT_Connect(gatt_cb.gatt_if, remote_bda, BLE_ADDR_UNKNOWN_TYPE, TRUE, transport, FALSE); + GATT_Connect(gatt_cb.gatt_if, remote_bda, BLE_ADDR_UNKNOWN_TYPE, TRUE, transport, FALSE, FALSE, 0xFF, 0xFF); p_clcb->ccc_stage = GATT_SVC_CHANGED_CONNECTING; if (!p_clcb->connected) { diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_auth.c b/components/bt/host/bluedroid/stack/gatt/gatt_auth.c index 4db0a554d5..a5769a83d7 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_auth.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_auth.c @@ -129,6 +129,8 @@ void gatt_verify_signature(tGATT_TCB *p_tcb, BT_HDR *p_buf) } #endif ///SMP_INCLUDED == TRUE +#if (SMP_INCLUDED == TRUE) + /******************************************************************************* ** ** Function gatt_sec_check_complete @@ -155,6 +157,7 @@ void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb, UINT8 s #endif ///GATTC_INCLUDED == TRUE } } + /******************************************************************************* ** ** Function gatt_enc_cmpl_cback @@ -253,6 +256,7 @@ void gatt_notify_enc_cmpl(BD_ADDR bd_addr) } return; } + /******************************************************************************* ** ** Function gatt_set_sec_act @@ -268,6 +272,7 @@ void gatt_set_sec_act(tGATT_TCB *p_tcb, tGATT_SEC_ACTION sec_act) p_tcb->sec_act = sec_act; } } + /******************************************************************************* ** ** Function gatt_get_sec_act @@ -285,6 +290,7 @@ tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB *p_tcb) } return sec_act; } +#endif // (SMP_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_determine_sec_act @@ -420,7 +426,7 @@ tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB *p_tcb) return encrypt_status ; } - +#if (SMP_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_convert_sec_action @@ -450,6 +456,7 @@ static BOOLEAN gatt_convert_sec_action(tGATT_SEC_ACTION gatt_sec_act, tBTM_BLE_S return status; } + /******************************************************************************* ** ** Function gatt_check_enc_req @@ -517,6 +524,6 @@ BOOLEAN gatt_security_check_start(tGATT_CLCB *p_clcb) return status; } - +#endif // (SMP_INCLUDED == TRUE) #endif /* BLE_INCLUDED */ diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c index ddd089f4e0..1bdbfaec08 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c @@ -554,7 +554,13 @@ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; UNUSED(op_code); - UNUSED(len); + + /* Fix: Validate minimum length (opcode:1 + handle:2 + reason:1 = 4 bytes) */ + if (len < 4) { + GATT_TRACE_ERROR("invalid error rsp len: %d", len); + gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); + return; + } GATT_TRACE_DEBUG("%s", __func__); STREAM_TO_UINT8(opcode, p); @@ -800,6 +806,14 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 handle_len = 4; } + /* Check value_len is sufficient before subtraction to prevent underflow */ + if (value_len < handle_len) { + GATT_TRACE_ERROR("gatt_process_read_by_type_rsp: value_len(%d) < handle_len(%d), invalid response", + value_len, handle_len); + gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); + return; + } + value_len -= handle_len; /* subtract the handle pairs bytes */ len -= 1; diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_main.c b/components/bt/host/bluedroid/stack/gatt/gatt_main.c index e5d9823712..93eb1bb194 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_main.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_main.c @@ -102,8 +102,9 @@ void gatt_init (void) #endif /* #if GATT_DYNAMIC_MEMORY */ memset (&gatt_cb, 0, sizeof(tGATT_CB)); memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG)); - +#if (GATTC_INCLUDED == TRUE) gatt_cb.auto_disc = TRUE; +#endif // (GATTC_INCLUDED == TRUE) gatt_cb.p_clcb_list = list_new(osi_free_func); gatt_cb.p_tcb_list = list_new(osi_free_func); #if defined(GATT_INITIAL_TRACE_LEVEL) @@ -111,11 +112,11 @@ void gatt_init (void) #else gatt_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ #endif - gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE; - gatt_cb.sign_op_queue = fixed_queue_new(QUEUE_SIZE_MAX); +#if (GATTS_INCLUDED == TRUE) gatt_cb.srv_chg_clt_q = fixed_queue_new(QUEUE_SIZE_MAX); gatt_cb.pending_new_srv_start_q = fixed_queue_new(QUEUE_SIZE_MAX); gatt_cb.srv_chg_mode = GATTS_SEND_SERVICE_CHANGE_MODE; +#endif // (GATTS_INCLUDED == TRUE) /* First, register fixed L2CAP channel for ATT over BLE */ fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE; @@ -140,11 +141,10 @@ void gatt_init (void) #endif ///CLASSIC_BT_GATT_INCLUDED == TRUE BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0); - +#if (GATTS_INCLUDED == TRUE) gatt_cb.hdl_cfg.gatt_start_hdl = GATT_GATT_START_HANDLE; gatt_cb.hdl_cfg.gap_start_hdl = GATT_GAP_START_HANDLE; gatt_cb.hdl_cfg.app_start_hdl = GATT_APP_START_HANDLE; -#if (GATTS_INCLUDED == TRUE) gatt_profile_db_init(); #endif ///GATTS_INCLUDED == TRUE //init local MTU size @@ -165,28 +165,30 @@ void gatt_init (void) void gatt_free(void) { GATT_TRACE_DEBUG("gatt_free()"); - fixed_queue_free(gatt_cb.sign_op_queue, NULL); - gatt_cb.sign_op_queue = NULL; +#if (GATTS_INCLUDED == TRUE) fixed_queue_free(gatt_cb.srv_chg_clt_q, NULL); gatt_cb.srv_chg_clt_q = NULL; fixed_queue_free(gatt_cb.pending_new_srv_start_q, osi_free_func); gatt_cb.pending_new_srv_start_q = NULL; +#endif // (GATTS_INCLUDED == TRUE) list_node_t *p_node = NULL; tGATT_TCB *p_tcb = NULL; for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) { p_tcb = list_node(p_node); +#if (SMP_INCLUDED == TRUE) fixed_queue_free(p_tcb->pending_enc_clcb, NULL); p_tcb->pending_enc_clcb = NULL; - - fixed_queue_free(p_tcb->pending_ind_q, NULL); - p_tcb->pending_ind_q = NULL; - +#endif // (SMP_INCLUDED == TRUE) +#if (GATTS_INCLUDED == TRUE) btu_free_timer(&p_tcb->conf_timer_ent); memset(&p_tcb->conf_timer_ent, 0, sizeof(TIMER_LIST_ENT)); +#endif // (GATTS_INCLUDED == TRUE) +#if (GATTC_INCLUDED == TRUE) btu_free_timer(&p_tcb->ind_ack_timer_ent); memset(&p_tcb->ind_ack_timer_ent, 0, sizeof(TIMER_LIST_ENT)); +#endif // #if (GATTC_INCLUDED == TRUE) #if (GATTS_INCLUDED == TRUE) fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL); @@ -220,7 +222,8 @@ void gatt_free(void) ** Returns TRUE if connection is started, otherwise return FALSE. ** *******************************************************************************/ -BOOLEAN gatt_connect (BD_ADDR rem_bda, tBLE_ADDR_TYPE bd_addr_type, tGATT_TCB *p_tcb, tBT_TRANSPORT transport, BOOLEAN is_aux) +BOOLEAN gatt_connect (BD_ADDR rem_bda, tBLE_ADDR_TYPE bd_addr_type, tGATT_TCB *p_tcb, tBT_TRANSPORT transport, BOOLEAN is_aux, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent) { BOOLEAN gatt_ret = FALSE; @@ -230,7 +233,7 @@ BOOLEAN gatt_connect (BD_ADDR rem_bda, tBLE_ADDR_TYPE bd_addr_type, tGATT_TCB *p if (transport == BT_TRANSPORT_LE) { p_tcb->att_lcid = L2CAP_ATT_CID; - gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda, bd_addr_type, is_aux); + gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda, bd_addr_type, is_aux, is_pawr_synced, adv_handle, subevent); #if (CLASSIC_BT_GATT_INCLUDED == TRUE) } else { if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) != 0) { @@ -376,7 +379,8 @@ void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN ** *******************************************************************************/ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, - tBLE_ADDR_TYPE bd_addr_type, tBT_TRANSPORT transport, BOOLEAN is_aux) + tBLE_ADDR_TYPE bd_addr_type, tBT_TRANSPORT transport, BOOLEAN is_aux, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent) { BOOLEAN ret = FALSE; tGATT_TCB *p_tcb; @@ -389,7 +393,7 @@ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, /* before link down, another app try to open a GATT connection */ if (st == GATT_CH_OPEN && gatt_num_apps_hold_link(p_tcb) == 0 && transport == BT_TRANSPORT_LE ) { - if (!gatt_connect(bd_addr, bd_addr_type, p_tcb, transport, is_aux)) { + if (!gatt_connect(bd_addr, bd_addr_type, p_tcb, transport, is_aux, is_pawr_synced, adv_handle, subevent)) { ret = FALSE; } } else if (st == GATT_CH_CLOSING) { @@ -400,7 +404,7 @@ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, } } else { if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, transport)) != NULL) { - if (!gatt_connect(bd_addr, bd_addr_type, p_tcb, transport, is_aux)) { + if (!gatt_connect(bd_addr, bd_addr_type, p_tcb, transport, is_aux, is_pawr_synced, adv_handle, subevent)) { GATT_TRACE_ERROR("gatt_connect failed"); // code enter here if create connection failed. if disconnect after connection, code will not enter here @@ -409,12 +413,11 @@ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, // but here p_tcb is get from gatt_allocate_tcb_by_bdaddr(), is too old, so we get p_tcb again p_tcb = gatt_find_tcb_by_addr(bd_addr, transport); if(p_tcb != NULL) { +#if (SMP_INCLUDED == TRUE) if(p_tcb->pending_enc_clcb != NULL) { fixed_queue_free(p_tcb->pending_enc_clcb, NULL); } - if(p_tcb->pending_ind_q != NULL) { - fixed_queue_free(p_tcb->pending_ind_q, NULL); - } +#endif // (SMP_INCLUDED == TRUE) gatt_tcb_free(p_tcb); } @@ -448,8 +451,10 @@ static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connect { tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, transport); +#if (GATTS_INCLUDED == TRUE) BOOLEAN check_srv_chg = FALSE; tGATTS_SRV_CHG *p_srv_chg_clt = NULL; +#endif // (GATTS_INCLUDED == TRUE) /* ignore all fixed channel connect/disconnect on BR/EDR link for GATT */ if (transport == BT_TRANSPORT_BR_EDR) { @@ -459,7 +464,7 @@ static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connect GATT_TRACE_DEBUG ("GATT ATT protocol channel with BDA: %08x%04x is %s", (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], (bd_addr[4] << 8) + bd_addr[5], (connected) ? "connected" : "disconnected"); - +#if (GATTS_INCLUDED == TRUE) if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL) { check_srv_chg = TRUE; } else { @@ -467,6 +472,7 @@ static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connect gatt_add_a_bonded_dev_for_srv_chg(bd_addr); } } +#endif // #if (GATTS_INCLUDED == TRUE) if (connected) { /* do we have a channel initiating a connection? */ @@ -479,11 +485,11 @@ static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connect gatt_send_conn_cback(p_tcb); } - if (check_srv_chg) { #if (GATTS_INCLUDED == TRUE) + if (check_srv_chg) { gatt_chk_srv_chg (p_srv_chg_clt); -#endif ///GATTS_INCLUDED == TRUE } +#endif ///GATTS_INCLUDED == TRUE } /* this is incoming connection or background connection callback */ @@ -496,11 +502,11 @@ static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connect p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE; gatt_send_conn_cback (p_tcb); - if (check_srv_chg) { #if (GATTS_INCLUDED == TRUE) + if (check_srv_chg) { gatt_chk_srv_chg (p_srv_chg_clt); -#endif ///GATTS_INCLUDED == TRUE } +#endif ///GATTS_INCLUDED == TRUE } else { GATT_TRACE_ERROR("CCB max out, no resources"); } @@ -929,23 +935,23 @@ static void gatt_send_conn_cback(tGATT_TCB *p_tcb) { UINT8 i; tGATT_REG *p_reg; -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) tGATT_BG_CONN_DEV *p_bg_dev = NULL; -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) UINT16 conn_id; -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) /* notifying all applications for the connection up event */ for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++) { if (p_reg->in_use) { -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if)) { gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE); } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) if (p_reg->app_cb.p_conn_cb) { conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, @@ -995,6 +1001,7 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf) pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK); if (pseudo_op_code < GATT_OP_CODE_MAX) { + GATT_TRACE_DEBUG("%s opcode=%x msg_len=%u", __func__, op_code, msg_len); if (op_code == GATT_SIGN_CMD_WRITE) { #if (SMP_INCLUDED == TRUE) gatt_verify_signature(p_tcb, p_buf); @@ -1220,7 +1227,6 @@ tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB *p_tcb) { tGATT_CH_STATE ch_state = GATT_CH_CLOSE; if (p_tcb) { - GATT_TRACE_DEBUG ("gatt_get_ch_state: ch_state=%d", p_tcb->ch_state); ch_state = p_tcb->ch_state; } return ch_state; @@ -1233,6 +1239,7 @@ uint16_t gatt_get_local_mtu(void) void gatt_set_local_mtu(uint16_t mtu) { + GATT_TRACE_DEBUG("%s mtu=%u", __func__, mtu); gatt_default.local_mtu = mtu; } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index 5947239cf1..118dad4cb3 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -405,7 +405,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, tGATT_STATUS ret_code = GATT_SUCCESS; UNUSED(trans_id); - GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d\n", gatt_if); + GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d opcode=%x\n", gatt_if, op_code); gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE); @@ -479,7 +479,13 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U BOOLEAN is_need_dequeue_sr_cmd = FALSE; tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL; tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL; - UNUSED(len); + + /* Fix: Validate minimum length (flags: 1 byte) */ + if (len < 1) { + GATT_TRACE_ERROR("invalid exec write req len: %d", len); + gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE); + return; + } #if GATT_CONFORMANCE_TESTING == TRUE if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) { @@ -1234,10 +1240,13 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle, switch (op_code) { case GATT_SIGN_CMD_WRITE: - if (op_code == GATT_SIGN_CMD_WRITE) { - GATT_TRACE_DEBUG("Write CMD with data signing" ); - len -= GATT_AUTH_SIGN_LEN; + /* Fix: Validate length before subtraction to prevent underflow */ + if (len < GATT_AUTH_SIGN_LEN) { + GATT_TRACE_ERROR("signed write len too short: %d", len); + return; /* GATT_SIGN_CMD_WRITE has no response */ } + GATT_TRACE_DEBUG("Write CMD with data signing" ); + len -= GATT_AUTH_SIGN_LEN; /* fall through */ case GATT_CMD_WRITE: case GATT_REQ_WRITE: @@ -1473,7 +1482,13 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 UINT8 sec_flag, key_size, *p; UINT16 offset = 0, value_len = 0; - UNUSED (len); + /* Fix: Validate length for GATT_REQ_READ_BLOB (needs offset: 2 bytes) */ + if (op_code == GATT_REQ_READ_BLOB && len < 2) { + GATT_TRACE_ERROR("invalid read blob req len: %d", len); + gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, FALSE); + return; + } + if ((p_msg = (BT_HDR *)osi_calloc(buf_len)) == NULL) { GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n"); @@ -1633,33 +1648,6 @@ static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb ) } } -/******************************************************************************* -** -** Function gatts_chk_pending_ind -** -** Description This function check any pending indication needs to be sent if -** there is a pending indication then sent the indication -** -** Returns void -** -*******************************************************************************/ -static void gatts_chk_pending_ind(tGATT_TCB *p_tcb ) -{ -#if (GATTS_INCLUDED == TRUE) - tGATT_VALUE *p_buf = (tGATT_VALUE *)fixed_queue_try_peek_first(p_tcb->pending_ind_q); - GATT_TRACE_DEBUG("gatts_chk_pending_ind"); - - if (p_buf ) { - GATTS_HandleValueIndication (p_buf->conn_id, - p_buf->handle, - p_buf->len, - p_buf->value); - osi_free(fixed_queue_try_remove_from_queue(p_tcb->pending_ind_q, - p_buf)); - } -#endif ///GATTS_INCLUDED == TRUE -} - /******************************************************************************* ** ** Function gatts_proc_ind_ack @@ -1686,7 +1674,6 @@ static BOOLEAN gatts_proc_ind_ack(tGATT_TCB *p_tcb, UINT16 ack_handle) #endif /* GATTS_ROBUST_CACHING_ENABLED */ } - gatts_chk_pending_ind(p_tcb); return continue_processing; } @@ -1827,6 +1814,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code, { /* there is pending command, discard this one */ if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF) { + GATT_TRACE_WARNING("%s discard command opcode=%02x", __func__, op_code); return; } @@ -1891,6 +1879,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code, break; default: + GATT_TRACE_ERROR("%s unknown command opcode=%02x", __func__, op_code); break; } } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c index 5565169a78..e950b67932 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c @@ -80,30 +80,7 @@ static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x0 static UINT8 gatt_tcb_id[GATT_MAX_PHY_CHANNEL / 8 + 1]; -/******************************************************************************* -** -** Function gatt_free_pending_ind -** -** Description Free all pending indications -** -** Returns None -** -*******************************************************************************/ -void gatt_free_pending_ind(tGATT_TCB *p_tcb) -{ - GATT_TRACE_DEBUG("gatt_free_pending_ind"); - if (p_tcb->pending_ind_q == NULL) { - return; - } - - /* release all queued indications */ - while (!fixed_queue_is_empty(p_tcb->pending_ind_q)) { - osi_free(fixed_queue_dequeue(p_tcb->pending_ind_q, 0)); - } - fixed_queue_free(p_tcb->pending_ind_q, NULL); - p_tcb->pending_ind_q = NULL; -} - +#if (SMP_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_free_pending_enc_queue @@ -127,7 +104,8 @@ void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb) fixed_queue_free(p_tcb->pending_enc_clcb, NULL); p_tcb->pending_enc_clcb = NULL; } - +#endif // (SMP_INCLUDED == TRUE) +#if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_free_pending_prepare_write_queue @@ -153,7 +131,9 @@ void gatt_free_pending_prepare_write_queue(tGATT_TCB *p_tcb) p_tcb->prepare_write_record.total_num = 0; p_tcb->prepare_write_record.error_code_app = GATT_SUCCESS; } +#endif // (GATTS_INCLUDED == TRUE) +#if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_delete_dev_from_srv_chg_clt_list @@ -248,30 +228,9 @@ tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tB return p_buf; } +#endif // (GATTS_INCLUDED == TRUE) - -/******************************************************************************* -** -** Function gatt_add_pending_ind -** -** Description Add a pending indication -** -** Returns Pointer to the current pending indication buffer, NULL no buffer available -** -*******************************************************************************/ -tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB *p_tcb, tGATT_VALUE *p_ind) -{ - tGATT_VALUE *p_buf; - GATT_TRACE_DEBUG ("gatt_add_pending_ind"); - if ((p_buf = (tGATT_VALUE *)osi_malloc((UINT16)sizeof(tGATT_VALUE))) != NULL) { - GATT_TRACE_DEBUG ("enqueue a pending indication"); - memcpy(p_buf, p_ind, sizeof(tGATT_VALUE)); - fixed_queue_enqueue(p_tcb->pending_ind_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT); - } - return p_buf; -} - - +#if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_add_pending_new_srv_start @@ -327,7 +286,7 @@ tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg) ** Returns Pointer to the allocated buffer, NULL no buffer available ** *******************************************************************************/ -#if (GATTS_INCLUDED == TRUE) + tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void) { UINT8 i; @@ -803,7 +762,7 @@ BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found return found; } - +#if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_is_srv_chg_ind_pending @@ -818,23 +777,10 @@ BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb) { BOOLEAN srv_chg_ind_pending = FALSE; - GATT_TRACE_DEBUG("gatt_is_srv_chg_ind_pending is_queue_empty=%d", - fixed_queue_is_empty(p_tcb->pending_ind_q)); + GATT_TRACE_DEBUG("gatt_is_srv_chg_ind_pending is_queue_empty=%d_%d", p_tcb->indicate_handle, gatt_cb.handle_of_h_r); if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r) { srv_chg_ind_pending = TRUE; - } else if (! fixed_queue_is_empty(p_tcb->pending_ind_q)) { - list_t *list = fixed_queue_get_list(p_tcb->pending_ind_q); - for (const list_node_t *node = list_begin(list); - node != list_end(list); - node = list_next(node)) { - tGATT_VALUE *p_buf = (tGATT_VALUE *)list_node(node); - if (p_buf->handle == gatt_cb.handle_of_h_r) - { - srv_chg_ind_pending = TRUE; - break; - } - } } GATT_TRACE_DEBUG("srv_chg_ind_pending = %d", srv_chg_ind_pending); @@ -874,7 +820,7 @@ tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda) return p_buf; } - +#endif // (GATTS_INCLUDED == TRUE) /******************************************************************************* ** @@ -1083,8 +1029,9 @@ tGATT_TCB *gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport) } if (allocated) { memset(p_tcb, 0, sizeof(tGATT_TCB)); +#if (SMP_INCLUDED == TRUE) p_tcb->pending_enc_clcb = fixed_queue_new(QUEUE_SIZE_MAX); - p_tcb->pending_ind_q = fixed_queue_new(QUEUE_SIZE_MAX); +#endif // (SMP_INCLUDED == TRUE) p_tcb->in_use = TRUE; p_tcb->tcb_idx = i; p_tcb->transport = transport; @@ -1296,15 +1243,12 @@ BOOLEAN gatt_parse_uuid_from_cmd(tBT_UUID *p_uuid_rec, UINT16 uuid_size, UINT8 * void gatt_start_rsp_timer(UINT16 clcb_idx) { tGATT_CLCB *p_clcb = gatt_clcb_find_by_idx(clcb_idx); - UINT32 timeout = GATT_WAIT_FOR_RSP_TOUT; p_clcb->rsp_timer_ent.param = (TIMER_PARAM_TYPE)p_clcb; - if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && - p_clcb->op_subtype == GATT_DISC_SRVC_ALL) { - timeout = GATT_WAIT_FOR_DISC_RSP_TOUT; - } btu_start_timer (&p_clcb->rsp_timer_ent, BTU_TTYPE_ATT_WAIT_FOR_RSP, - timeout); + GATT_WAIT_FOR_RSP_TOUT); } + +#if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_start_conf_timer @@ -1320,6 +1264,9 @@ void gatt_start_conf_timer(tGATT_TCB *p_tcb) btu_start_timer (&p_tcb->conf_timer_ent, BTU_TTYPE_ATT_WAIT_FOR_RSP, GATT_WAIT_FOR_RSP_TOUT); } +#endif // (GATTS_INCLUDED == TRUE) + +#if (GATTC_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_start_ind_ack_timer @@ -1337,6 +1284,7 @@ void gatt_start_ind_ack_timer(tGATT_TCB *p_tcb) GATT_WAIT_FOR_IND_ACK_TOUT); } + /******************************************************************************* ** ** Function gatt_rsp_timeout @@ -1369,7 +1317,8 @@ void gatt_rsp_timeout(TIMER_LIST_ENT *p_tle) } } - GATT_TRACE_WARNING("gatt_rsp_timeout disconnecting..."); + GATT_TRACE_WARNING("gatt_rsp_timeout conn_id=%x op=%u op_sub=%u retry_count=%u disconnecting...", + p_clcb->conn_id, p_clcb->operation, p_clcb->op_subtype, p_clcb->retry_count); gatt_disconnect (p_clcb->p_tcb); } @@ -1394,6 +1343,9 @@ void gatt_ind_ack_timeout(TIMER_LIST_ENT *p_tle) attp_send_cl_msg(((tGATT_TCB *)p_tle->param), 0, GATT_HANDLE_VALUE_CONF, NULL); } +#endif // (GATTC_INCLUDED == TRUE) + +#if (GATTS_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_sr_find_i_rcb_by_handle @@ -1426,7 +1378,7 @@ UINT8 gatt_sr_find_i_rcb_by_handle(UINT16 handle) ** Returns GATT_MAX_SR_PROFILES if not found. Otherwise index of th eservice. ** *******************************************************************************/ -#if (GATTS_INCLUDED == TRUE) + UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst) { UINT8 i_rcb = 0; @@ -1450,7 +1402,7 @@ UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid } return i_rcb; } -#endif ///GATTS_INCLUDED == TRUE + /******************************************************************************* ** ** Function gatt_sr_find_i_rcb_by_handle @@ -1486,6 +1438,7 @@ UINT8 gatt_sr_alloc_rcb(tGATT_HDL_LIST_ELEM *p_list ) return ii; } +#endif ///GATTS_INCLUDED == TRUE /******************************************************************************* ** ** Function gatt_sr_get_sec_info @@ -1811,7 +1764,7 @@ void gatt_clcb_dealloc (tGATT_CLCB *p_clcb) btu_free_timer(&p_clcb->rsp_timer_ent); memset(p_clcb, 0, sizeof(tGATT_CLCB)); list_remove(gatt_cb.p_clcb_list, p_clcb); - p_clcb = NULL; + p_clcb = NULL; } } @@ -2149,6 +2102,7 @@ BOOLEAN gatt_find_specific_app_in_hold_link(tGATT_TCB *p_tcb, tGATT_IF p_gatt_if return found; } +#if (GATTC_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_cmd_enq @@ -2202,6 +2156,7 @@ tGATT_CLCB *gatt_cmd_dequeue(tGATT_TCB *p_tcb, UINT8 *p_op_code) return p_clcb; } +#endif // (GATTC_INCLUDED == TRUE) /******************************************************************************* ** @@ -2370,16 +2325,22 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport) gatt_clcb_dealloc(p_clcb); } } - +#if (GATTC_INCLUDED == TRUE) btu_free_timer (&p_tcb->ind_ack_timer_ent); +#endif // #if (GATTC_INCLUDED == TRUE) +#if (GATTS_INCLUDED == TRUE) btu_free_timer (&p_tcb->conf_timer_ent); - gatt_free_pending_ind(p_tcb); +#endif // (GATTS_INCLUDED == TRUE) +#if (SMP_INCLUDED == TRUE) gatt_free_pending_enc_queue(p_tcb); +#endif // (SMP_INCLUDED == TRUE) +#if (GATTS_INCLUDED == TRUE) gatt_free_pending_prepare_write_queue(p_tcb); -#if (GATTS_INCLUDED) +#endif // (GATTS_INCLUDED == TRUE) +#if (GATTS_INCLUDED == TRUE) fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, osi_free_func); p_tcb->sr_cmd.multi_rsp_q = NULL; -#endif /* #if (GATTS_INCLUDED) */ +#endif /* #if (GATTS_INCLUDED == TRUE) */ for (i = 0; i < GATT_MAX_APPS; i ++) { p_reg = &gatt_cb.cl_rcb[i]; if (p_reg->in_use && p_reg->app_cb.p_conn_cb) { @@ -2393,7 +2354,9 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport) GATT_TRACE_DEBUG ("exit gatt_cleanup_upon_disc "); BTM_Recovery_Pre_State(); } +#if (GATTS_INCLUDED == TRUE) gatt_delete_dev_from_srv_chg_clt_list(bda); +#endif // (GATTS_INCLUDED == TRUE) } /******************************************************************************* ** @@ -2461,7 +2424,7 @@ void gatt_dbg_display_uuid(tBT_UUID bt_uuid) } -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** ** Function gatt_is_bg_dev_for_app @@ -2842,9 +2805,9 @@ BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_ } return ret; } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) - +#endif // #if (GATT_BG_CONN_DEV == TRUE) +#if (SMP_INCLUDED == TRUE) /******************************************************************************* ** ** Function gatt_add_pending_new_srv_start @@ -2862,57 +2825,11 @@ tGATT_PENDING_ENC_CLCB *gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGAT if ((p_buf = (tGATT_PENDING_ENC_CLCB *)osi_malloc((UINT16)sizeof(tGATT_PENDING_ENC_CLCB))) != NULL) { GATT_TRACE_DEBUG ("enqueue a new pending encryption channel clcb"); p_buf->p_clcb = p_clcb; - fixed_queue_enqueue(p_tcb->pending_enc_clcb, p_buf, FIXED_QUEUE_MAX_TIMEOUT); + fixed_queue_enqueue(p_tcb->pending_enc_clcb, p_buf, FIXED_QUEUE_MAX_TIMEOUT); } return p_buf; } -/******************************************************************************* -** -** Function gatt_update_listen_mode -** -** Description update peripheral role listening mode -** -** Returns Pointer to the new service start buffer, NULL no buffer available -** -*******************************************************************************/ -BOOLEAN gatt_update_listen_mode(void) -{ - UINT8 ii = 0; - tGATT_REG *p_reg = &gatt_cb.cl_rcb[0]; - UINT8 listening = 0; - UINT16 connectability, window, interval; - BOOLEAN rt = TRUE; - - for (; ii < GATT_MAX_APPS; ii ++, p_reg ++) { - if ( p_reg->in_use && p_reg->listening > listening) { - listening = p_reg->listening; - } - } - - if (listening == GATT_LISTEN_TO_ALL || - listening == GATT_LISTEN_TO_NONE) { - BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_ALL); - } else { - BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_WL); - } - - if (rt) { - connectability = BTM_ReadConnectability (&window, &interval); - - if (listening != GATT_LISTEN_TO_NONE) { - connectability |= BTM_BLE_CONNECTABLE; - } else { - if ((connectability & BTM_BLE_CONNECTABLE) == 0) { - connectability &= ~BTM_BLE_CONNECTABLE; - } - } - /* turning on the adv now */ - btm_ble_set_connectability(connectability); - } - - return rt; - -} +#endif // (SMP_INCLUDED == TRUE) char *gatt_uuid_to_str(const tBT_UUID *uuid) { diff --git a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h index f9d3cd8e51..933312a46e 100644 --- a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h +++ b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h @@ -76,9 +76,12 @@ typedef UINT8 tGATT_SEC_ACTION; #define GATT_HDR_SIZE 3 /* 1B opcode + 2B handle */ -/* wait for ATT cmd response timeout value */ -#define GATT_WAIT_FOR_RSP_TOUT 30 -#define GATT_WAIT_FOR_DISC_RSP_TOUT 15 +/** + * Wait for ATT cmd response timeout value (40 seconds). + * The max connection supervision timeout is 32 seconds, + * And The ATT cmd may not be sent out by controller immediately. + */ +#define GATT_WAIT_FOR_RSP_TOUT 40 #define GATT_REQ_RETRY_LIMIT 2 #define GATT_WAIT_FOR_IND_ACK_TOUT 5 @@ -373,8 +376,11 @@ typedef struct{ }tGATT_PREPARE_WRITE_RECORD; typedef struct { +#if (SMP_INCLUDED == TRUE) fixed_queue_t *pending_enc_clcb; /* pending encryption channel q */ tGATT_SEC_ACTION sec_act; +#endif // (SMP_INCLUDED == TRUE) + BD_ADDR peer_bda; tBT_TRANSPORT transport; UINT32 trans_id; @@ -391,30 +397,33 @@ typedef struct { /* server response data */ #if (GATTS_INCLUDED == TRUE) tGATT_SR_CMD sr_cmd; -#endif ///GATTS_INCLUDED == TRUE UINT16 indicate_handle; - fixed_queue_t *pending_ind_q; TIMER_LIST_ENT conf_timer_ent; /* peer confirm to indication timer */ +#endif ///GATTS_INCLUDED == TRUE UINT8 prep_cnt[GATT_MAX_APPS]; +#if (GATTC_INCLUDED == TRUE) UINT8 ind_count; tGATT_CMD_Q cl_cmd_q[GATT_CL_MAX_LCB]; TIMER_LIST_ENT ind_ack_timer_ent; /* local app confirm to indication timer */ +#endif // (GATTC_INCLUDED == TRUE) UINT8 pending_cl_req; UINT8 next_slot_inq; /* index of next available slot in queue */ - +#if (GATTS_ROBUST_CACHING_ENABLED == TRUE) /* client supported feature */ UINT8 cl_supp_feat; /* server supported feature */ UINT8 sr_supp_feat; /* if false, should handle database out of sync */ BOOLEAN is_robust_cache_change_aware; - +#endif // (GATTS_ROBUST_CACHING_ENABLED == TRUE) BOOLEAN in_use; UINT8 tcb_idx; +#if (GATTS_INCLUDED == TRUE) tGATT_PREPARE_WRITE_RECORD prepare_write_record; /* prepare write packets record */ +#endif // (GATTS_INCLUDED == TRUE) } tGATT_TCB; @@ -480,14 +489,14 @@ typedef struct { UINT32 service_change; } tGATT_SVC_CHG; -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) typedef struct { tGATT_IF gatt_if[GATT_MAX_APPS]; tGATT_IF listen_gif[GATT_MAX_APPS]; BD_ADDR remote_bda; BOOLEAN in_use; } tGATT_BG_CONN_DEV; -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) #define GATT_SVC_CHANGED_CONNECTING 1 /* wait for connection */ #define GATT_SVC_CHANGED_SERVICE 2 /* GATT service discovery */ @@ -511,11 +520,11 @@ typedef struct { typedef struct { list_t *p_tcb_list; - fixed_queue_t *sign_op_queue; - +#if (GATTS_INCLUDED == TRUE) tGATT_SR_REG sr_reg[GATT_MAX_SR_PROFILES]; UINT16 next_handle; /* next available handle */ tGATT_SVC_CHG gattp_attr; /* GATT profile attribute service change */ +#endif // (GATTS_INCLUDED == TRUE) tGATT_IF gatt_if; #if (GATTS_INCLUDED == TRUE) tGATT_HDL_LIST_INFO hdl_list_info; @@ -523,13 +532,13 @@ typedef struct { tGATT_SRV_LIST_INFO srv_list_info; tGATT_SRV_LIST_ELEM srv_list[GATT_MAX_SR_PROFILES]; #endif ///GATTS_INCLUDED == TRUE +#if (GATTS_INCLUDED == TRUE) fixed_queue_t *srv_chg_clt_q; /* service change clients queue */ fixed_queue_t *pending_new_srv_start_q; /* pending new service start queue */ +#endif // (GATTS_INCLUDED == TRUE) tGATT_REG cl_rcb[GATT_MAX_APPS]; list_t *p_clcb_list; /* connection link control block*/ - tGATT_SCCB sccb[GATT_MAX_SCCB]; /* sign complete callback function GATT_MAX_SCCB <= GATT_CL_MAX_LCB */ UINT8 trace_level; - UINT16 def_mtu_size; #if GATT_CONFORMANCE_TESTING == TRUE BOOLEAN enable_err_rsp; @@ -553,14 +562,19 @@ typedef struct { tGATT_APPL_INFO cb_info; - +#if (GATTS_INCLUDED == TRUE) tGATT_HDL_CFG hdl_cfg; -#if (tGATT_BG_CONN_DEV == TRUE) +#endif // (GATTS_INCLUDED == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) tGATT_BG_CONN_DEV bgconn_dev[GATT_MAX_BG_CONN_DEV]; -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) +#if (GATTC_INCLUDED == TRUE) BOOLEAN auto_disc; /* internal use: true for auto discovering after connected */ +#endif // (GATTC_INCLUDED == TRUE) +#if (GATTS_INCLUDED == TRUE) UINT8 srv_chg_mode; /* internal use: service change mode */ tGATTS_RSP rsp; /* use to read internal service attribute */ +#endif // (GATTS_INCLUDED == TRUE) } tGATT_CB; typedef struct{ @@ -597,8 +611,8 @@ extern void gatt_free(void); /* from gatt_main.c */ extern BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb); -extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_type, tBT_TRANSPORT transport, BOOLEAN is_aux); -extern BOOLEAN gatt_connect (BD_ADDR rem_bda, tBLE_ADDR_TYPE bd_addr_type, tGATT_TCB *p_tcb, tBT_TRANSPORT transport, BOOLEAN is_aux); +extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_type, tBT_TRANSPORT transport, BOOLEAN is_aux, BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent); +extern BOOLEAN gatt_connect (BD_ADDR rem_bda, tBLE_ADDR_TYPE bd_addr_type, tGATT_TCB *p_tcb, tBT_TRANSPORT transport, BOOLEAN is_aux, BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent); extern void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf); extern void gatt_update_app_use_link_flag ( tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link); @@ -649,10 +663,8 @@ extern tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda); extern BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx, tBT_TRANSPORT *p_transport); extern void gatt_set_srv_chg(void); extern void gatt_delete_dev_from_srv_chg_clt_list(BD_ADDR bd_addr); -extern tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB *p_tcb, tGATT_VALUE *p_ind); extern tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start( tGATTS_HNDL_RANGE *p_new_srv_start); extern void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id); -extern BOOLEAN gatt_update_listen_mode(void); extern BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb); /* reserved handle list */ @@ -670,7 +682,7 @@ extern BOOLEAN gatt_add_an_item_to_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_L extern BOOLEAN gatt_remove_an_item_from_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIST_ELEM *p_remove); extern tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg); -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) /* for background connection */ extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initiator); extern BOOLEAN gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV *p_dev, tGATT_IF gatt_if); @@ -680,7 +692,7 @@ extern BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if); extern tGATT_BG_CONN_DEV *gatt_find_bg_dev(BD_ADDR remote_bda); extern void gatt_deregister_bgdev_list(tGATT_IF gatt_if); extern void gatt_reset_bgdev_list(void); -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) /* server function */ extern UINT8 gatt_sr_find_i_rcb_by_handle(UINT16 handle); diff --git a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c index 5ad13216f7..fef574fd6a 100644 --- a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c @@ -618,6 +618,8 @@ BOOLEAN btsnd_hcic_ble_start_enc (UINT16 handle, UINT8 rand[HCIC_BLE_RAND_DI_SIZ BT_HDR *p; UINT8 *pp; + HCI_TRACE_DEBUG("%s handle=%u LTK=%s", __func__, handle, bt_hex2str(ltk, HCIC_BLE_ENCRYT_KEY_SIZE)); + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_START_ENC)) == NULL) { return (FALSE); } @@ -644,6 +646,8 @@ BOOLEAN btsnd_hcic_ble_ltk_req_reply (UINT16 handle, UINT8 ltk[HCIC_BLE_ENCRYT_K BT_HDR *p; UINT8 *pp; + HCI_TRACE_DEBUG("%s handle=%u LTK=%s", __func__, handle, bt_hex2str(ltk, HCIC_BLE_ENCRYT_KEY_SIZE)); + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_LTK_REQ_REPLY)) == NULL) { return (FALSE); } @@ -668,6 +672,8 @@ BOOLEAN btsnd_hcic_ble_ltk_req_neg_reply (UINT16 handle) BT_HDR *p; UINT8 *pp; + HCI_TRACE_WARNING("%s handle=%u", __func__, handle); + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_LTK_REQ_NEG_REPLY)) == NULL) { return (FALSE); } @@ -1221,7 +1227,55 @@ UINT8 btsnd_hcic_ble_set_extend_rand_address(UINT8 adv_handle, BD_ADDR rand_addr return btu_hcif_send_cmd_sync (LOCAL_BR_EDR_CONTROLLER_ID, p); } +#if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) +UINT8 btsnd_hcic_ble_set_ext_adv_params_v2(UINT8 adv_handle, UINT16 properties, UINT32 interval_min, + UINT32 interval_max, UINT8 channel_map, UINT8 own_addr_type, + UINT8 peer_addr_type, BD_ADDR peer_addr, + UINT8 adv_filter_policy, INT8 adv_tx_power, + UINT8 primary_adv_phy, UINT8 secondary_adv_max_skip, + UINT8 secondary_adv_phy, + UINT8 adv_sid, UINT8 scan_req_ntf_enable, + UINT8 primary_adv_phy_options, UINT8 secondary_adv_phy_options) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_EVENT("%s, adv_handle = %d, properties = %d, interval_min = %d, interval_max = %d, channel_map = %d,\n\ + own_addr_type = %d, peer_addr_type = %d, adv_filter_policy = %d,\n\ + adv_tx_power = %d, primary_adv_phy = %d, secondary_adv_max_skip = %d, secondary_adv_phy = %d,\n\ + adv_sid = %d, scan_req_ntf_enable = %d, primary_phy_options %d secondary_phy_options %d", __func__, adv_handle, properties, interval_min, interval_max, + channel_map, own_addr_type, peer_addr_type, adv_filter_policy, adv_tx_power, + primary_adv_phy, secondary_adv_max_skip, secondary_adv_phy, adv_sid, scan_req_ntf_enable, + primary_adv_phy_options, secondary_adv_phy_options); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_EXT_ADV_SET_PARAMS + 2); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_EXT_ADV_PARAM_V2); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_EXT_ADV_SET_PARAMS + 2); + + UINT8_TO_STREAM(pp, adv_handle); + UINT16_TO_STREAM(pp, properties); + UINT24_TO_STREAM(pp, interval_min); + UINT24_TO_STREAM(pp, interval_max); + UINT8_TO_STREAM(pp, channel_map); + UINT8_TO_STREAM(pp, own_addr_type); + UINT8_TO_STREAM(pp, peer_addr_type); + BDADDR_TO_STREAM (pp, peer_addr); + UINT8_TO_STREAM(pp, adv_filter_policy); + INT8_TO_STREAM(pp, adv_tx_power); + UINT8_TO_STREAM(pp, primary_adv_phy); + UINT8_TO_STREAM(pp, secondary_adv_max_skip); + UINT8_TO_STREAM(pp, secondary_adv_phy); + UINT8_TO_STREAM(pp, adv_sid); + UINT8_TO_STREAM(pp, scan_req_ntf_enable); + UINT8_TO_STREAM(pp, primary_adv_phy_options); + UINT8_TO_STREAM(pp, secondary_adv_phy_options); + + return btu_hcif_send_cmd_sync (LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +#else UINT8 btsnd_hcic_ble_set_ext_adv_params(UINT8 adv_handle, UINT16 properties, UINT32 interval_min, UINT32 interval_max, UINT8 channel_map, UINT8 own_addr_type, UINT8 peer_addr_type, BD_ADDR peer_addr, @@ -1264,8 +1318,7 @@ UINT8 btsnd_hcic_ble_set_ext_adv_params(UINT8 adv_handle, UINT16 properties, UIN return btu_hcif_send_cmd_sync (LOCAL_BR_EDR_CONTROLLER_ID, p); } - -bool ext_adv_flag = false; +#endif // #if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) UINT8 btsnd_hcic_ble_set_ext_adv_data(UINT8 adv_handle, UINT8 operation, UINT8 fragment_prefrence, @@ -1275,7 +1328,6 @@ UINT8 btsnd_hcic_ble_set_ext_adv_data(UINT8 adv_handle, UINT8 *pp; HCI_TRACE_EVENT("%s, adv_handle = %d, operation = %d, fragment_prefrence = %d,\ data_len = %d", __func__, adv_handle, operation, fragment_prefrence, data_len); - ext_adv_flag = true; HCIC_BLE_CMD_CREATED(p, pp, data_len + 4); UINT16_TO_STREAM(pp, HCI_BLE_SET_EXT_ADV_DATA); @@ -1421,10 +1473,40 @@ UINT8 btsnd_hcic_ble_clear_adv_set(void) #endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +UINT8 btsnd_hcic_ble_set_periodic_adv_params_v2(UINT8 adv_handle, UINT16 interval_min, UINT16 interval_max, + UINT16 propertics, UINT8 num_subevents, UINT8 subevent_interval, + UINT8 rsp_slot_delay, UINT8 rsp_slot_spacing, UINT8 num_rsp_slots) +{ + BT_HDR *p; + UINT8 *pp; + HCI_TRACE_EVENT("%s, adv_handle = %d, interval_min = %d, interval_max = %d, propertics = %d num_subevents = %d subevent_interval = %d rsp_slot_delay %d rsp_slot_spacing %d num_rsp_slots %d", + __func__, adv_handle, interval_min, interval_max, propertics, num_subevents, subevent_interval, rsp_slot_delay, rsp_slot_spacing, num_rsp_slots); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_PERIODIC_ADV_PARAMS_V2); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_PERIOD_ADV_PARAMS_V2); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_PERIODIC_ADV_PARAMS_V2); + + UINT8_TO_STREAM(pp, adv_handle); + UINT16_TO_STREAM(pp, interval_min); + UINT16_TO_STREAM(pp, interval_max); + UINT16_TO_STREAM(pp, propertics); + UINT8_TO_STREAM(pp, num_subevents); + UINT8_TO_STREAM(pp, subevent_interval); + UINT8_TO_STREAM(pp, rsp_slot_delay); + UINT8_TO_STREAM(pp, rsp_slot_spacing); + UINT8_TO_STREAM(pp, num_rsp_slots); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); + +} + +#else UINT8 btsnd_hcic_ble_set_periodic_adv_params(UINT8 adv_handle, UINT16 interval_min, UINT16 interval_max, - UINT8 propertics) + UINT16 propertics) { BT_HDR *p; UINT8 *pp; @@ -1445,6 +1527,9 @@ UINT8 btsnd_hcic_ble_set_periodic_adv_params(UINT8 adv_handle, } +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) + + UINT8 btsnd_hcic_ble_set_periodic_adv_data(UINT8 adv_handle, UINT8 operation, UINT8 len, @@ -1618,6 +1703,81 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn) } +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +BOOLEAN btsnd_hcic_ble_create_ext_conn_v2(tHCI_CreatExtConn *p_conn) +{ + BT_HDR *p; + UINT8 *pp; + tHCI_ExtConnParams *params; + HCI_TRACE_EVENT("%s", __func__); + uint8_t size = HCIC_PARAM_SIZE_EXT_CONN_CREATE_BASE + 2; + + if (p_conn->init_phy_mask & 0x01) { + size += sizeof(tHCI_ExtConnParams); + } + + if (p_conn->init_phy_mask & 0x02) { + size += sizeof(tHCI_ExtConnParams); + } + + if (p_conn->init_phy_mask & 0x04) { + size += sizeof(tHCI_ExtConnParams); + } + + HCIC_BLE_CMD_CREATED(p, pp, size); + + UINT16_TO_STREAM(pp, HCI_BLE_EXT_CREATE_CONN_V2); + UINT8_TO_STREAM(pp, size); + UINT8_TO_STREAM(pp, p_conn->adv_handle); + UINT8_TO_STREAM(pp, p_conn->subevent); + UINT8_TO_STREAM(pp, p_conn->filter_policy); + UINT8_TO_STREAM(pp, p_conn->own_addr_type); + UINT8_TO_STREAM(pp, p_conn->peer_addr_type); + BDADDR_TO_STREAM(pp, p_conn->peer_addr); + UINT8_TO_STREAM(pp, p_conn->init_phy_mask); + + if (p_conn->init_phy_mask & 0x01) { + params = &p_conn->params[0]; + UINT16_TO_STREAM(pp, params->scan_interval); + UINT16_TO_STREAM(pp, params->scan_window); + UINT16_TO_STREAM(pp, params->conn_interval_min); + UINT16_TO_STREAM(pp, params->conn_interval_max); + UINT16_TO_STREAM(pp, params->conn_latency); + UINT16_TO_STREAM(pp, params->sup_timeout); + UINT16_TO_STREAM(pp, params->min_ce_len ? params->min_ce_len : BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->max_ce_len ? params->max_ce_len : BLE_CE_LEN_MIN); + } + + if (p_conn->init_phy_mask & 0x02) { + params = &p_conn->params[1]; + UINT16_TO_STREAM(pp, params->scan_interval); + UINT16_TO_STREAM(pp, params->scan_window); + UINT16_TO_STREAM(pp, params->conn_interval_min); + UINT16_TO_STREAM(pp, params->conn_interval_max); + UINT16_TO_STREAM(pp, params->conn_latency); + UINT16_TO_STREAM(pp, params->sup_timeout); + UINT16_TO_STREAM(pp, params->min_ce_len ? params->min_ce_len : BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->max_ce_len ? params->max_ce_len : BLE_CE_LEN_MIN); + } + + if (p_conn->init_phy_mask & 0x04) { + params = &p_conn->params[2]; + UINT16_TO_STREAM(pp, params->scan_interval); + UINT16_TO_STREAM(pp, params->scan_window); + UINT16_TO_STREAM(pp, params->conn_interval_min); + UINT16_TO_STREAM(pp, params->conn_interval_max); + UINT16_TO_STREAM(pp, params->conn_latency); + UINT16_TO_STREAM(pp, params->sup_timeout); + UINT16_TO_STREAM(pp, params->min_ce_len ? params->min_ce_len : BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->max_ce_len ? params->max_ce_len : BLE_CE_LEN_MIN); + } + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; + +} +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) + #if (BLE_50_EXTEND_SYNC_EN == TRUE) BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 option, UINT8 adv_sid, UINT8 adv_addr_type, BD_ADDR adv_addr, @@ -2808,3 +2968,435 @@ UINT8 btsnd_hcic_ble_set_host_feature(uint16_t bit_num, uint8_t bit_val) return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +UINT8 btsnd_hcic_ble_set_periodic_adv_subevt_data(UINT8 adv_handle, UINT8 num_subevents_with_data, ble_subevent_params *subevent_params) +{ + BT_HDR *p; + UINT8 *pp; + uint8_t param_len = 0; + + HCI_TRACE_DEBUG("hci set PA subevent data, adv_handle %d num_subevents_with_data %d", adv_handle, num_subevents_with_data); + + if (!subevent_params) { + HCI_TRACE_ERROR("%s error\n", __func__); + return HCI_ERR_ILLEGAL_PARAMETER_FMT; + } + param_len += HCIC_PARAM_SIZE_SET_PA_SUBEVT_DATA_PARAMS_LEN; + + for (UINT8 i = 0; i < num_subevents_with_data; i++) + { + HCI_TRACE_DEBUG("subevent_params: subevent %d response_slot_start %d response_slot_count %d subevent_data_len %d", + subevent_params[i].subevent, subevent_params[i].response_slot_start, subevent_params[i].response_slot_count, + subevent_params[i].subevent_data_len); + + if (subevent_params[i].subevent_data_len) { + esp_log_buffer_hex_internal("data", subevent_params[i].data, subevent_params[i].subevent_data_len, ESP_LOG_DEBUG); + } + + param_len += (4 + subevent_params[i].subevent_data_len); + } + + HCIC_BLE_CMD_CREATED(p, pp, param_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_PERIOD_ADV_SUBEVT_DATA); + UINT8_TO_STREAM(pp, param_len); + + UINT8_TO_STREAM(pp, adv_handle); + UINT8_TO_STREAM(pp, num_subevents_with_data); + for (UINT8 i = 0; i < num_subevents_with_data; i++) + { + UINT8_TO_STREAM(pp, subevent_params[i].subevent); + UINT8_TO_STREAM(pp, subevent_params[i].response_slot_start); + UINT8_TO_STREAM(pp, subevent_params[i].response_slot_count); + UINT8_TO_STREAM(pp, subevent_params[i].subevent_data_len); + if (subevent_params[i].subevent_data_len) { + ARRAY_TO_STREAM(pp, subevent_params[i].data, subevent_params[i].subevent_data_len); + } + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_set_periodic_adv_rsp_data(UINT16 sync_handle, UINT16 req_evt, UINT8 req_subevt, UINT8 rsp_subevt, UINT8 rsp_slot, UINT8 rsp_data_len, UINT8 *rsp_data) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set PA rsp data, sync_handle %d req_evt %d req_subevt %d rsp_subevt %d rsp_slot %d rsp_data_len %d", + sync_handle, req_evt, req_subevt, rsp_subevt, rsp_slot, rsp_data_len); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_PA_RESPONSE_DATA_PARAMS_LEN + rsp_data_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_PERIOD_ADV_RSP_DATA); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_PA_RESPONSE_DATA_PARAMS_LEN + rsp_data_len); + + UINT16_TO_STREAM(pp, sync_handle); + UINT16_TO_STREAM(pp, req_evt); + UINT8_TO_STREAM(pp, req_subevt); + UINT8_TO_STREAM(pp, rsp_subevt); + UINT8_TO_STREAM(pp, rsp_slot); + UINT8_TO_STREAM(pp, rsp_data_len); + + if (rsp_data) { + ARRAY_TO_STREAM(pp, rsp_data, rsp_data_len); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_set_periodic_sync_subevt(UINT16 sync_handle, UINT16 periodic_adv_properties, UINT8 num_subevents_to_sync, UINT8 *subevt) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set PA sync subevent, sync_handle %d periodic_adv_properties %d num_subevents_to_sync %d", + sync_handle, periodic_adv_properties, num_subevents_to_sync); + for (UINT8 i = 0; i < num_subevents_to_sync; i++) + { + HCI_TRACE_DEBUG("subevt[%d] = %d", i, subevt[i]); + } + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_PA_SYNC_SUBEVT_PARAMS_LEN + num_subevents_to_sync); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_PERIOD_SYNC_SUBEVT); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_PA_SYNC_SUBEVT_PARAMS_LEN + num_subevents_to_sync); + + UINT16_TO_STREAM(pp, sync_handle); + UINT16_TO_STREAM(pp, periodic_adv_properties); + UINT8_TO_STREAM(pp, num_subevents_to_sync); + for (UINT8 i = 0; i < num_subevents_to_sync; i++) + { + UINT8_TO_STREAM(pp, subevt[i]); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +UINT8 btsnd_hcic_ble_cs_read_local_supported_caps(void) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs read local supported caps"); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_READ_LOCAL_SUPP_CAPS_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_READ_LOCAL_SUPP_CAPS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_LOCAL_SUPP_CAPS_PARAMS_LEN); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return (TRUE); +} + +UINT8 btsnd_hcic_ble_cs_read_remote_supported_capabilities(UINT16 conn_handle) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs read remote supported caps, conn_handle %d", conn_handle); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_READ_REMOTE_SUPP_CAPS_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_READ_REMOTE_SUPP_CAPS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_REMOTE_SUPP_CAPS_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return (TRUE); +} + +UINT8 btsnd_hcic_ble_cs_write_cached_remote_supported_capabilities(UINT16 conn_handle, UINT8 num_config_supported, UINT16 max_consecutive_proc_supported, + UINT8 num_ant_supported, UINT8 max_ant_paths_supported, UINT8 roles_supported, + UINT8 modes_supported, UINT8 rtt_capability, UINT8 rtt_aa_only_n, + UINT8 rtt_sounding_n, UINT8 rtt_random_payload_n, UINT16 NADM_sounding_capability, + UINT16 NADM_random_capability, UINT8 cs_sync_phys_supported, UINT16 subfeatures_supported, + UINT16 T_IP1_times_supported, UINT16 T_IP2_times_supported, UINT16 T_FCS_times_supported, + UINT16 T_PM_times_supported, UINT8 T_SW_times_supported, UINT8 TX_SNR_capability) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs write cached remote supported caps"); + HCI_TRACE_DEBUG("conn_handle %d num_config_supported %d max_consecutive_proc_supported %d, num_ant_supported %d max_ant_paths_supported %d roles_supported %d,\ + modes_supported %d, rtt_capability %d, rtt_aa_only_n %d, rtt_sounding_n %d, rtt_random_payload_n %d, NADM_sounding_capability %d, NADM_random_capability %d\ + ,cs_sync_phys_supported %d, subfeatures_supported %d, T_IP1_times_supported %d, T_IP2_times_supported %d, T_FCS_times_supported %d, T_PM_times_supported %d\ + ,T_SW_times_supported %d, TX_SNR_capability %d", + conn_handle, num_config_supported, max_consecutive_proc_supported, num_ant_supported, max_ant_paths_supported, roles_supported, + modes_supported, rtt_capability, rtt_aa_only_n, rtt_sounding_n, rtt_random_payload_n, NADM_sounding_capability, + NADM_random_capability, cs_sync_phys_supported, subfeatures_supported, T_IP1_times_supported, T_IP2_times_supported, T_FCS_times_supported, + T_PM_times_supported, T_SW_times_supported, TX_SNR_capability); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_WRITE_CACHE_REMOTE_SUPP_CAPS_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_WRITE_CACHED_REMOTE_SUPP_CAPS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_CACHE_REMOTE_SUPP_CAPS_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, num_config_supported); + UINT16_TO_STREAM(pp, max_consecutive_proc_supported); + UINT8_TO_STREAM(pp, num_ant_supported); + UINT8_TO_STREAM(pp, max_ant_paths_supported); + UINT8_TO_STREAM(pp, roles_supported); + UINT8_TO_STREAM(pp, modes_supported); + UINT8_TO_STREAM(pp, rtt_capability); + UINT8_TO_STREAM(pp, rtt_aa_only_n); + UINT8_TO_STREAM(pp, rtt_sounding_n); + UINT8_TO_STREAM(pp, rtt_random_payload_n); + UINT16_TO_STREAM(pp, NADM_sounding_capability); + UINT16_TO_STREAM(pp, NADM_random_capability); + UINT8_TO_STREAM(pp, cs_sync_phys_supported); + UINT16_TO_STREAM(pp, subfeatures_supported); + UINT16_TO_STREAM(pp, T_IP1_times_supported); + UINT16_TO_STREAM(pp, T_IP2_times_supported); + UINT16_TO_STREAM(pp, T_FCS_times_supported); + UINT16_TO_STREAM(pp, T_PM_times_supported); + UINT8_TO_STREAM(pp, T_SW_times_supported); + UINT8_TO_STREAM(pp, TX_SNR_capability); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); + +} + +UINT8 btsnd_hcic_ble_cs_security_enable(UINT16 conn_handle) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs security enable conn_handle %d", conn_handle); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SECURITY_ENABLE_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_SECURITY_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SECURITY_ENABLE_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return (TRUE); +} + +UINT8 btsnd_hcic_ble_cs_set_default_settings(UINT16 conn_handle, UINT8 role_enable, UINT8 cs_sync_ant_selection, INT8 max_tx_power) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs set default settings, conn_handle %d role_enable %d cs_sync_ant_selection %d max_tx_power %d", conn_handle, role_enable, cs_sync_ant_selection, max_tx_power); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_DEFAULT_SETTINGS_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_SET_DEFAULT_SETTINGS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_DEFAULT_SETTINGS_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, role_enable); + UINT8_TO_STREAM(pp, cs_sync_ant_selection); + INT8_TO_STREAM(pp, max_tx_power); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_cs_read_remote_fae_table(UINT16 conn_handle) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs read remote fae table, conn_handle %d", conn_handle); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_READ_REMOTE_FAE_TAB_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_READ_REMOTE_FAE_TABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_REMOTE_FAE_TAB_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return (TRUE); +} + +UINT8 btsnd_hcic_ble_cs_write_cached_remote_fae_table(UINT16 conn_handle, UINT8 *remote_fae_table) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs write cached remote fae table, conn_handle %d", conn_handle); + esp_log_buffer_hex_internal("remote_fae_table", remote_fae_table, 72, ESP_LOG_DEBUG); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_WRITE_CACHED_REMOTE_FAE_TABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + ARRAY_TO_STREAM(pp, remote_fae_table, 72); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_cs_create_config(UINT16 conn_handle, UINT8 config_id, UINT8 create_context, + UINT8 main_mode_type, UINT8 sub_mode_type, UINT8 min_main_mode_steps, + UINT8 max_main_mode_steps, UINT8 main_mode_repetition, UINT8 mode_0_steps, + UINT8 role, UINT8 rtt_type, UINT8 cs_sync_phy, UINT8 *channel_map, + UINT8 channel_map_repetition, UINT8 channel_selection_type, UINT8 ch3c_shape, + UINT8 ch3c_jump,UINT8 reserved) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs create config"); + HCI_TRACE_DEBUG("conn_handle %d config_id %d create_context %d main_mode_type %d sub_mode_type %d min_main_mode_steps %d max_main_mode_steps\ + %d main_mode_repetition %d mode_0_steps %d role %d rtt_type %d cs_sync_phy %d, channel_map_repetition %d, channel_selection_type %d\ + ch3c_shape %d ch3c_jump %d,reserved %d", conn_handle, config_id, create_context, main_mode_type, sub_mode_type, min_main_mode_steps, max_main_mode_steps,\ + main_mode_repetition, mode_0_steps, role, rtt_type, cs_sync_phy, channel_map_repetition, channel_selection_type\ + ,ch3c_shape, ch3c_jump, reserved); + esp_log_buffer_hex_internal("channel_map", channel_map, 10, ESP_LOG_DEBUG); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_CREATE_CONFIG_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_CREATE_CONFIG); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CREATE_CONFIG_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, config_id); + UINT8_TO_STREAM(pp, create_context); + UINT8_TO_STREAM(pp, main_mode_type); + UINT8_TO_STREAM(pp, sub_mode_type); + UINT8_TO_STREAM(pp, min_main_mode_steps); + UINT8_TO_STREAM(pp, max_main_mode_steps); + UINT8_TO_STREAM(pp, main_mode_repetition); + UINT8_TO_STREAM(pp, mode_0_steps); + UINT8_TO_STREAM(pp, role); + UINT8_TO_STREAM(pp, rtt_type); + UINT8_TO_STREAM(pp, cs_sync_phy); + ARRAY_TO_STREAM(pp, channel_map, 10); + UINT8_TO_STREAM(pp, channel_map_repetition); + UINT8_TO_STREAM(pp, channel_selection_type); + UINT8_TO_STREAM(pp, ch3c_shape); + UINT8_TO_STREAM(pp, ch3c_jump); + UINT8_TO_STREAM(pp, reserved); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return (TRUE); +} + +UINT8 btsnd_hcic_ble_cs_remove_config(UINT16 conn_handle, UINT8 config_id) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs remove config, conn_handle %d config_id %d", conn_handle, config_id); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_REMOVE_CONFIG_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_REMOVE_CONFIG); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_REMOVE_CONFIG_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, config_id); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + + return TRUE; +} + +UINT8 btsnd_hcic_ble_cs_set_channel_classification(UINT8 *channel_class) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs set channel class"); + esp_log_buffer_hex_internal("channel", channel_class, 10, ESP_LOG_DEBUG); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_CHANNEL_CLASS_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_SET_CAHNNEL_CLASS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_CHANNEL_CLASS_PARAMS_LEN); + ARRAY_TO_STREAM(pp, channel_class, 10); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_cs_set_procedure_params(UINT16 conn_handle, UINT8 config_id, UINT16 max_procedure_len, + UINT16 min_procedure_interval, UINT16 max_procedure_interval, + UINT16 max_procedure_count, UINT32 min_subevent_len, + UINT32 max_subevent_len, UINT8 tone_ant_config_selection, + UINT8 phy, UINT8 tx_power_delta, UINT8 preferred_peer_antenna, + UINT8 SNR_control_initiator, UINT8 SNR_control_reflector) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs set procedure params"); + HCI_TRACE_DEBUG("conn_handle %d config_id %d max_procedure_len %d min_procedure_interval %d max_procedure_interval %d\ + max_procedure_count %d min_subevent_len %d max_subevent_len %d tone_ant_config_selection %d phy %d tx_power_delta %d,\ + preferred_peer_antenna %d SNR_control_initiator %d SNR_control_reflector %d\n", + conn_handle, config_id, max_procedure_len, min_procedure_interval, max_procedure_interval, max_procedure_count, min_subevent_len, max_subevent_len, + tone_ant_config_selection, phy, tx_power_delta, preferred_peer_antenna, SNR_control_initiator, SNR_control_reflector); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_PROCEDURE_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_SET_PROCEDURE_PARAMS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_PROCEDURE_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, config_id); + UINT16_TO_STREAM(pp, max_procedure_len); + UINT16_TO_STREAM(pp, min_procedure_interval); + UINT16_TO_STREAM(pp, max_procedure_interval); + UINT16_TO_STREAM(pp, max_procedure_count); + UINT24_TO_STREAM(pp, min_subevent_len); + UINT24_TO_STREAM(pp, max_subevent_len); + UINT8_TO_STREAM(pp, tone_ant_config_selection); + UINT8_TO_STREAM(pp, phy); + UINT8_TO_STREAM(pp, tx_power_delta); + UINT8_TO_STREAM(pp, preferred_peer_antenna); + UINT8_TO_STREAM(pp, SNR_control_initiator); + UINT8_TO_STREAM(pp, SNR_control_reflector); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_cs_procedure_enable(UINT16 conn_handle, UINT8 config_id, UINT8 enable) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("cs set procedure enable, conn_handle %d config_id %d enable %d", conn_handle, config_id, enable); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_PROCEDURE_ENABLE_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CS_SET_PROCEDURE_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_PROCEDURE_ENABLE_PARAMS_LEN); + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, config_id); + UINT8_TO_STREAM(pp, enable); + + btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); + + return TRUE; +} +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_api.h index 3415df5de3..3f932d087d 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_api.h @@ -80,19 +80,6 @@ enum { typedef uint8_t tBTM_STATUS; -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) -typedef enum { - BTM_BR_ONE, /*0 First state or BR/EDR scan 1*/ - BTM_BLE_ONE, /*1BLE scan 1*/ - BTM_BR_TWO, /*2 BR/EDR scan 2*/ - BTM_BLE_TWO, /*3 BLE scan 2*/ - BTM_FINISH, /*4 End of Interleave Scan, or normal scan*/ - BTM_NO_INTERLEAVING /*5 No Interleaving*/ -} btm_inq_state; -#endif - - - /************************* ** Device Control Types **************************/ @@ -647,9 +634,6 @@ typedef struct { /* contains the parameters passed to the inquiry fun BOOLEAN report_dup; /* report duplicated inquiry response with higher RSSI value */ UINT8 filter_cond_type; /* new devices, BD ADDR, COD, or No filtering */ tBTM_INQ_FILT_COND filter_cond; /* filter value based on filter cond type */ -#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE) - UINT8 intl_duration[4]; /*duration array storing the interleave scan's time portions*/ -#endif } tBTM_INQ_PARMS; #define BTM_INQ_RESULT_BR 0x01 @@ -3046,28 +3030,6 @@ tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL ** *******************************************************************************/ tBTM_STATUS BTM_ReadChannelMap(BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb); -#if (BLE_HOST_READ_TX_POWER_EN == TRUE) -/******************************************************************************* -** -** Function BTM_ReadTxPower -** -** Description This function is called to read the current connection -** TX power of the connection. The TX power level results -** are returned in the callback. -** (tBTM_RSSI_RESULTS) -** -** Returns BTM_CMD_STARTED if command issued to controller. -** BTM_NO_RESOURCES if couldn't allocate memory to issue command -** BTM_UNKNOWN_ADDR if no active link with bd addr specified -** BTM_BUSY if command is already in progress -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda, - tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb); - -tBTM_STATUS BTM_BleReadAdvTxPower(tBTM_CMPL_CB *p_cb); -#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) void BTM_BleGetWhiteListSize(uint16_t *length); diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h index e696fe65cf..eaefaf6a79 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h @@ -57,13 +57,6 @@ typedef UINT32 tBTM_BLE_REF_VALUE; #define BTM_BLE_SCAN_MODE_NONE 0xff typedef UINT8 tBLE_SCAN_MODE; -#define BTM_BLE_BATCH_SCAN_MODE_DISABLE 0 -#define BTM_BLE_BATCH_SCAN_MODE_PASS 1 -#define BTM_BLE_BATCH_SCAN_MODE_ACTI 2 -#define BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI 3 - -typedef UINT8 tBTM_BLE_BATCH_SCAN_MODE; - /* advertising channel map */ #define BTM_BLE_ADV_CHNL_37 (0x01 << 0) #define BTM_BLE_ADV_CHNL_38 (0x01 << 1) @@ -129,8 +122,6 @@ typedef UINT8 tBTM_BLE_SFP; #define BTM_BLE_SCAN_INT_MAX 0x4000 #define BTM_BLE_SCAN_WIN_MIN 0x0004 #define BTM_BLE_SCAN_WIN_MAX 0x4000 -#define BTM_BLE_EXT_SCAN_INT_MAX 0x00FFFFFF -#define BTM_BLE_EXT_SCAN_WIN_MAX 0xFFFF #define BTM_BLE_CONN_INT_MIN 0x0006 #define BTM_BLE_CONN_INT_MAX 0x0C80 #define BTM_BLE_CONN_LATENCY_MAX 499 @@ -393,22 +384,7 @@ typedef UINT8 tBTM_BLE_AD_TYPE; typedef UINT8 tBTM_BLE_ADV_TX_POWER; /* adv tx power in dBm */ -typedef struct { -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - UINT8 adv_inst_max; /* max adv instance supported in controller */ -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - UINT8 rpa_offloading; - UINT16 tot_scan_results_strg; - UINT8 max_irk_list_sz; - UINT8 filter_support; - UINT8 max_filter; - UINT8 energy_support; - BOOLEAN values_read; - UINT16 version_supported; - UINT16 total_trackable_advertisers; - UINT8 extended_scan_support; - UINT8 debug_logging_supported; -} tBTM_BLE_VSC_CB; + /* slave preferred connection interval range */ typedef struct { @@ -500,40 +476,6 @@ typedef struct { tBTM_BLE_ADV_TX_POWER tx_power; } tBTM_BLE_ADV_PARAMS; -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -typedef struct { - UINT8 *p_sub_code; /* dynamic array to store sub code */ - UINT8 *p_inst_id; /* dynamic array to store instance id */ - UINT8 pending_idx; - UINT8 next_idx; -} tBTM_BLE_MULTI_ADV_OPQ; - -typedef void (tBTM_BLE_MULTI_ADV_CBACK)(tBTM_BLE_MULTI_ADV_EVT evt, UINT8 inst_id, - void *p_ref, tBTM_STATUS status); - -typedef struct { - UINT8 inst_id; - BOOLEAN in_use; - UINT8 adv_evt; - BD_ADDR rpa; - TIMER_LIST_ENT raddr_timer_ent; - tBTM_BLE_MULTI_ADV_CBACK *p_cback; - void *p_ref; - UINT8 index; -} tBTM_BLE_MULTI_ADV_INST; - -typedef struct { - UINT8 inst_index_queue[BTM_BLE_MULTI_ADV_MAX]; - int front; - int rear; -} tBTM_BLE_MULTI_ADV_INST_IDX_Q; - -typedef struct { - tBTM_BLE_MULTI_ADV_INST *p_adv_inst; /* dynamic array to store adv instance */ - tBTM_BLE_MULTI_ADV_OPQ op_q; -} tBTM_BLE_MULTI_ADV_CB; -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - typedef UINT8 tGATT_IF; typedef void (tBTM_BLE_SCAN_THRESHOLD_CBACK)(tBTM_BLE_REF_VALUE ref_value); @@ -542,60 +484,17 @@ typedef void (tBTM_BLE_SCAN_REP_CBACK)(tBTM_BLE_REF_VALUE ref_value, UINT8 repor UINT8 *p_rep_data, UINT8 status); typedef void (tBTM_BLE_SCAN_SETUP_CBACK)(UINT8 evt, tBTM_BLE_REF_VALUE ref_value, UINT8 status); -#ifndef BTM_BLE_BATCH_SCAN_MAX -#define BTM_BLE_BATCH_SCAN_MAX 5 -#endif #ifndef BTM_BLE_BATCH_REP_MAIN_Q_SIZE #define BTM_BLE_BATCH_REP_MAIN_Q_SIZE 2 #endif -typedef enum { - BTM_BLE_SCAN_INVALID_STATE = 0, - BTM_BLE_SCAN_ENABLE_CALLED = 1, - BTM_BLE_SCAN_ENABLED_STATE = 2, - BTM_BLE_SCAN_DISABLE_CALLED = 3, - BTM_BLE_SCAN_DISABLED_STATE = 4 -} tBTM_BLE_BATCH_SCAN_STATE; - enum { BTM_BLE_DISCARD_OLD_ITEMS, BTM_BLE_DISCARD_LOWER_RSSI_ITEMS }; typedef UINT8 tBTM_BLE_DISCARD_RULE; -typedef struct { - UINT8 sub_code[BTM_BLE_BATCH_SCAN_MAX]; - tBTM_BLE_BATCH_SCAN_STATE cur_state[BTM_BLE_BATCH_SCAN_MAX]; - tBTM_BLE_REF_VALUE ref_value[BTM_BLE_BATCH_SCAN_MAX]; - UINT8 pending_idx; - UINT8 next_idx; -} tBTM_BLE_BATCH_SCAN_OPQ; - -typedef struct { - UINT8 rep_mode[BTM_BLE_BATCH_REP_MAIN_Q_SIZE]; - tBTM_BLE_REF_VALUE ref_value[BTM_BLE_BATCH_REP_MAIN_Q_SIZE]; - UINT8 num_records[BTM_BLE_BATCH_REP_MAIN_Q_SIZE]; - UINT16 data_len[BTM_BLE_BATCH_REP_MAIN_Q_SIZE]; - UINT8 *p_data[BTM_BLE_BATCH_REP_MAIN_Q_SIZE]; - UINT8 pending_idx; - UINT8 next_idx; -} tBTM_BLE_BATCH_SCAN_REP_Q; - -typedef struct { - tBTM_BLE_BATCH_SCAN_STATE cur_state; - tBTM_BLE_BATCH_SCAN_MODE scan_mode; - UINT32 scan_interval; - UINT32 scan_window; - tBLE_ADDR_TYPE addr_type; - tBTM_BLE_DISCARD_RULE discard_rule; - tBTM_BLE_BATCH_SCAN_OPQ op_q; - tBTM_BLE_BATCH_SCAN_REP_Q main_rep_q; - tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback; - tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback; - tBTM_BLE_SCAN_REP_CBACK *p_scan_rep_cback; - tBTM_BLE_REF_VALUE ref_value; -} tBTM_BLE_BATCH_SCAN_CB; /// Ble scan duplicate type enum { @@ -781,6 +680,10 @@ typedef struct { tBTM_BLE_GAP_PHY secondary_phy; UINT8 sid; BOOLEAN scan_req_notif; +#if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) + UINT8 primary_adv_phy_options; + UINT8 secondary_adv_phy_options; +#endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) } tBTM_BLE_GAP_EXT_ADV_PARAMS; typedef struct { @@ -808,7 +711,14 @@ typedef struct { typedef struct { UINT16 interval_min; UINT16 interval_max; - UINT8 properties; + UINT16 properties; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + UINT8 num_subevents; + UINT8 subevent_interval; + UINT8 rsp_slot_delay; + UINT8 rsp_slot_spacing; + UINT8 num_rsp_slots; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) } tBTM_BLE_Periodic_Adv_Params; typedef struct { @@ -948,53 +858,7 @@ typedef UINT8 tBTM_BLE_CONN_TYPE; #define ADV_INFO_PRESENT 0x00 #define NO_ADV_INFO_PRESENT 0x01 -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -typedef btgatt_track_adv_info_t tBTM_BLE_TRACK_ADV_DATA; - -typedef void (tBTM_BLE_TRACK_ADV_CBACK)(tBTM_BLE_TRACK_ADV_DATA *p_track_adv_data); - -typedef UINT8 tBTM_BLE_TRACK_ADV_EVT; - -typedef struct { - tBTM_BLE_REF_VALUE ref_value; - tBTM_BLE_TRACK_ADV_CBACK *p_track_cback; -} tBTM_BLE_ADV_TRACK_CB; - -enum { - BTM_BLE_TRACK_ADV_ADD, - BTM_BLE_TRACK_ADV_REMOVE -}; - -typedef UINT8 tBTM_BLE_TRACK_ADV_ACTION; -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - -#define BTM_BLE_MULTI_ADV_INVALID 0 - -#define BTM_BLE_BATCH_SCAN_ENABLE_EVT 1 -#define BTM_BLE_BATCH_SCAN_CFG_STRG_EVT 2 -#define BTM_BLE_BATCH_SCAN_READ_REPTS_EVT 3 -#define BTM_BLE_BATCH_SCAN_THR_EVT 4 -#define BTM_BLE_BATCH_SCAN_PARAM_EVT 5 -#define BTM_BLE_BATCH_SCAN_DISABLE_EVT 6 - -typedef UINT8 tBTM_BLE_BATCH_SCAN_EVT; - -typedef UINT32 tBTM_BLE_TX_TIME_MS; -typedef UINT32 tBTM_BLE_RX_TIME_MS; -typedef UINT32 tBTM_BLE_IDLE_TIME_MS; -typedef UINT32 tBTM_BLE_ENERGY_USED; - -typedef void (tBTM_BLE_ENERGY_INFO_CBACK)(tBTM_BLE_TX_TIME_MS tx_time, tBTM_BLE_RX_TIME_MS rx_time, - tBTM_BLE_IDLE_TIME_MS idle_time, - tBTM_BLE_ENERGY_USED energy_used, - tBTM_STATUS status); - -typedef struct { - tBTM_BLE_ENERGY_INFO_CBACK *p_ener_cback; -} tBTM_BLE_ENERGY_INFO_CB; - typedef BOOLEAN (tBTM_BLE_SEL_CBACK)(BD_ADDR random_bda, UINT8 *p_remote_name); -typedef void (tBTM_BLE_CTRL_FEATURES_CBACK)(tBTM_STATUS status); /* callback function for SMP signing algorithm, signed data in little endian order with tlen bits long */ typedef void (tBTM_BLE_SIGN_CBACK)(void *p_ref_data, UINT8 *p_signing_data); @@ -1005,8 +869,6 @@ typedef void (tBTM_BLE_RANDOM_SET_CBACK) (BD_ADDR random_bda); typedef void (tBTM_BLE_SCAN_REQ_CBACK)(BD_ADDR remote_bda, tBLE_ADDR_TYPE addr_type, UINT8 adv_evt); typedef void (*tBLE_SCAN_PARAM_SETUP_CBACK)(tGATT_IF client_if, tBTM_STATUS status); -tBTM_BLE_SCAN_SETUP_CBACK bta_ble_scan_setup_cb; - typedef void (tBTM_START_ADV_CMPL_CBACK) (UINT8 status); typedef void (tBTM_START_STOP_ADV_CMPL_CBACK) (UINT8 status); @@ -1090,7 +952,29 @@ typedef void (tBTM_SET_VENDOR_EVT_MASK_CBACK) (tBTM_STATUS status); #if (BLE_50_FEATURE_SUPPORT == TRUE) #define BTM_BLE_GAP_SET_HOST_FEATURE_EVT 51 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) -#define BTM_BLE_5_GAP_UNKNOWN_EVT 52 +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +#define BTM_BLE_GAP_SET_PERIODIC_ADV_SUBEVT_DATA_EVT 52 +#define BTM_BLE_GAP_SET_PERIODIC_ADV_RESPONSE_DATA_EVT 53 +#define BTM_BLE_GAP_SET_PERIODIC_SYNC_SUBEVT_EVT 54 +#define BTM_BLE_GAP_PERIODIC_ADV_SUBEVT_DATA_REQUEST_EVT 55 +#define BTM_BLE_GAP_PERIODIC_ADV_RESPONSE_REPORT_EVT 56 +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#define BTM_BLE_GAP_CS_READ_LOCAL_SUPP_CAPS_EVT 57 +#define BTM_BLE_GAP_CS_WRITE_CACHED_REMOTE_SUPP_CAPS_EVT 58 +#define BTM_BLE_GAP_CS_SET_DEFAULT_SETTINGS_EVT 59 +#define BTM_BLE_GAP_CS_WRITE_CACHED_REMOTE_FAE_TAB_EVT 60 +#define BTM_BLE_GAP_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT 61 +#define BTM_BLE_GAP_CS_SET_CHANNEL_CLASS_CMPL_EVT 62 +#define BTM_BLE_GAP_CS_PROC_PARAMS_CMPL_EVT 63 +#define BTM_BLE_GAP_CS_PROC_ENABLE_CMPL_EVT 64 +#define BTM_BLE_GAP_CS_READ_REMOTE_FAE_TABLE_CMPL_EVT 65 +#define BTM_BLE_GAP_CS_SECURITY_ENABLE_CMPL_EVT 66 +#define BTM_BLE_GAP_CS_CONFIG_CMPL_EVT 67 +#define BTM_BLE_GAP_CS_SUBEVENT_RESULT_EVT 68 +#define BTM_BLE_GAP_CS_SUBEVENT_RESULT_CONTINUE_EVT 69 +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#define BTM_BLE_5_GAP_UNKNOWN_EVT 70 typedef UINT8 tBTM_BLE_5_GAP_EVENT; #if (BLE_FEAT_ISO_EN == TRUE) @@ -1332,6 +1216,10 @@ typedef struct { UINT8 tx_power; INT8 rssi; UINT8 cte_type; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + UINT16 periodic_evt_cnt; + UINT8 subevt; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) tBTM_BLE_EXT_ADV_DATA_STATUS data_status; UINT8 data_length; UINT8 *data; @@ -1350,6 +1238,12 @@ typedef struct { UINT8 adv_phy; UINT16 period_adv_interval; UINT8 adv_clk_accuracy; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + UINT8 num_subevt; + UINT8 subevt_interval; + UINT8 rsp_slot_delay; + UINT8 rsp_slot_spacing; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) } tBTM_BLE_PERIOD_ADV_SYNC_ESTAB; typedef struct { @@ -1453,6 +1347,199 @@ typedef struct { } __attribute__((packed)) tBTM_BLE_SUBRATE_CHANGE_EVT; #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +typedef struct { + UINT8 status; + UINT8 adv_handle; +} __attribute__((packed)) tBTM_BLE_PA_SUBEVT_DATA_EVT; +typedef struct { + UINT8 status; + UINT16 sync_handle; +} __attribute__((packed)) tBTM_BLE_PA_RSP_DATA_EVT; +typedef struct { + UINT8 status; + UINT16 sync_handle; +} __attribute__((packed)) tBTM_BLE_PA_SYNC_SUBEVT_DATA_EVT; +typedef struct { + UINT8 adv_handle; + UINT8 subevt_start; + UINT8 subevt_data_count; +} __attribute__((packed)) tBTM_BLE_PA_SUBEVT_DATA_REQ_EVT; + +typedef struct { + INT8 tx_power; + INT8 rssi; + UINT8 cte_type; + UINT8 rsp_slot; + UINT8 data_status; + UINT8 data_len; + UINT8 *data; +} __attribute__((packed)) tBTM_BLE_PA_RSP_DATA_INFO; + +typedef struct { + UINT8 adv_handle; + UINT8 subevt; + UINT8 tx_status; + UINT8 num_rsp; + tBTM_BLE_PA_RSP_DATA_INFO *rsp_data_info; +} __attribute__((packed)) tBTM_BLE_PA_RSP_REPORT_EVT; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CS_WRITE_CACHED_SUPPORT_CAPS_EVT; +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CS_SET_DEFAULT_SETTINGS_EVT; +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CS_WRITE_CACHED_REMOTE_FAE_TAB_EVT; +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CS_SET_PAROC_PARAMS_EVT; +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT8 num_config_supported; + UINT16 max_consecutive_proc_supported; + UINT8 num_ant_supported; + UINT8 max_ant_paths_supported; + UINT8 roles_supported; + UINT8 modes_supported; + UINT8 rtt_capability; + UINT8 rtt_aa_only_n; + UINT8 rtt_sounding_n; + UINT8 rtt_random_payload_n; + UINT16 NADM_sounding_capability; + UINT16 NADM_random_capability; + UINT8 cs_sync_phys_supported; + UINT16 subfeatures_supported; + UINT16 T_IP1_times_supported; + UINT16 T_IP2_times_supported; + UINT16 T_FCS_times_supported; + UINT16 T_PM_times_supported; + UINT8 T_SW_times_supported; + UINT8 TX_SNR_capability; +} __attribute__((packed)) tBTM_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT8 remote_fae_table[72]; +} __attribute__((packed)) tBTM_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CS_SEC_ENABLE_CMPL_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT8 config_id; + UINT8 action; + UINT8 main_mode_type; + UINT8 sub_mode_type; + UINT8 min_main_mode_steps; + UINT8 max_main_mode_steps; + UINT8 main_mode_repetition; + UINT8 mode_0_steps; + UINT8 role; + UINT8 rtt_type; + UINT8 cs_sync_phy; + UINT8 channel_map[10]; + UINT8 channel_map_repetition; + UINT8 channel_selection_type; + UINT8 ch3c_shape; + UINT8 ch3c_jump; + UINT8 reserved; + UINT8 t_ip1_time; + UINT8 t_ip2_time; + UINT8 t_fcs_time; + UINT8 t_pm_time; +}__attribute__((packed)) tBTM_BLE_CS_CONFIG_CMPL_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT8 config_id; + UINT8 state; + UINT8 tone_ant_config_select; + INT8 select_tx_power; + UINT32 subevent_Len; + UINT8 subevents_per_event; + UINT16 subevent_interval; + UINT16 event_interval; + UINT16 procedure_interval; + UINT16 procedure_count; + UINT16 max_procedure_len; +}__attribute__((packed)) tBTM_BLE_CS_PROC_ENABLE_CMPL_EVT; + +typedef struct { + UINT8 step_mode; + UINT8 step_channel; + UINT8 step_data_len; + UINT8 *data; +} __attribute__((packed)) tBTM_BLE_CS_STEP_INFO; + +typedef struct { + UINT16 conn_handle; + UINT8 config_id; + UINT16 start_acl_conn_event_counter; + UINT16 procedure_counter; + INT16 frequency_compensation; + INT8 reference_power_level; + UINT8 procedure_done_status; + UINT8 subevent_done_status; + UINT8 abort_reason; + UINT8 num_ant_paths; + UINT8 num_steps_reported; + tBTM_BLE_CS_STEP_INFO *step_info; +}__attribute__((packed)) tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT; + +typedef struct { + UINT16 conn_handle; + UINT8 config_id; + UINT8 proc_done_status; + UINT8 subevt_done_status; + UINT8 abort_reason; + UINT8 num_ant_paths; + UINT8 num_steps_reported; + tBTM_BLE_CS_STEP_INFO *step_info; +}__attribute__((packed)) tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT8 num_config_supported; + UINT16 max_consecutive_proc_supported; + UINT8 num_ant_supported; + UINT8 max_ant_paths_supported; + UINT8 roles_supported; + UINT8 modes_supported; + UINT8 rtt_capability; + UINT8 rtt_aa_only_n; + UINT8 rtt_sounding_n; + UINT8 rtt_random_payload_n; + UINT16 NADM_sounding_capability; + UINT16 NADM_random_capability; + UINT8 cs_sync_phys_supported; + UINT16 subfeatures_supported; + UINT16 T_IP1_times_supported; + UINT16 T_IP2_times_supported; + UINT16 T_FCS_times_supported; + UINT16 T_PM_times_supported; + UINT8 T_SW_times_supported; + UINT8 TX_SNR_capability; +} __attribute__((packed)) tBTM_BLE_CS_READ_LOCAL_SUPP_CAPS_CMPL_EVT; + +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) typedef struct { @@ -1819,6 +1906,27 @@ typedef union { #if (BLE_FEAT_CONN_SUBRATING == TRUE) tBTM_BLE_SUBRATE_CHANGE_EVT subrate_change_evt; #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + tBTM_BLE_PA_SUBEVT_DATA_EVT pa_subevt_data_evt; + tBTM_BLE_PA_RSP_DATA_EVT pa_rsp_data_evt; + tBTM_BLE_PA_SYNC_SUBEVT_DATA_EVT pa_sync_subevt_evt; + tBTM_BLE_PA_SUBEVT_DATA_REQ_EVT pa_subevent_data_req_evt; + tBTM_BLE_PA_RSP_REPORT_EVT pa_rsp_rpt_evt; +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + tBTM_BLE_CS_WRITE_CACHED_SUPPORT_CAPS_EVT cs_write_cached_remote_supp_caps; + tBTM_BLE_CS_SET_DEFAULT_SETTINGS_EVT cs_set_default_settings; + tBTM_BLE_CS_WRITE_CACHED_REMOTE_FAE_TAB_EVT cs_write_cached_remote_fae_tab; + tBTM_BLE_CS_SET_PAROC_PARAMS_EVT cs_set_proc_params; + tBTM_BLE_CS_READ_LOCAL_SUPP_CAPS_CMPL_EVT cs_read_local_supp_caps; + tBTM_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT cs_read_remote_supp_caps; + tBTM_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT cs_read_remote_fae_tab; + tBTM_BLE_CS_SEC_ENABLE_CMPL_EVT cs_security_enable; + tBTM_BLE_CS_PROC_ENABLE_CMPL_EVT cs_proc_en; + tBTM_BLE_CS_CONFIG_CMPL_EVT cs_config_update; + tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT cs_subevt_result; + tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT cs_subevt_result_continue; +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) } tBTM_BLE_5_GAP_CB_PARAMS; typedef struct { @@ -1961,61 +2069,6 @@ tBTM_STATUS BTM_BleSetRandAddress(BD_ADDR rand_addr); void BTM_BleClearRandAddress(void); -/******************************************************************************* -** -** Function BTM_BleSetAdvParams -** -** Description This function is called to set advertising parameters. -** -** Parameters adv_int_min: minimum advertising interval -** adv_int_max: maximum advertising interval -** p_dir_bda: connectable direct initiator's LE device address -** chnl_map: advertising channel map. -** -** Returns void -** -*******************************************************************************/ -//extern -void BTM_BleReadAdvParams (UINT16 *adv_int_min, UINT16 *adv_int_max, - tBLE_BD_ADDR *p_dir_bda, tBTM_BLE_ADV_CHNL_MAP *p_chnl_map); - -/******************************************************************************* -** -** Function BTM_BleObtainVendorCapabilities -** -** Description This function is called to obtain vendor capabilities -** -** Parameters p_cmn_vsc_cb - Returns the vendor capabilities -** -** Returns void -** -*******************************************************************************/ -//extern -void BTM_BleObtainVendorCapabilities(tBTM_BLE_VSC_CB *p_cmn_vsc_cb); - -#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) -/******************************************************************************* -** -** Function BTM_BleSetScanParams -** -** Description This function is called to set Scan parameters. -** -** Parameters client_if - Client IF value -** scan_interval - Scan interval -** scan_window - Scan window -** scan_type - Scan type -** scan_setup_status_cback - Scan setup status callback -** -** Returns void -** -*******************************************************************************/ -//extern -void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, - UINT32 scan_window, tBLE_SCAN_MODE scan_type, - tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback); - -#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) - /******************************************************************************* ** ** Function BTM_BleSetScanFilterParams @@ -2039,116 +2092,6 @@ tBTM_STATUS BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback); -/******************************************************************************* -** -** Function BTM_BleGetVendorCapabilities -** -** Description This function reads local LE features -** -** Parameters p_cmn_vsc_cb : Locala LE capability structure -** -** Returns void -** -*******************************************************************************/ -//extern -void BTM_BleGetVendorCapabilities(tBTM_BLE_VSC_CB *p_cmn_vsc_cb); -/******************************************************************************* -** -** Function BTM_BleSetStorageConfig -** -** Description This function is called to setup storage configuration and setup callbacks. -** -** Parameters UINT8 batch_scan_full_max -Batch scan full maximum - UINT8 batch_scan_trunc_max - Batch scan truncated value maximum - UINT8 batch_scan_notify_threshold - Threshold value - tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback - Setup callback - tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback -Threshold callback - void *p_ref - Reference value -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleSetStorageConfig(UINT8 batch_scan_full_max, - UINT8 batch_scan_trunc_max, - UINT8 batch_scan_notify_threshold, - tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback, - tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback, - tBTM_BLE_SCAN_REP_CBACK *p_cback, - tBTM_BLE_REF_VALUE ref_value); - -/******************************************************************************* -** -** Function BTM_BleEnableBatchScan -** -** Description This function is called to enable batch scan -** -** Parameters tBTM_BLE_BATCH_SCAN_MODE scan_mode - Batch scan mode - UINT32 scan_interval -Scan interval - UINT32 scan_window - Scan window value - tBLE_ADDR_TYPE addr_type - Address type - tBTM_BLE_DISCARD_RULE discard_rule - Data discard rules -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode, - UINT32 scan_interval, UINT32 scan_window, - tBTM_BLE_DISCARD_RULE discard_rule, - tBLE_ADDR_TYPE addr_type, - tBTM_BLE_REF_VALUE ref_value); - -/******************************************************************************* -** -** Function BTM_BleDisableBatchScan -** -** Description This function is called to disable batch scanning -** -** Parameters void -** -** Returns void -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value); - -#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleReadScanReports -** -** Description This function is called to read batch scan reports -** -** Parameters tBLE_SCAN_MODE scan_mode - Scan mode report to be read out - tBTM_BLE_SCAN_REP_CBACK* p_cback - Reports callback -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleReadScanReports(tBLE_SCAN_MODE scan_mode, - tBTM_BLE_REF_VALUE ref_value); -#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - -#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleTrackAdvertiser -** -** Description This function is called to read batch scan reports -** -** Parameters p_track_cback - Tracking callback -** ref_value - Reference value -** -** Returns tBTM_STATUS -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback, - tBTM_BLE_REF_VALUE ref_value); -#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) - /******************************************************************************* ** ** Function BTM_BleWriteScanRsp @@ -2531,20 +2474,6 @@ void BTM_BleSetPrefConnParams (BD_ADDR bd_addr, //extern void BTM_BleSetConnScanParams (UINT32 scan_interval, UINT32 scan_window); -/****************************************************************************** -** -** Function BTM_BleReadControllerFeatures -** -** Description Reads BLE specific controller features -** -** Parameters: tBTM_BLE_CTRL_FEATURES_CBACK : Callback to notify when features are read -** -** Returns void -** -*******************************************************************************/ -//extern -void BTM_BleReadControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK *p_vsc_cback); - /******************************************************************************* ** ** Function BTM_CheckAdvData @@ -2691,6 +2620,22 @@ BOOLEAN BTM_BleConfigPrivacy(BOOLEAN enable, tBTM_SET_LOCAL_PRIVACY_CBACK *set_l *******************************************************************************/ void BTM_BleConfigLocalIcon(uint16_t icon); +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +/******************************************************************************* +** +** Function BTM_BleSetKeyMaterial +** +** Description Set the Encrypted Data Key Material in GAP service +** +** Parameters session_key: 16-byte session key +** iv: 8-byte initialization vector +** +** Returns void +** +*******************************************************************************/ +void BTM_BleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv); +#endif + /******************************************************************************* ** ** Function BTM_BleConfigConnParams @@ -2732,20 +2677,6 @@ BOOLEAN BTM_BleLocalPrivacyEnabled(void); //extern void BTM_BleEnableMixedPrivacyMode(BOOLEAN mixed_on); -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -/******************************************************************************* -** -** Function BTM_BleMaxMultiAdvInstanceCount -** -** Description Returns max number of multi adv instances supported by controller -** -** Returns Max multi adv instance count -** -*******************************************************************************/ -//extern -UINT8 BTM_BleMaxMultiAdvInstanceCount(void); -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) - /******************************************************************************* ** ** Function BTM_BleSetConnectableMode @@ -2804,19 +2735,6 @@ BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR emote_bda, tBLE_AD *******************************************************************************/ void BTM_BleClearWhitelist(tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb); -/******************************************************************************* -** -** Function BTM_BleUpdateAdvFilterPolicy -** -** Description This function update the filter policy of advertiser. -** -** Parameter adv_policy: advertising filter policy -** -** Return void -*******************************************************************************/ -//extern -void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy); - /******************************************************************************* ** ** Function BTM_BleReceiverTest @@ -2925,80 +2843,6 @@ BOOLEAN BTM_BleSecurityProcedureIsRunning (BD_ADDR bd_addr); //extern UINT8 BTM_BleGetSupportedKeySize (BD_ADDR bd_addr); -#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) -/*******************************************************************************/ -/* Multi ADV API */ -/******************************************************************************* -** -** Function BTM_BleEnableAdvInstance -** -** Description This function enable a Multi-ADV instance with the specified -** adv parameters -** -** Parameters p_params: pointer to the adv parameter structure, set as default -** adv parameter when the instance is enabled. -** p_cback: callback function for the adv instance. -** p_ref: reference data attach to the adv instance to be enabled. -** -** Returns status -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params, - tBTM_BLE_MULTI_ADV_CBACK *p_cback, - void *p_ref); - -/******************************************************************************* -** -** Function BTM_BleUpdateAdvInstParam -** -** Description This function update a Multi-ADV instance with the specified -** adv parameters. -** -** Parameters inst_id: adv instance ID -** p_params: pointer to the adv parameter structure. -** -** Returns status -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params); - -/******************************************************************************* -** -** Function BTM_BleCfgAdvInstData -** -** Description This function configure a Multi-ADV instance with the specified -** adv data or scan response data. -** -** Parameters inst_id: adv instance ID -** is_scan_rsp: is this scacn response, if no set as adv data. -** data_mask: adv data mask. -** p_data: pointer to the adv data structure. -** -** Returns status -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp, - tBTM_BLE_AD_MASK data_mask, - tBTM_BLE_ADV_DATA *p_data); - -/******************************************************************************* -** -** Function BTM_BleDisableAdvInstance -** -** Description This function disable a Multi-ADV instance. -** -** Parameters inst_id: adv instance ID -** -** Returns status -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id); - -#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** @@ -3060,20 +2904,6 @@ tBTM_STATUS BTM_BleEnableDisableFilterFeature(UINT8 enable, tBTM_BLE_PF_STATUS_CBACK *p_stat_cback, tBTM_BLE_REF_VALUE ref_value); -/******************************************************************************* -** -** Function BTM_BleGetEnergyInfo -** -** Description This function obtains the energy info -** -** Parameters p_ener_cback - Callback pointer -** -** Returns status -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleGetEnergyInfo(tBTM_BLE_ENERGY_INFO_CBACK *p_ener_cback); - /******************************************************************************* ** ** Function BTM_SetBleDataLength @@ -3371,7 +3201,46 @@ void BTM_BleSetDefaultSubrate(UINT16 subrate_min, UINT16 subrate_max, UINT16 max void BTM_BleSubrateRequest(UINT16 conn_handle, UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, UINT16 continuation_number, UINT16 supervision_timeout); #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + #if (BLE_50_FEATURE_SUPPORT == TRUE) tBTM_STATUS BTM_BleSetHostFeature(uint16_t bit_num, uint8_t bit_val); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +void BTM_BleSetPaSubeventData(UINT8 adv_handle, UINT8 num_subevents_with_data, uint8_t *subevent_params); +void BTM_BleSetPaResponseData(UINT16 sync_handle, UINT16 req_evt, UINT8 req_subevt, UINT8 rsp_subevt, UINT8 rsp_slot, UINT8 rsp_data_len, UINT8 *rsp_data); +void BTM_BleSetPaSyncSubevt(UINT16 sync_handle, UINT16 periodic_adv_properties, UINT8 num_subevents_to_sync, UINT8 *subevt); +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +void BTM_BleCSReadLocalSuppCaps(void); +void BTM_BleCSReadRemoteSuppCaps(UINT16 conn_handle); +void BTM_BleGapWriteCachedRemoteSupportedCaps(UINT16 conn_handle, UINT8 num_config_supported, UINT16 max_consecutive_proc_supported, + UINT8 num_ant_supported, UINT8 max_ant_paths_supported, UINT8 roles_supported, + UINT8 modes_supported, UINT8 rtt_capability, UINT8 rtt_aa_only_n, + UINT8 rtt_sounding_n, UINT8 rtt_random_payload_n, UINT16 NADM_sounding_capability, + UINT16 NADM_random_capability, UINT8 cs_sync_phys_supported, UINT16 subfeatures_supported, + UINT16 T_IP1_times_supported, UINT16 T_IP2_times_supported, UINT16 T_FCS_times_supported, + UINT16 T_PM_times_supported, UINT8 T_SW_times_supported, UINT8 TX_SNR_capability); +void BTM_BleGapCsSecurityEnable(UINT16 conn_handle); +void BTM_BleGapCsSetDefaultSetting(UINT16 conn_handle, UINT8 role_enable, UINT8 cs_sync_ant_selection, INT8 max_tx_power); +void BTM_BleGapCsReadRemoteFaeTable(UINT16 conn_handle); +void BTM_BleGapWriteCachedRemoteFaeTable(UINT16 conn_handle, UINT8 *remote_fae_table); +void BTM_BleGapCsCreateConfig(UINT16 conn_handle, UINT8 config_id, UINT8 create_context, + UINT8 main_mode_type, UINT8 sub_mode_type, UINT8 min_main_mode_steps, + UINT8 max_main_mode_steps, UINT8 main_mode_repetition, UINT8 mode_0_steps, + UINT8 role, UINT8 rtt_type, UINT8 cs_sync_phy, UINT8 *channel_map, + UINT8 channel_map_repetition, UINT8 channel_selection_type, UINT8 ch3c_shape, + UINT8 ch3c_jump,UINT8 reserved); +void BTM_BleGapCsRemoveConfig(UINT16 conn_handle, UINT8 config_id); +void BTM_BleGapCsSetChannelClass(UINT8 *channel_class); +void BTM_BleGapCsSetProcPatams(UINT16 conn_handle, UINT8 config_id, UINT16 max_procedure_len, + UINT16 min_procedure_interval, UINT16 max_procedure_interval, + UINT16 max_procedure_count, UINT32 min_subevent_len, + UINT32 max_subevent_len, UINT8 tone_ant_config_selection, + UINT8 phy, UINT8 tx_power_delta, UINT8 preferred_peer_antenna, + UINT8 SNR_control_initiator, UINT8 SNR_control_reflector); +void BTM_BleGapCsProcEnable(UINT16 conn_handle, UINT8 config_id, UINT8 enable); +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + #endif diff --git a/components/bt/host/bluedroid/stack/include/stack/gap_api.h b/components/bt/host/bluedroid/stack/include/stack/gap_api.h index 62062d2f21..81d353d022 100644 --- a/components/bt/host/bluedroid/stack/include/stack/gap_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/gap_api.h @@ -113,12 +113,29 @@ typedef struct { UINT16 sp_tout; } tGAP_BLE_PREF_PARAM; +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) +#define GAP_KEY_MATERIAL_SESSION_KEY_SIZE 16 /* 128-bit session key */ +#define GAP_KEY_MATERIAL_IV_SIZE 8 /* 64-bit IV */ +#define GAP_KEY_MATERIAL_SIZE (GAP_KEY_MATERIAL_SESSION_KEY_SIZE + GAP_KEY_MATERIAL_IV_SIZE) + +typedef struct { + UINT8 session_key[GAP_KEY_MATERIAL_SESSION_KEY_SIZE]; + UINT8 iv[GAP_KEY_MATERIAL_IV_SIZE]; +} tGAP_BLE_KEY_MATERIAL; +#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + typedef union { tGAP_BLE_PREF_PARAM conn_param; BD_ADDR reconn_bda; UINT16 icon; UINT8 *p_dev_name; UINT8 addr_resolution; +#if (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) + UINT16 security_level; +#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE) +#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) + tGAP_BLE_KEY_MATERIAL key_material; +#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE) } tGAP_BLE_ATTR_VALUE; diff --git a/components/bt/host/bluedroid/stack/include/stack/gatt_api.h b/components/bt/host/bluedroid/stack/include/stack/gatt_api.h index 002cb16e33..2e1d2d54c2 100644 --- a/components/bt/host/bluedroid/stack/include/stack/gatt_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/gatt_api.h @@ -1140,7 +1140,8 @@ extern void GATT_StartIf (tGATT_IF gatt_if); ** *******************************************************************************/ extern BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_type, - BOOLEAN is_direct, tBT_TRANSPORT transport, BOOLEAN is_aux); + BOOLEAN is_direct, tBT_TRANSPORT transport, BOOLEAN is_aux, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent); /******************************************************************************* @@ -1226,23 +1227,6 @@ extern BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id, tBT_TRANSPORT transport); -/******************************************************************************* -** -** Function GATT_Listen -** -** Description This function start or stop LE advertisement and listen for -** connection. -** -** Parameters gatt_if: application interface -** p_bd_addr: listen for specific address connection, or NULL for -** listen to all device connection. -** start: is a direct connection or a background auto connection -** -** Returns TRUE if advertisement is started; FALSE if adv start failure. -** -*******************************************************************************/ -extern BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr); - /******************************************************************************* ** ** Function GATT_ConfigServiceChangeCCC diff --git a/components/bt/host/bluedroid/stack/include/stack/gattdefs.h b/components/bt/host/bluedroid/stack/include/stack/gattdefs.h index d8e4cb591e..8da14f4cb7 100644 --- a/components/bt/host/bluedroid/stack/include/stack/gattdefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/gattdefs.h @@ -52,6 +52,9 @@ #define GATT_UUID_GAP_PREF_CONN_PARAM 0x2A04 #define GATT_UUID_GAP_CENTRAL_ADDR_RESOL 0x2AA6 +#define GATT_UUID_GAP_GATT_SECURITY_LEVELS 0x2BF5 +#define GATT_UUID_GAP_KEY_MATERIAL 0x2B88 /* Encrypted Data Key Material */ + /* Attribute Profile Attribute UUID */ #define GATT_UUID_GATT_SRV_CHGD 0x2A05 /* Attribute Protocol Test */ @@ -81,7 +84,7 @@ #define GATT_UUID_GM_CONTROL_POINT 0x2A52 #define GATT_UUID_GM_FEATURE 0x2A51 -/* device infor characteristic */ +/* device information characteristic */ #define GATT_UUID_SYSTEM_ID 0x2A23 #define GATT_UUID_MODEL_NUMBER_STR 0x2A24 #define GATT_UUID_SERIAL_NUMBER_STR 0x2A25 diff --git a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h index 23f9b3e6b8..ca6f901377 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h @@ -443,6 +443,33 @@ #define HCI_BLE_SUBRATE_REQUEST (0x007E | HCI_GRP_BLE_CMDS) #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) +#define HCI_BLE_SET_EXT_ADV_PARAM_V2 (0x007F | HCI_GRP_BLE_CMDS) +#endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) + +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +#define HCI_BLE_SET_PERIOD_ADV_SUBEVT_DATA (0x0082 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_PERIOD_ADV_RSP_DATA (0x0083 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_PERIOD_SYNC_SUBEVT (0x0084 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_EXT_CREATE_CONN_V2 (0x0085 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_PERIOD_ADV_PARAMS_V2 (0x0086 | HCI_GRP_BLE_CMDS) +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#define HCI_BLE_CS_READ_LOCAL_SUPP_CAPS (0x0089 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_READ_REMOTE_SUPP_CAPS (0x008A | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_WRITE_CACHED_REMOTE_SUPP_CAPS (0x008B | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_SECURITY_ENABLE (0x008C | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_SET_DEFAULT_SETTINGS (0x008D | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_READ_REMOTE_FAE_TABLE (0x008E | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_WRITE_CACHED_REMOTE_FAE_TABLE (0x008F | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_CREATE_CONFIG (0x0090 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_REMOVE_CONFIG (0x0091 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_SET_CAHNNEL_CLASS (0x0092 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_SET_PROCEDURE_PARAMS (0x0093 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CS_SET_PROCEDURE_ENABLE (0x0094 | HCI_GRP_BLE_CMDS) +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + // Vendor OGF define #define HCI_VENDOR_OGF 0x3F @@ -461,10 +488,9 @@ //ESP BLE subcode define #define HCI_SUBCODE_BLE_INIT 0x00 #define HCI_SUBCODE_BLE_MULTI_ADV 0x01 -#define HCI_SUBCODE_BLE_BATCH_SCAN 0x02 #define HCI_SUBCODE_BLE_ADV_FILTER 0x03 #define HCI_SUBCODE_BLE_TRACK_ADV 0x04 -#define HCI_SUBCODE_BLE_ENERGY_INFO 0x05 + #define HCI_SUBCODE_BLE_EXTENDED_SCAN_PARAMS 0x06 #define HCI_SUBCODE_BLE_LONG_ADV 0x07 #define HCI_SUBCODE_BLE_DUPLICATE_EXCEPTIONAL_LIST 0x08 @@ -509,14 +535,11 @@ //ESP BLE HCI CMD /* Multi adv OCF */ #define HCI_BLE_MULTI_ADV_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_MULTI_ADV) -/* Batch scan OCF */ -#define HCI_BLE_BATCH_SCAN_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_BATCH_SCAN) + /* ADV filter OCF */ #define HCI_BLE_ADV_FILTER_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_ADV_FILTER) /* Tracking OCF */ #define HCI_BLE_TRACK_ADV_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_TRACK_ADV) -/* Energy info OCF */ -#define HCI_BLE_ENERGY_INFO_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_ENERGY_INFO) /* Extended BLE Scan parameters OCF */ #define HCI_BLE_EXTENDED_SCAN_PARAMS_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_EXTENDED_SCAN_PARAMS) /* BLE update duplicate scan exceptional list */ @@ -549,12 +572,6 @@ /* multi adv VSE subcode */ #define HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG 0x55 /* multi adv instance state change */ -/* subcode for batch scan feature */ -#define BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE 0x01 -#define BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM 0x02 -#define BTM_BLE_BATCH_SCAN_SET_PARAMS 0x03 -#define BTM_BLE_BATCH_SCAN_READ_RESULTS 0x04 - /* batch scan VSE subcode */ #define HCI_VSE_SUBCODE_BLE_THRESHOLD_SUB_EVT 0x54 /* Threshold event */ @@ -918,6 +935,24 @@ #define HCI_BLE_SUBRATE_CHANGE_EVT 0x23 #endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#define HCI_BLE_PERIOD_ADV_SYNC_ESTAB_EVT_V2 0x24 +#define HCI_BLE_PERIOD_ADV_REPORT_EVT_V2 0x25 + +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +#define HCI_BLE_PA_SUBEVT_DATA_REQUEST_EVT 0x27 +#define HCI_BLE_PA_RESPONSE_REPORT_EVT 0x28 +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#define HCI_BLE_CS_READ_REMOTE_SUPP_CAPS_CMPL_EVT 0x2C +#define HCI_BLE_CS_READ_REMOTE_FAE_TAB_CMPL_EVT 0x2D +#define HCI_BLE_CS_SECURITY_ENABLE_CMPL_EVT 0x2E +#define HCI_BLE_CS_CONFIG_CMPL_EVT 0x2F +#define HCI_BLE_CS_PROC_ENABLE_CMPL_EVT 0x30 +#define HCI_BLE_CS_SUBEVENT_RESULT_EVT 0x31 +#define HCI_BLE_CS_SUBEVENT_RESULT_CONTINUE_EVT 0x32 +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + /* Definitions for LE Channel Map */ #define HCI_BLE_CHNL_MAP_SIZE 5 diff --git a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h index 4ee07b4d40..c4da454d0f 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h @@ -947,6 +947,10 @@ typedef struct { } tHCI_ExtConnParams; typedef struct { +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + UINT8 adv_handle; + UINT8 subevent; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) UINT8 filter_policy; UINT8 own_addr_type; UINT8 peer_addr_type; @@ -1013,7 +1017,7 @@ UINT8 btsnd_hcic_ble_clear_adv_set(void); UINT8 btsnd_hcic_ble_set_periodic_adv_params(UINT8 adv_handle, UINT16 interval_min, UINT16 interval_max, - UINT8 propertics); + UINT16 propertics); UINT8 btsnd_hcic_ble_set_periodic_adv_data(UINT8 adv_handle, UINT8 operation, @@ -1032,6 +1036,10 @@ UINT8 btsnd_hcic_ble_ext_scan_enable(UINT8 enable, UINT8 filter_dups, BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn); +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +BOOLEAN btsnd_hcic_ble_create_ext_conn_v2(tHCI_CreatExtConn *p_conn); +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) + BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 filter_policy, UINT8 adv_sid, UINT8 adv_addr_type, BD_ADDR adv_addr, UINT16 sync_timeout, UINT8 sync_cte_type); @@ -1243,4 +1251,82 @@ UINT8 btsnd_hcic_ble_subrate_request(UINT16 conn_handle, UINT16 subrate_min, UIN UINT8 btsnd_hcic_ble_set_host_feature(uint16_t bit_num, uint8_t bit_val); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BT_BLE_FEAT_PAWR_EN == TRUE) +typedef struct { + uint8_t subevent; + uint8_t response_slot_start; + uint8_t response_slot_count; + uint8_t subevent_data_len; + uint8_t data[251]; +} ble_subevent_params; + +#define HCIC_PARAM_SIZE_SET_PA_SUBEVT_DATA_PARAMS_LEN 2 +#define HCIC_PARAM_SIZE_SET_PA_RESPONSE_DATA_PARAMS_LEN 8 +#define HCIC_PARAM_SIZE_SET_PA_SYNC_SUBEVT_PARAMS_LEN 5 + +#define HCIC_PARAM_SIZE_SET_PERIODIC_ADV_PARAMS_V2 12 +UINT8 btsnd_hcic_ble_set_periodic_adv_params_v2(UINT8 adv_handle, UINT16 interval_min, UINT16 interval_max, + UINT16 propertics, UINT8 num_subevents, UINT8 subevent_interval, + UINT8 rsp_slot_delay, UINT8 rsp_slot_spacing, UINT8 num_rsp_slots); +UINT8 btsnd_hcic_ble_set_periodic_adv_subevt_data(UINT8 adv_handle, UINT8 num_subevents_with_data, ble_subevent_params *subevent_params); +UINT8 btsnd_hcic_ble_set_periodic_adv_rsp_data(UINT16 sync_handle, UINT16 req_evt, UINT8 req_subevt, UINT8 rsp_subevt, UINT8 rsp_slot, UINT8 rsp_data_len, UINT8 *rsp_data); +UINT8 btsnd_hcic_ble_set_periodic_sync_subevt(UINT16 sync_handle, UINT16 periodic_adv_properties, UINT8 num_subevents_to_sync, UINT8 *subevt); +#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE) + +#if (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) +UINT8 btsnd_hcic_ble_set_ext_adv_params_v2(UINT8 adv_handle, UINT16 properties, UINT32 interval_min, + UINT32 interval_max, UINT8 channel_map, UINT8 own_addr_type, + UINT8 peer_addr_type, BD_ADDR peer_addr, + UINT8 adv_filter_policy, INT8 adv_tx_power, + UINT8 primary_adv_phy, UINT8 secondary_adv_max_skip, + UINT8 secondary_adv_phy, + UINT8 adv_sid, UINT8 scan_req_ntf_enable, + UINT8 primary_adv_phy_options, UINT8 secondary_adv_phy_options); +#endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) + +#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#define HCIC_PARAM_SIZE_READ_LOCAL_SUPP_CAPS_PARAMS_LEN 0 +#define HCIC_PARAM_SIZE_READ_REMOTE_SUPP_CAPS_PARAMS_LEN 2 +#define HCIC_PARAM_SIZE_WRITE_CACHE_REMOTE_SUPP_CAPS_PARAMS_LEN 30 +#define HCIC_PARAM_SIZE_SECURITY_ENABLE_PARAMS_LEN 2 +#define HCIC_PARAM_SIZE_SET_DEFAULT_SETTINGS_PARAMS_LEN 5 +#define HCIC_PARAM_SIZE_READ_REMOTE_FAE_TAB_PARAMS_LEN 2 +#define HCIC_PARAM_SIZE_WRITE_CACHED_REMOTE_FAE_TAB_PARAMS_LEN 74 +#define HCIC_PARAM_SIZE_CREATE_CONFIG_PARAMS_LEN 28 +#define HCIC_PARAM_SIZE_REMOVE_CONFIG_PARAMS_LEN 3 +#define HCIC_PARAM_SIZE_SET_CHANNEL_CLASS_PARAMS_LEN 10 +#define HCIC_PARAM_SIZE_SET_PROCEDURE_PARAMS_LEN 21 +#define HCIC_PARAM_SIZE_SET_PROCEDURE_ENABLE_PARAMS_LEN 4 + +UINT8 btsnd_hcic_ble_cs_read_local_supported_caps(void); +UINT8 btsnd_hcic_ble_cs_read_remote_supported_capabilities(UINT16 conn_handle); +UINT8 btsnd_hcic_ble_cs_write_cached_remote_supported_capabilities(UINT16 conn_handle, UINT8 num_config_supported, UINT16 max_consecutive_proc_supported, + UINT8 num_ant_supported, UINT8 max_ant_paths_supported, UINT8 roles_supported, + UINT8 modes_supported, UINT8 rtt_capability, UINT8 rtt_aa_only_n, + UINT8 rtt_sounding_n, UINT8 rtt_random_payload_n, UINT16 NADM_sounding_capability, + UINT16 NADM_random_capability, UINT8 cs_sync_phys_supported, UINT16 subfeatures_supported, + UINT16 T_IP1_times_supported, UINT16 T_IP2_times_supported, UINT16 T_FCS_times_supported, + UINT16 T_PM_times_supported, UINT8 T_SW_times_supported, UINT8 TX_SNR_capability); + +UINT8 btsnd_hcic_ble_cs_security_enable(UINT16 conn_handle); +UINT8 btsnd_hcic_ble_cs_set_default_settings(UINT16 conn_handle, UINT8 role_enable, UINT8 cs_sync_ant_selection, INT8 max_tx_power); +UINT8 btsnd_hcic_ble_cs_read_remote_fae_table(UINT16 conn_handle); +UINT8 btsnd_hcic_ble_cs_write_cached_remote_fae_table(UINT16 conn_handle, UINT8 *remote_fae_table); +UINT8 btsnd_hcic_ble_cs_create_config(UINT16 conn_handle, UINT8 config_id, UINT8 create_context, + UINT8 main_mode_type, UINT8 sub_mode_type, UINT8 min_main_mode_steps, + UINT8 max_main_mode_steps, UINT8 main_mode_repetition, UINT8 mode_0_steps, + UINT8 role, UINT8 rtt_type, UINT8 cs_sync_phy, UINT8 *channel_map, + UINT8 channel_map_repetition, UINT8 channel_selection_type, UINT8 ch3c_shape, + UINT8 ch3c_jump,UINT8 reserved); +UINT8 btsnd_hcic_ble_cs_remove_config(UINT16 conn_handle, UINT8 config_id); +UINT8 btsnd_hcic_ble_cs_set_channel_classification(UINT8 *channel_class); +UINT8 btsnd_hcic_ble_cs_set_procedure_params(UINT16 conn_handle, UINT8 config_id, UINT16 max_procedure_len, + UINT16 min_procedure_interval, UINT16 max_procedure_interval, + UINT16 max_procedure_count, UINT32 min_subevent_len, + UINT32 max_subevent_len, UINT8 tone_ant_config_selection, + UINT8 phy, UINT8 tx_power_delta, UINT8 preferred_peer_antenna, + UINT8 SNR_control_initiator, UINT8 SNR_control_reflector); +UINT8 btsnd_hcic_ble_cs_procedure_enable(UINT16 conn_handle, UINT8 config_id, UINT8 enable); +#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) + #endif diff --git a/components/bt/host/bluedroid/stack/include/stack/l2c_api.h b/components/bt/host/bluedroid/stack/include/stack/l2c_api.h index b985b641e8..45538ff534 100644 --- a/components/bt/host/bluedroid/stack/include/stack/l2c_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/l2c_api.h @@ -121,7 +121,7 @@ typedef UINT8 tL2CAP_CHNL_DATA_RATE; #define L2CAP_FCR_CHAN_OPT_ALL_MASK (L2CAP_FCR_CHAN_OPT_BASIC | L2CAP_FCR_CHAN_OPT_ERTM | L2CAP_FCR_CHAN_OPT_STREAM) /* Validity check for PSM. PSM values must be odd. Also, all PSM values must -** be assigned such that the least significant bit of the most sigificant +** be assigned such that the least significant bit of the most significant ** octet equals zero. */ #define L2C_INVALID_PSM(psm) (((psm) & 0x0101) != 0x0001) @@ -938,7 +938,7 @@ typedef struct { ** ** Parameters: tL2CAP_UCD_CB_INFO ** -** Return value: TRUE if successs +** Return value: TRUE if success ** *******************************************************************************/ extern BOOLEAN L2CA_UcdRegister ( UINT16 psm, tL2CAP_UCD_CB_INFO *p_cb_info ); @@ -951,7 +951,7 @@ extern BOOLEAN L2CA_UcdRegister ( UINT16 psm, tL2CAP_UCD_CB_INFO *p_cb_info ); ** ** Parameters: PSM ** -** Return value: TRUE if successs +** Return value: TRUE if success ** *******************************************************************************/ extern BOOLEAN L2CA_UcdDeregister ( UINT16 psm ); @@ -968,7 +968,7 @@ extern BOOLEAN L2CA_UcdDeregister ( UINT16 psm ); ** L2CAP_UCD_INFO_TYPE_MTU ** ** -** Return value: TRUE if successs +** Return value: TRUE if success ** *******************************************************************************/ extern BOOLEAN L2CA_UcdDiscover ( UINT16 psm, BD_ADDR rem_bda, UINT8 info_type ); @@ -1001,7 +1001,7 @@ extern UINT16 L2CA_UcdDataWrite (UINT16 psm, BD_ADDR rem_bda, BT_HDR *p_buf, UIN ** Parameters: BD Addr ** Timeout in second ** -** Return value: TRUE if successs +** Return value: TRUE if success ** *******************************************************************************/ extern BOOLEAN L2CA_UcdSetIdleTimeout ( BD_ADDR rem_bda, UINT16 timeout ); @@ -1089,7 +1089,8 @@ extern BOOLEAN L2CA_RegisterFixedChannel (UINT16 fixed_cid, tL2CAP_FIXED_CHNL_R ** Return value: TRUE if connection started ** *******************************************************************************/ -extern BOOLEAN L2CA_ConnectFixedChnl (UINT16 fixed_cid, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_type, BOOLEAN is_aux); +extern BOOLEAN L2CA_ConnectFixedChnl (UINT16 fixed_cid, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_type, BOOLEAN is_aux, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent); /******************************************************************************* ** diff --git a/components/bt/host/bluedroid/stack/l2cap/include/l2c_int.h b/components/bt/host/bluedroid/stack/l2cap/include/l2c_int.h index 88eac86b2f..df956dc442 100644 --- a/components/bt/host/bluedroid/stack/l2cap/include/l2c_int.h +++ b/components/bt/host/bluedroid/stack/l2cap/include/l2c_int.h @@ -379,6 +379,11 @@ typedef struct t_l2c_linkcb { BOOLEAN in_use; /* TRUE when in use, FALSE when not */ tL2C_LINK_STATE link_state; BOOLEAN is_aux; /* This variable used for BLE 5.0 or higher version when do auxiliary connection */ +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + BOOLEAN is_pawr_synced; + UINT8 adv_handle; + UINT8 subevent; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) TIMER_LIST_ENT timer_entry; /* Timer list entry for timeout evt */ UINT16 handle; /* The handle used with LM */ @@ -483,19 +488,24 @@ typedef struct { list_t *p_lcb_pool; /* Link Control Block pool */ list_t *p_ccb_pool; /* Channel Control Block pool */ +#if (CLASSIC_BT_INCLUDED == TRUE) tL2C_RCB rcb_pool[MAX_L2CAP_CLIENTS]; /* Registration info pool */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) - +#if (CLASSIC_BT_INCLUDED == TRUE) UINT8 desire_role; /* desire to be master/slave when accepting a connection */ BOOLEAN disallow_switch; /* FALSE, to allow switch at create conn */ +#endif // (CLASSIC_BT_INCLUDED == TRUE) UINT16 num_lm_acl_bufs; /* # of ACL buffers on controller */ UINT16 idle_timeout; /* Idle timeout */ list_t *rcv_pending_q; /* Recv pending queue */ TIMER_LIST_ENT rcv_hold_tle; /* Timer list entry for rcv hold */ - tL2C_LCB *p_cur_hcit_lcb; /* Current HCI Transport buffer */ + // tL2C_LCB *p_cur_hcit_lcb; /* Current HCI Transport buffer */ +#if (CLASSIC_BT_INCLUDED == TRUE) UINT16 num_links_active; /* Number of links active */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE) UINT16 non_flushable_pbf; /* L2CAP_PKT_START_NON_FLUSHABLE if controller supports */ @@ -524,13 +534,16 @@ typedef struct { tL2C_RCB ble_rcb_pool[BLE_MAX_L2CAP_CLIENTS]; /* Registration info pool */ #endif +#if (CLASSIC_BT_INCLUDED == TRUE) tL2CA_ECHO_DATA_CB *p_echo_data_cb; /* Echo data callback */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (defined(L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE) && (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE)) UINT16 high_pri_min_xmit_quota; /* Minimum number of ACL credit for high priority link */ #endif /* (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE) */ - +#if (CLASSIC_BT_INCLUDED == TRUE) UINT16 dyn_psm; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } tL2C_CB; diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c index fa01790d5f..07377901a7 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c @@ -215,7 +215,7 @@ UINT16 L2CA_ConnectReq (UINT16 psm, BD_ADDR p_bd_addr) ** ** Parameters: PSM: L2CAP PSM for the connection ** BD address of the peer -** Enhaced retransmission mode configurations +** Enhanced retransmission mode configurations ** Returns the CID of the connection, or 0 if it failed to start ** @@ -760,7 +760,7 @@ bool L2CA_GetIdentifiers(uint16_t lcid, uint16_t *rcid, uint16_t *handle) ** ** NOTE This timeout takes effect after at least 1 channel has been ** established and removed. L2CAP maintains its own timer from -** whan a connection is established till the first channel is +** when a connection is established till the first channel is ** set up. *******************************************************************************/ BOOLEAN L2CA_SetIdleTimeout (UINT16 cid, UINT16 timeout, BOOLEAN is_global) @@ -863,7 +863,7 @@ UINT8 L2CA_SetTraceLevel (UINT8 new_level) return (l2cb.l2cap_trace_level); } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function L2CA_SetDesireRole @@ -901,6 +901,7 @@ UINT8 L2CA_SetDesireRole (UINT8 new_role) return (l2cb.desire_role); } +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if (CLASSIC_BT_INCLUDED == TRUE) @@ -1649,7 +1650,8 @@ BOOLEAN L2CA_RegisterFixedChannel (UINT16 fixed_cid, tL2CAP_FIXED_CHNL_REG *p_f ** Return value: TRUE if connection started ** *******************************************************************************/ -BOOLEAN L2CA_ConnectFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda, tBLE_ADDR_TYPE bd_addr_type, BOOLEAN is_aux) +BOOLEAN L2CA_ConnectFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda, tBLE_ADDR_TYPE bd_addr_type, BOOLEAN is_aux, + BOOLEAN is_pawr_synced, UINT8 adv_handle, UINT8 subevent) { tL2C_LCB *p_lcb; tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; @@ -1738,6 +1740,11 @@ BOOLEAN L2CA_ConnectFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda, tBLE_ADDR_TYPE #if (BLE_INCLUDED == TRUE) p_lcb->is_aux = is_aux; p_lcb->open_addr_type = bd_addr_type; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + p_lcb->is_pawr_synced = is_pawr_synced; + p_lcb->adv_handle = adv_handle; + p_lcb->subevent = subevent; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) #endif if (!l2cu_create_conn(p_lcb, transport)) { L2CAP_TRACE_WARNING ("%s() - create_conn failed", __func__); @@ -1901,6 +1908,8 @@ BOOLEAN L2CA_RemoveFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda) tL2C_CCB *p_ccb; tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; + L2CAP_TRACE_DEBUG("%s cid=%04x bda="MACSTR"", __func__, fixed_cid, MAC2STR(rem_bda)); + /* Check CID is valid and registered */ if ( (fixed_cid < L2CAP_FIRST_FIXED_CHNL) || (fixed_cid > L2CAP_LAST_FIXED_CHNL) || (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb == NULL) ) { diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c index 3ce25ab977..e0f787c9a1 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c @@ -92,6 +92,8 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda) { tL2C_LCB *p_lcb; + L2CAP_TRACE_DEBUG("%s rem_bda="MACSTR"", __func__, MAC2STR(rem_bda)); + /* There can be only one BLE connection request outstanding at a time */ if (btm_ble_get_conn_st() == BLE_CONN_IDLE) { L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending"); @@ -99,10 +101,8 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda) } if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN)) { - L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: %08x%04x Cancel: %08x%04x", - (l2cb.ble_connecting_bda[0] << 24) + (l2cb.ble_connecting_bda[1] << 16) + (l2cb.ble_connecting_bda[2] << 8) + l2cb.ble_connecting_bda[3], - (l2cb.ble_connecting_bda[4] << 8) + l2cb.ble_connecting_bda[5], - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: "MACSTR" Cancel: "MACSTR"", + MAC2STR(l2cb.ble_connecting_bda), MAC2STR(rem_bda)); return (FALSE); } @@ -148,16 +148,12 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in /* If we don't have one, create one and accept the connection. */ if (!p_lcb || !p_acl_cb) { - L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x", - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR "MACSTR"", MAC2STR(rem_bda)); return (FALSE); } if (p_lcb->transport != BT_TRANSPORT_LE) { - L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE", - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR "MACSTR" not LE", MAC2STR(rem_bda)); return (FALSE); } @@ -172,7 +168,7 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL){ status = HCI_ERR_ILLEGAL_COMMAND; need_cb = true; - L2CAP_TRACE_ERROR("There are two connection parameter requests that are being updated, please try later "); + L2CAP_TRACE_ERROR("%s connection parameter update in progress, please try later", __func__); } if ((need_cb == TRUE) && (conn_callback_func.update_conn_param_cb != NULL)) { @@ -221,20 +217,16 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable) p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE); if (!p_lcb) { - L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x", - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR "MACSTR"", MAC2STR(rem_bda)); return (FALSE); } - L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x", __FUNCTION__, - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5], enable, p_lcb->conn_update_mask); + L2CAP_TRACE_API ("%s - BD_ADDR "MACSTR" enable %d current upd state 0x%02x", + __func__, MAC2STR(rem_bda), enable, p_lcb->conn_update_mask); if (p_lcb->transport != BT_TRANSPORT_LE) { - L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__, - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5], p_lcb->link_role); + L2CAP_TRACE_WARNING ("%s - BD_ADDR "MACSTR" not LE (link role %d)", + __func__, MAC2STR(rem_bda), p_lcb->link_role); return (FALSE); } @@ -514,8 +506,13 @@ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE typ void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout) { +#if (BLE_TOPOLOGY_CHECK == TRUE) btm_ble_update_link_topology_mask(role, TRUE); - +#else + btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE; + /* make device fall back into undirected adv mode by default */ + btm_cb.ble_ctr_cb.inq_var.directed_conn = BTM_BLE_CONNECT_EVT; +#endif // (BLE_TOPOLOGY_CHECK == TRUE) if (role == HCI_ROLE_MASTER) { l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout); } else { @@ -718,6 +715,11 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) UINT16 cmd_len; UINT16 min_interval, max_interval, latency, timeout; + if (pkt_len < L2CAP_CMD_OVERHEAD) { + L2CAP_TRACE_WARNING ("L2CAP - LE - pkt too short: %d", pkt_len); + return; + } + p_pkt_end = p + pkt_len; STREAM_TO_UINT8 (cmd_code, p); @@ -734,6 +736,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) case L2CAP_CMD_REJECT: case L2CAP_CMD_ECHO_RSP: case L2CAP_CMD_INFO_RSP: + if (cmd_len < 2) { + L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len); + return; + } p += 2; break; case L2CAP_CMD_ECHO_REQ: @@ -742,6 +748,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) break; case L2CAP_CMD_BLE_UPDATE_REQ: + if (cmd_len < 8) { + L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len); + return; + } STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */ STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */ STREAM_TO_UINT16 (latency, p); /* 0x0000 - 0x03E8 */ @@ -784,6 +794,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) break; case L2CAP_CMD_BLE_UPDATE_RSP: { + if (cmd_len < 2) { + L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len); + return; + } UINT16 result = 0; STREAM_TO_UINT16(result, p); //result = 0 connection param accepted, result = 1 connection param rejected. UINT8 status = (result == 0) ? HCI_SUCCESS : HCI_ERR_PARAM_OUT_OF_RANGE; @@ -796,6 +810,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) break; } case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ: { + if (cmd_len < 10) { + L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len); + return; + } tL2C_CCB *p_ccb = NULL; tL2C_RCB *p_rcb = NULL; UINT16 spsm; @@ -844,6 +862,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) break; } case L2CAP_CMD_DISC_REQ: { + if (cmd_len < 4) { + L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len); + return; + } tL2C_CCB *p_ccb = NULL; UINT16 lcid; UINT16 rcid; @@ -953,11 +975,14 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) #endif // CONTROLLER_RPA_LIST_ENABLE #endif // (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE) +#if (BLE_TOPOLOGY_CHECK == TRUE) if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) { l2cu_release_lcb (p_lcb); L2CAP_TRACE_ERROR("initiate direct connection fail, topology limitation"); return FALSE; } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) + uint32_t link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT; if(GATTC_CONNECT_RETRY_COUNT) { if(!p_lcb->retry_create_con) { @@ -1020,6 +1045,10 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) } tHCI_CreatExtConn aux_conn = {0}; +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + aux_conn.adv_handle = p_lcb->adv_handle; + aux_conn.subevent = p_lcb->subevent; +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) aux_conn.filter_policy = FALSE; aux_conn.own_addr_type = own_addr_type; aux_conn.peer_addr_type = peer_addr_type; @@ -1041,9 +1070,19 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN); btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, link_timeout); btm_ble_set_conn_st (BLE_DIR_CONN); - if(!btsnd_hcic_ble_create_ext_conn(&aux_conn)) { - l2cu_release_lcb (p_lcb); - L2CAP_TRACE_ERROR("initiate Aux connection failed, no resources"); +#if (BT_BLE_FEAT_PAWR_EN == TRUE) + if (p_lcb->is_pawr_synced) { + if(!btsnd_hcic_ble_create_ext_conn_v2(&aux_conn)) { + l2cu_release_lcb (p_lcb); + L2CAP_TRACE_ERROR("initiate pawr sync connection failed, no resources"); + } + } else +#endif // (BT_BLE_FEAT_PAWR_EN == TRUE) + { + if(!btsnd_hcic_ble_create_ext_conn(&aux_conn)) { + l2cu_release_lcb (p_lcb); + L2CAP_TRACE_ERROR("initiate Aux connection failed, no resources"); + } } #else L2CAP_TRACE_ERROR("BLE 5.0 not support!\n"); @@ -1073,11 +1112,11 @@ BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb) L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st); btm_ble_enqueue_direct_conn_req(p_lcb); -#if (tGATT_BG_CONN_DEV == TRUE) +#if (GATT_BG_CONN_DEV == TRUE) if (conn_st == BLE_BG_CONN) { btm_ble_suspend_bg_conn(); } -#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#endif // #if (GATT_BG_CONN_DEV == TRUE) rt = TRUE; } return rt; @@ -1104,6 +1143,7 @@ void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs) l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs; } +#if (BLE_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2c_ble_link_adjust_allocation @@ -1223,6 +1263,7 @@ void l2c_ble_link_adjust_allocation (void) } } } +#endif // #if (BLE_INCLUDED == TRUE) #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) /******************************************************************************* diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_link.c b/components/bt/host/bluedroid/stack/l2cap/l2c_link.c index 9cb412e748..a51c4e8427 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_link.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_link.c @@ -392,10 +392,12 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) p_lcb->link_state = LST_DISCONNECTING; #if (BLE_INCLUDED == TRUE) +#if (BLE_TOPOLOGY_CHECK == TRUE) /* Check for BLE and handle that differently */ if (p_lcb->transport == BT_TRANSPORT_LE) { btm_ble_update_link_topology_mask(p_lcb->link_role, FALSE); } +#endif // (BLE_TOPOLOGY_CHECK == TRUE) #endif #if (CLASSIC_BT_INCLUDED == TRUE) /* Link is disconnected. For all channels, send the event through */ @@ -734,7 +736,7 @@ void l2c_info_timeout (tL2C_LCB *p_lcb) #endif ///CLASSIC_BT_INCLUDED == TRUE } } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2c_link_adjust_allocation @@ -855,7 +857,7 @@ void l2c_link_adjust_allocation (void) } } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2c_link_adjust_chnl_allocation @@ -936,6 +938,7 @@ UINT8 l2c_link_pkts_rcvd (UINT16 *num_pkts, UINT16 *handles) return (num_found); } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2c_link_role_changed @@ -973,6 +976,7 @@ void l2c_link_role_changed (BD_ADDR bd_addr, UINT8 new_role, UINT8 hci_status) } } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -1009,7 +1013,9 @@ void l2c_pin_code_request (BD_ADDR bd_addr) *******************************************************************************/ BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb) { +#if (CLASSIC_BT_INCLUDED == TRUE) tBTM_PM_MODE mode; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) tL2C_CCB *p_ccb; BOOLEAN need_to_active = FALSE; @@ -1029,6 +1035,7 @@ BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb) /* if we have packets to send */ if ( need_to_active ) { +#if (CLASSIC_BT_INCLUDED == TRUE) /* check power mode */ if (BTM_ReadPowerMode(p_lcb->remote_bd_addr, &mode) == BTM_SUCCESS) { if ( mode == BTM_PM_STS_PENDING ) { @@ -1037,6 +1044,7 @@ BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb) return TRUE; } } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } return FALSE; } diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_main.c b/components/bt/host/bluedroid/stack/l2cap/l2c_main.c index dfdef99bef..d5d6b91dbb 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_main.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_main.c @@ -859,8 +859,10 @@ void l2c_init (void) l2c_cb_ptr = (tL2C_CB *)osi_malloc(sizeof(tL2C_CB)); #endif /* #if L2C_DYNAMIC_MEMORY */ memset (&l2cb, 0, sizeof (tL2C_CB)); +#if (CLASSIC_BT_INCLUDED == TRUE) /* the psm is increased by 2 before being used */ l2cb.dyn_psm = 0xFFF; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) l2cb.p_ccb_pool = list_new(osi_free_func); if (l2cb.p_ccb_pool == NULL) { @@ -877,13 +879,13 @@ void l2c_init (void) #endif - +#if (CLASSIC_BT_INCLUDED == TRUE) #ifdef L2CAP_DESIRED_LINK_ROLE l2cb.desire_role = L2CAP_DESIRED_LINK_ROLE; #else l2cb.desire_role = HCI_ROLE_SLAVE; #endif - +#endif // (CLASSIC_BT_INCLUDED == TRUE) /* Set the default idle timeout */ l2cb.idle_timeout = L2CAP_LINK_INACTIVITY_TOUT; diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c index 97cae231f7..de1faec749 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c @@ -113,8 +113,10 @@ tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPOR } else #endif { +#if (CLASSIC_BT_INCLUDED == TRUE) l2cb.num_links_active++; l2c_link_adjust_allocation(); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } p_lcb->link_xmit_data_q = list_new(NULL); return (p_lcb); @@ -158,6 +160,9 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb) { tL2C_CCB *p_ccb; + L2CAP_TRACE_DEBUG("%s handle=%u bda="MACSTR"", + __func__, p_lcb->handle, MAC2STR(p_lcb->remote_bd_addr)); + p_lcb->in_use = FALSE; p_lcb->is_bonding = FALSE; #if (BLE_INCLUDED == TRUE) @@ -258,11 +263,13 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb) } else #endif { +#if (CLASSIC_BT_INCLUDED == TRUE) if (l2cb.num_links_active >= 1) { l2cb.num_links_active--; } l2c_link_adjust_allocation(); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } /* Check for ping outstanding */ @@ -366,6 +373,7 @@ uint8_t l2cu_ble_plcb_active_count(void) } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2cu_get_conn_role @@ -382,6 +390,7 @@ UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb) { return l2cb.desire_role; } +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -1794,6 +1803,7 @@ tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid) return (NULL); } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2cu_allocate_rcb @@ -1823,6 +1833,7 @@ tL2C_RCB *l2cu_allocate_rcb (UINT16 psm) /* If here, no free RCB found */ return (NULL); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE) /******************************************************************************* @@ -1902,7 +1913,7 @@ void l2cu_disconnect_chnl (tL2C_CCB *p_ccb) } } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2cu_find_rcb_by_psm @@ -1927,6 +1938,7 @@ tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm) /* If here, no match found */ return (NULL); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE) /******************************************************************************* @@ -2271,8 +2283,11 @@ BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport) #if BTM_SCO_INCLUDED == TRUE BOOLEAN is_sco_active; #endif + +#if (CLASSIC_BT_INCLUDED == TRUE) list_node_t *p_node = NULL; tL2C_LCB *p_lcb_cur = NULL; +#endif // (CLASSIC_BT_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE) tBT_DEVICE_TYPE dev_type; @@ -2295,6 +2310,7 @@ BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport) } #endif +#if (CLASSIC_BT_INCLUDED == TRUE) /* If there is a connection where we perform as a slave, try to switch roles for this connection */ for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) { @@ -2338,6 +2354,8 @@ BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport) p_lcb->link_state = LST_CONNECTING; return (l2cu_create_conn_after_switch (p_lcb)); +#endif // (CLASSIC_BT_INCLUDED == TRUE) + return false; } /******************************************************************************* @@ -2364,7 +2382,7 @@ UINT8 l2cu_get_num_hi_priority (void) return no_hi; } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function l2cu_create_conn_after_switch @@ -2439,7 +2457,7 @@ BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb) return (TRUE); } - +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** diff --git a/components/bt/host/bluedroid/stack/smp/aes.c b/components/bt/host/bluedroid/stack/smp/aes.c index 18b56b877d..6555b6af97 100644 --- a/components/bt/host/bluedroid/stack/smp/aes.c +++ b/components/bt/host/bluedroid/stack/smp/aes.c @@ -48,6 +48,8 @@ /* add the target configuration to allow using internal data types and compilation options */ #include "common/bt_target.h" +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) + /* define if you have fast 32-bit types on your system */ #if 1 # define HAVE_UINT_32T @@ -569,7 +571,7 @@ return_type aes_set_key( const unsigned char key[], length_type keylen, aes_cont /* Encrypt a single block of 16 bytes */ -/* @breif change the name by snake for avoid the conflict with libcrypto */ +/* @brief change the name by snake for avoid the conflict with libcrypto */ return_type bluedroid_aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) { if ( ctx->rnd ) { @@ -935,4 +937,6 @@ void bluedroid_aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char o copy_and_key( out, s1, o_key ); } +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ + #endif diff --git a/components/bt/host/bluedroid/stack/smp/include/aes.h b/components/bt/host/bluedroid/stack/smp/include/aes.h index 48495bb174..9c14e22dcf 100644 --- a/components/bt/host/bluedroid/stack/smp/include/aes.h +++ b/components/bt/host/bluedroid/stack/smp/include/aes.h @@ -31,6 +31,10 @@ #ifndef AES_H #define AES_H +#include "common/bt_target.h" + +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) + #if 1 # define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ #endif @@ -117,7 +121,7 @@ return_type aes_cbc_decrypt( const unsigned char *in, The encryption subroutines take a key in an array of bytes in key[L] where L is 16, 24 or 32 bytes for key lengths of 128, 192, and 256 bits respectively. They then encrypts the input - data, in[] with this key and put the reult in the output array + data, in[] with this key and put the result in the output array out[]. In addition, the second key array, o_key[L], is used to output the key that is needed by the decryption subroutine to reverse the encryption operation. The two key arrays can @@ -159,4 +163,6 @@ void bluedroid_aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char o_key[2 * N_BLOCK] ); #endif -#endif +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ + +#endif /* AES_H */ diff --git a/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h b/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h index 3b28e0c99a..7c2f7279eb 100644 --- a/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h +++ b/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h @@ -24,9 +24,12 @@ #pragma once -#include "p_256_multprecision.h" #include "common/bt_target.h" +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) + +#include "p_256_multprecision.h" + typedef unsigned long DWORD; typedef struct { @@ -72,3 +75,5 @@ bool ECC_CheckPointIsInElliCur_P256(Point *p); #define ECC_PointMult(q, p, n, keyLength) ECC_PointMult_Bin_NAF(q, p, n, keyLength) void p_256_init_curve(UINT32 keyLength); + +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h b/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h index 0a33b4e24f..83b7f1876f 100644 --- a/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h +++ b/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h @@ -24,6 +24,9 @@ #pragma once #include "stack/bt_types.h" +#include "common/bt_target.h" + +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) /* Type definitions */ typedef unsigned long DWORD; @@ -58,3 +61,5 @@ DWORD multiprecision_lshift(DWORD *c, DWORD *a, uint32_t keyLength); void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); void multiprecision_fast_mod(DWORD *c, DWORD *a); void multiprecision_fast_mod_P256(DWORD *c, DWORD *a); + +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c b/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c index abf9a8eecc..b3fca522de 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c @@ -23,6 +23,10 @@ ******************************************************************************/ #include +#include "common/bt_target.h" + +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) + #include "p_256_ecc_pp.h" void p_256_init_curve(UINT32 keyLength) @@ -76,3 +80,5 @@ void p_256_init_curve(UINT32 keyLength) ec->G.y[0] = 0x37bf51f5; } } + +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c b/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c index 1f49c652bd..d3b9452c1e 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c @@ -24,9 +24,12 @@ //#include //#include #include +#include "common/bt_target.h" + +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) + #include "p_256_ecc_pp.h" #include "p_256_multprecision.h" -#include "common/bt_target.h" #if SMP_DYNAMIC_MEMORY == FALSE elliptic_curve_t curve; @@ -281,3 +284,5 @@ bool ECC_CheckPointIsInElliCur_P256(Point *p) return true; } } + +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c b/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c index 1dbca13756..92291d98b3 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c @@ -24,6 +24,9 @@ #include #include "common/bt_target.h" + +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) + #include "p_256_ecc_pp.h" #include "p_256_multprecision.h" @@ -365,7 +368,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a) uint8_t UB; uint8_t UC; uint8_t UD; - uint8_t UE; + uint8_t U_E; uint8_t UF; uint8_t UG; DWORD U; @@ -381,7 +384,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a) // E = a[8] + a[9]; E = a[8]; E += a[9]; - UE = (E < a[9]); + U_E = (E < a[9]); // F = a[9] + a[10]; F = a[9]; @@ -418,7 +421,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a) c[0] = a[0]; c[0] += E; U = (c[0] < E); - U += UE; + U += U_E; U -= (c[0] < A); U -= UA; c[0] -= A; @@ -479,7 +482,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a) U -= (c[3] < a[15]); c[3] -= a[15]; U -= (c[3] < E); - U -= UE; + U -= U_E; c[3] -= E; if (U & 0x80000000) { @@ -546,7 +549,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a) c[6] += a[15]; U += (c[6] < a[15]); U -= (c[6] < E); - U -= UE; + U -= U_E; c[6] -= E; if (U & 0x80000000) { @@ -645,3 +648,5 @@ void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength) multiprecision_copy(aminus, C, keyLength); } } + +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/smp_act.c b/components/bt/host/bluedroid/stack/smp/smp_act.c index b467a1c13d..1c88b8dcd3 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_act.c +++ b/components/bt/host/bluedroid/stack/smp/smp_act.c @@ -22,7 +22,15 @@ #include "btm_int.h" #include "stack/l2c_api.h" #include "smp_int.h" +#if (SMP_CRYPTO_MBEDTLS == TRUE) +#include "mbedtls/ecp.h" +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) +#include "tinycrypt/ecc_dh.h" +#include "tinycrypt/ecc.h" +#include "tinycrypt/constants.h" +#else #include "p_256_ecc_pp.h" +#endif //#include "utils/include/bt_utils.h" #if SMP_INCLUDED == TRUE @@ -79,7 +87,7 @@ static bool lmp_version_below(BD_ADDR bda, uint8_t version) *******************************************************************************/ static void smp_update_key_mask (tSMP_CB *p_cb, UINT8 key_type, BOOLEAN recv) { - SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x\n", + SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x", __func__, p_cb->role, recv, p_cb->local_i_key, p_cb->local_r_key); if (((p_cb->le_secure_connections_mode_is_used) || @@ -103,8 +111,8 @@ static void smp_update_key_mask (tSMP_CB *p_cb, UINT8 key_type, BOOLEAN recv) } } - SMP_TRACE_DEBUG("updated local_i_key = %02x, local_r_key = %02x\n", p_cb->local_i_key, - p_cb->local_r_key); + SMP_TRACE_DEBUG("updated local_i_key = %02x, local_r_key = %02x", + p_cb->local_i_key, p_cb->local_r_key); } /******************************************************************************* @@ -115,7 +123,7 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { tSMP_EVT_DATA cb_data; tSMP_STATUS callback_rc; - SMP_TRACE_DEBUG("%s p_cb->cb_evt=%d\n", __func__, p_cb->cb_evt); + SMP_TRACE_DEBUG("%s cb_evt=%d", __func__, p_cb->cb_evt); if (p_cb->p_callback && p_cb->cb_evt != 0) { switch (p_cb->cb_evt) { case SMP_IO_CAP_REQ_EVT: @@ -171,11 +179,11 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) p_cb->local_r_key = 0; } - SMP_TRACE_DEBUG ("rcvd auth_req: 0x%02x, io_cap: %d \ - loc_oob_flag: %d loc_enc_size: %d," - "local_i_key: 0x%02x, local_r_key: 0x%02x\n", - p_cb->loc_auth_req, p_cb->local_io_capability, p_cb->loc_oob_flag, - p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key); + SMP_TRACE_DEBUG ("rcvd auth_req: 0x%02x, io_cap: %d," + "loc_oob_flag: %d loc_enc_size: %d," + "local_i_key: 0x%02x, local_r_key: 0x%02x", + p_cb->loc_auth_req, p_cb->local_io_capability, p_cb->loc_oob_flag, + p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key); p_cb->secure_connections_only_mode_required = (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE; @@ -222,8 +230,6 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) p_cb->discard_sec_req = FALSE; smp_sm_event(p_cb, SMP_DISCARD_SEC_REQ_EVT, NULL); } - - SMP_TRACE_DEBUG("%s return\n", __func__); } /******************************************************************************* @@ -249,7 +255,7 @@ void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); #if (BLE_INCLUDED == TRUE) tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda); @@ -269,7 +275,7 @@ void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); #if (BLE_INCLUDED == TRUE) p_cb->local_i_key &= p_cb->peer_i_key; @@ -291,7 +297,7 @@ void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb); } @@ -313,7 +319,7 @@ void smp_send_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_send_cmd(SMP_OPCODE_RAND, p_cb); } @@ -323,7 +329,7 @@ void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_send_cmd(SMP_OPCODE_PAIR_PUBLIC_KEY, p_cb); } @@ -365,7 +371,7 @@ void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { tBTM_LE_LENC_KEYS le_key; - SMP_TRACE_DEBUG("%s p_cb->loc_enc_size = %d\n", __func__, p_cb->loc_enc_size); + SMP_TRACE_DEBUG("%s loc_enc_size = %d", __func__, p_cb->loc_enc_size); smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE); smp_send_cmd(SMP_OPCODE_ENCRYPT_INFO, p_cb); @@ -383,8 +389,6 @@ void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) (tBTM_LE_KEY_VALUE *)&le_key, TRUE); } - SMP_TRACE_DEBUG ("%s\n", __func__); - smp_key_distribution(p_cb, NULL); #endif ///BLE_INCLUDED == TRUE } @@ -395,7 +399,7 @@ void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, FALSE); smp_send_cmd(SMP_OPCODE_IDENTITY_INFO, p_cb); @@ -420,7 +424,7 @@ void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { tBTM_LE_LCSRK_KEYS key; - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, FALSE); if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb)) { @@ -455,12 +459,10 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) tBTM_BLE_SEC_REQ_ACT sec_req_act; UINT8 reason; - SMP_TRACE_DEBUG("%s auth_req=0x%x", __func__, auth_req); - p_cb->cb_evt = 0; btm_ble_link_sec_check(p_cb->pairing_bda, auth_req, &sec_req_act); - SMP_TRACE_DEBUG("%s sec_req_act=0x%x", __func__, sec_req_act); + SMP_TRACE_DEBUG("%s auth_req=0x%x sec_req_act=0x%x", __func__, auth_req, sec_req_act); switch (sec_req_act) { case BTM_BLE_SEC_REQ_ACT_ENCRYPT: @@ -475,6 +477,8 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) /* respond to non SC pairing request as failure in SC only mode */ if (p_cb->secure_connections_only_mode_required && (auth_req & SMP_SC_SUPPORT_BIT) == 0) { + SMP_TRACE_ERROR("%s SC mode not support, auth_req=0x%x", + __func__, auth_req); reason = SMP_PAIR_AUTH_FAIL; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } else { @@ -503,7 +507,7 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { UINT8 res = *(UINT8 *)p_data; - SMP_TRACE_DEBUG("%s", __func__); + SMP_TRACE_DEBUG("%s res=0x%x", __func__, res); if (res != SMP_SUCCESS) { smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, p_data); } else { /*otherwise, start pairing */ @@ -560,7 +564,7 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT8 reason = SMP_ENC_KEY_SIZE; tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda); - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); /* erase all keys if it is slave proc pairing req*/ if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE)) { btm_sec_clear_ble_keys(p_dev_rec); @@ -682,7 +686,7 @@ void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT8 *p = (UINT8 *)p_data; UINT8 reason = SMP_INVALID_PARAMETERS; - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); if (smp_command_has_invalid_parameters(p_cb)) { smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); @@ -775,10 +779,98 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) } /* In order to prevent the x and y coordinates of the public key from being modified, we need to check whether the x and y coordinates are on the given elliptic curve. */ +#if (SMP_CRYPTO_MBEDTLS == TRUE) + { + /* + * mbedTLS validates the public key using mbedtls_ecp_check_pubkey. + */ + mbedtls_ecp_group grp = {0}; + mbedtls_ecp_point pt = {0}; + int rc; + UINT8 pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */ + + mbedtls_ecp_group_init(&grp); + mbedtls_ecp_point_init(&pt); + + /* Load the group */ + rc = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1); + if (rc != 0) { + SMP_TRACE_ERROR("%s, Invalid Public key. mbedtls_ecp_group_load failed: %d\n", __func__, rc); + mbedtls_ecp_point_free(&pt); + mbedtls_ecp_group_free(&grp); + reason = SMP_INVALID_PARAMETERS; + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); + return; + } + + /* Construct peer public key in uncompressed format (0x04 || X || Y) */ + pub_be[0] = 0x04; + for (int i = 0; i < BT_OCTET32_LEN; i++) { + pub_be[1 + i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i]; + pub_be[33 + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i]; + } + + /* Read public key */ + rc = mbedtls_ecp_point_read_binary(&grp, &pt, pub_be, sizeof(pub_be)); + if (rc != 0) { + SMP_TRACE_ERROR("%s, Invalid Public key. mbedtls_ecp_point_read_binary failed: %d\n", __func__, rc); + mbedtls_ecp_point_free(&pt); + mbedtls_ecp_group_free(&grp); + reason = SMP_INVALID_PARAMETERS; + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); + return; + } + + /* Validate public key - check if it's on the curve */ + rc = mbedtls_ecp_check_pubkey(&grp, &pt); + if (rc != 0) { + SMP_TRACE_ERROR("%s, Invalid Public key. mbedtls_ecp_check_pubkey failed: %d\n", __func__, rc); + mbedtls_ecp_point_free(&pt); + mbedtls_ecp_group_free(&grp); + reason = SMP_INVALID_PARAMETERS; + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); + return; + } + + /* Key is valid, clean up */ + mbedtls_ecp_point_free(&pt); + mbedtls_ecp_group_free(&grp); + } +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) + { + /* + * TinyCrypt validates the public key using uECC_valid_public_key. + * TinyCrypt expects public key in format: X (32 bytes) || Y (32 bytes), no prefix. + */ + UINT8 pub_be[64]; /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */ + + /* Convert peer public key from little-endian to big-endian */ + /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + pub_be[i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i]; + pub_be[BT_OCTET32_LEN + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i]; + } + + /* Validate public key - TinyCrypt will check if it's on the curve */ + /* uECC_valid_public_key returns 0 if valid, negative value if invalid */ + if (uECC_valid_public_key(pub_be, uECC_secp256r1()) < 0) { + SMP_TRACE_ERROR("%s, Invalid Public key. uECC_valid_public_key failed\n", __func__); + reason = SMP_INVALID_PARAMETERS; + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); + memset(pub_be, 0, sizeof(pub_be)); + return; + } + + /* Clear sensitive data from stack */ + memset(pub_be, 0, sizeof(pub_be)); + } +#else if (!ECC_CheckPointIsInElliCur_P256((Point *)&p_cb->peer_publ_key)) { SMP_TRACE_ERROR("%s, Invalid Public key.", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); + return; } +#endif /* SMP_CRYPTO_MBEDTLS */ p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY; smp_wait_for_both_public_keys(p_cb, NULL); @@ -1170,6 +1262,7 @@ void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) } } else { + SMP_TRACE_ERROR("%s pairing failed - check confirm value error", __func__); reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } @@ -1213,6 +1306,7 @@ void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) } if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY) { + SMP_TRACE_ERROR("%s start encryption failed, cmd=0x%x", __func__, cmd); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } } @@ -1239,7 +1333,7 @@ void smp_enc_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT8 enc_enable = *(UINT8 *)p_data; UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL; - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s %u", __func__, enc_enable); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } diff --git a/components/bt/host/bluedroid/stack/smp/smp_api.c b/components/bt/host/bluedroid/stack/smp/smp_api.c index 78e295f4f1..0b00bf151c 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_api.c +++ b/components/bt/host/bluedroid/stack/smp/smp_api.c @@ -35,7 +35,9 @@ #include "stack/hcimsgs.h" #include "stack/btu.h" +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) #include "p_256_ecc_pp.h" +#endif #include "osi/allocator.h" /******************************************************************************* @@ -51,12 +53,16 @@ void SMP_Init(void) { #if SMP_DYNAMIC_MEMORY smp_cb_ptr = (tSMP_CB *)osi_malloc(sizeof(tSMP_CB)); +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) curve_ptr = (elliptic_curve_t *)osi_malloc(sizeof(elliptic_curve_t)); curve_p256_ptr = (elliptic_curve_t *)osi_malloc(sizeof(elliptic_curve_t)); +#endif #endif memset(&smp_cb, 0, sizeof(tSMP_CB)); +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) memset(&curve, 0, sizeof(elliptic_curve_t)); memset(&curve_p256, 0, sizeof(elliptic_curve_t)); +#endif #if defined(SMP_INITIAL_TRACE_LEVEL) smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL; @@ -66,8 +72,10 @@ void SMP_Init(void) SMP_TRACE_EVENT ("%s", __FUNCTION__); smp_l2cap_if_init(); +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) /* initialization of P-256 parameters */ p_256_init_curve(KEY_LENGTH_DWORDS_P256); +#endif } void SMP_Free(void) @@ -75,8 +83,10 @@ void SMP_Free(void) memset(&smp_cb, 0, sizeof(tSMP_CB)); #if SMP_DYNAMIC_MEMORY FREE_AND_RESET(smp_cb_ptr); +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) FREE_AND_RESET(curve_ptr); FREE_AND_RESET(curve_p256_ptr); +#endif #endif /* #if SMP_DYNAMIC_MEMORY */ } @@ -161,7 +171,7 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr) memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN); - if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE)) { + if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE, FALSE, 0xFF, 0xFF)) { SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.\n", __FUNCTION__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); return status; @@ -205,7 +215,7 @@ tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr) memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN); - if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE)) { + if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE, FALSE, 0xFF, 0xFF)) { SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__); smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status); return status; @@ -236,7 +246,7 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr) if ( (p_cb->state != SMP_STATE_IDLE) && (!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) ) { p_cb->is_pair_cancel = TRUE; - SMP_TRACE_DEBUG("Cancel Pairing: set fail reason Unknown"); + SMP_TRACE_ERROR("%s Cancel Pairing: set fail reason Unknown", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &err_code); status = TRUE; } @@ -434,6 +444,8 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data } if (res != SMP_SUCCESS || len == 0 || !p_data) { + SMP_TRACE_ERROR("%s pairing failed, res=0x%x len=%u p_data=%p", + __func__, res, len, p_data); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); } else { if (len > BT_OCTET16_LEN) { @@ -524,10 +536,10 @@ void SMP_SecureConnectionOobDataReply(UINT8 *p_data) ** Description This function is called to encrypt the data with the specified ** key ** -** Parameters: key - Pointer to key key[0] conatins the MSB +** Parameters: key - Pointer to key key[0] contains the MSB ** key_len - key length ** plain_text - Pointer to data to be encrypted -** plain_text[0] conatins the MSB +** plain_text[0] contains the MSB ** pt_len - plain text length ** p_out - output of the encrypted texts ** diff --git a/components/bt/host/bluedroid/stack/smp/smp_cmac.c b/components/bt/host/bluedroid/stack/smp/smp_cmac.c index e47c56b71f..b097a05d23 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_cmac.c +++ b/components/bt/host/bluedroid/stack/smp/smp_cmac.c @@ -32,7 +32,16 @@ #include "stack/btm_ble_api.h" #include "smp_int.h" #include "stack/hcimsgs.h" +#if (SMP_CRYPTO_MBEDTLS == TRUE) +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) +#include "tinycrypt/aes.h" +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/constants.h" +#endif +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) typedef struct { UINT8 *text; UINT16 len; @@ -46,6 +55,7 @@ const BT_OCTET16 const_Rb = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ void print128(BT_OCTET16 x, const UINT8 *key_name) { @@ -75,6 +85,7 @@ void print128(BT_OCTET16 x, const UINT8 *key_name) ** Returns void ** *******************************************************************************/ +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) static void padding ( BT_OCTET16 dest, UINT8 length ) { UINT8 i, *p = dest; @@ -83,6 +94,7 @@ static void padding ( BT_OCTET16 dest, UINT8 length ) p[BT_OCTET16_LEN - i - 1] = ( i == length ) ? 0x80 : 0; } } + /******************************************************************************* ** ** Function leftshift_onebit @@ -104,6 +116,8 @@ static void leftshift_onebit(UINT8 *input, UINT8 *output) } return; } +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ + /******************************************************************************* ** ** Function cmac_aes_cleanup @@ -113,6 +127,7 @@ static void leftshift_onebit(UINT8 *input, UINT8 *output) ** Returns void ** *******************************************************************************/ +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) static void cmac_aes_cleanup(void) { if (cmac_cb.text != NULL) { @@ -167,11 +182,12 @@ static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 t return FALSE; } } + /******************************************************************************* ** ** Function cmac_prepare_last_block ** -** Description This function proceeed to prepare the last block of message +** Description This function proceed to prepare the last block of message ** Mn depending on the size of the message. ** ** Returns void @@ -197,6 +213,8 @@ static void cmac_prepare_last_block (BT_OCTET16 k1, BT_OCTET16 k2) smp_xor_128(&cmac_cb.text[0], k2); } } +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ + /******************************************************************************* ** ** Function cmac_subkey_cont @@ -206,6 +224,7 @@ static void cmac_prepare_last_block (BT_OCTET16 k1, BT_OCTET16 k2) ** Returns void ** *******************************************************************************/ +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) static void cmac_subkey_cont(tSMP_ENC *p) { UINT8 k1[BT_OCTET16_LEN], k2[BT_OCTET16_LEN]; @@ -262,6 +281,8 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key) return ret; } +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ + /******************************************************************************* ** ** Function aes_cipher_msg_auth_code @@ -271,7 +292,7 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key) ** Parameters key - CMAC key in little endian order, expect SRK when used by SMP. ** input - text to be signed in little endian byte order. ** length - length of the input in byte. -** tlen - lenth of mac desired +** tlen - length of mac desired ** p_signature - data pointer to where signed data to be stored, tlen long. ** ** Returns FALSE if out of resources, TRUE in other cases. @@ -280,43 +301,189 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key) BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length, UINT16 tlen, UINT8 *p_signature) { - UINT16 len, diff; - UINT16 n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN; /* n is number of rounds */ BOOLEAN ret = FALSE; SMP_TRACE_EVENT ("%s", __func__); - if (n == 0) { - n = 1; +#if (SMP_CRYPTO_MBEDTLS == TRUE) + { + /* + * mbedTLS CMAC implementation. + * Bluedroid and mbedTLS both use little-endian, so no byte order conversion needed. + */ + mbedtls_cipher_context_t ctx = {0}; + const mbedtls_cipher_info_t *cipher_info; + int rc; + + SMP_TRACE_DEBUG("AES128_CMAC (mbedTLS) started, length = %d", length); + + mbedtls_cipher_init(&ctx); + + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + if (cipher_info == NULL) { + SMP_TRACE_ERROR("mbedtls_cipher_info_from_type failed"); + mbedtls_cipher_free(&ctx); + return FALSE; + } + + rc = mbedtls_cipher_setup(&ctx, cipher_info); + if (rc != 0) { + SMP_TRACE_ERROR("mbedtls_cipher_setup failed: %d", rc); + mbedtls_cipher_free(&ctx); + return FALSE; + } + + rc = mbedtls_cipher_cmac_starts(&ctx, key, 128); + if (rc != 0) { + SMP_TRACE_ERROR("mbedtls_cipher_cmac_starts failed: %d", rc); + mbedtls_cipher_free(&ctx); + return FALSE; + } + + if (length > 0 && input != NULL) { + rc = mbedtls_cipher_cmac_update(&ctx, input, length); + if (rc != 0) { + SMP_TRACE_ERROR("mbedtls_cipher_cmac_update failed: %d", rc); + mbedtls_cipher_free(&ctx); + return FALSE; + } + } + + UINT8 mac[BT_OCTET16_LEN]; + rc = mbedtls_cipher_cmac_finish(&ctx, mac); + mbedtls_cipher_free(&ctx); + + if (rc != 0) { + SMP_TRACE_ERROR("mbedtls_cipher_cmac_finish failed: %d", rc); + /* Clear sensitive data from stack */ + memset(mac, 0, sizeof(mac)); + return FALSE; + } + + /* Truncate to tlen bytes */ + for (UINT16 i = 0; i < tlen && i < BT_OCTET16_LEN; i++) { + p_signature[i] = mac[i]; + } + + /* Clear sensitive data from stack */ + memset(mac, 0, sizeof(mac)); + + ret = TRUE; } - len = n * BT_OCTET16_LEN; +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) + { + /* + * TinyCrypt CMAC implementation. + * Bluedroid uses little-endian, TinyCrypt uses big-endian. + * We reverse the key and input, then reverse the output. + */ + struct tc_aes_key_sched_struct sched; + struct tc_cmac_struct state; + UINT8 key_be[BT_OCTET16_LEN]; + UINT8 *input_be = NULL; + UINT8 mac_be[BT_OCTET16_LEN]; - SMP_TRACE_DEBUG("AES128_CMAC started, allocate buffer size = %d", len); - /* allocate a memory space of multiple of 16 bytes to hold text */ - if ((cmac_cb.text = (UINT8 *)osi_malloc(len)) != NULL) { - cmac_cb.round = n; + SMP_TRACE_DEBUG("AES128_CMAC (TinyCrypt) started, length = %d", length); - memset(cmac_cb.text, 0, len); - diff = len - length; + /* Convert key from little-endian to big-endian */ + for (int i = 0; i < BT_OCTET16_LEN; i++) { + key_be[i] = key[BT_OCTET16_LEN - 1 - i]; + } - if (input != NULL && length > 0) { - memcpy(&cmac_cb.text[diff] , input, (int)length); - cmac_cb.len = length; + /* Setup CMAC */ + if (tc_cmac_setup(&state, key_be, &sched) == TC_CRYPTO_FAIL) { + SMP_TRACE_ERROR("tc_cmac_setup failed"); + memset(key_be, 0, sizeof(key_be)); + memset(&sched, 0, sizeof(sched)); + return FALSE; + } + + /* Allocate and convert input from little-endian to big-endian */ + if (length > 0) { + input_be = (UINT8 *)osi_malloc(length); + if (input_be == NULL) { + SMP_TRACE_ERROR("No resources for input_be"); + tc_cmac_erase(&state); + memset(key_be, 0, sizeof(key_be)); + memset(&sched, 0, sizeof(sched)); + return FALSE; + } + for (UINT16 i = 0; i < length; i++) { + input_be[i] = input[length - 1 - i]; + } + + /* Update CMAC with input data */ + if (tc_cmac_update(&state, input_be, length) == TC_CRYPTO_FAIL) { + SMP_TRACE_ERROR("tc_cmac_update failed"); + osi_free(input_be); + tc_cmac_erase(&state); + memset(key_be, 0, sizeof(key_be)); + memset(&sched, 0, sizeof(sched)); + return FALSE; + } + osi_free(input_be); + } + + /* Finalize CMAC */ + if (tc_cmac_final(mac_be, &state) == TC_CRYPTO_FAIL) { + SMP_TRACE_ERROR("tc_cmac_final failed"); + tc_cmac_erase(&state); + memset(key_be, 0, sizeof(key_be)); + memset(&sched, 0, sizeof(sched)); + return FALSE; + } + + /* Convert MAC from big-endian to little-endian and truncate to tlen bytes */ + for (UINT16 i = 0; i < tlen && i < BT_OCTET16_LEN; i++) { + p_signature[i] = mac_be[BT_OCTET16_LEN - 1 - i]; + } + + /* Clear sensitive data from stack */ + tc_cmac_erase(&state); + memset(key_be, 0, sizeof(key_be)); + memset(mac_be, 0, sizeof(mac_be)); + memset(&sched, 0, sizeof(sched)); + + ret = TRUE; + } +#else + { + UINT16 len, diff; + UINT16 n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN; + + if (n == 0) { + n = 1; + } + len = n * BT_OCTET16_LEN; + + SMP_TRACE_DEBUG("AES128_CMAC started, allocate buffer size = %d", len); + /* allocate a memory space of multiple of 16 bytes to hold text */ + if ((cmac_cb.text = (UINT8 *)osi_malloc(len)) != NULL) { + cmac_cb.round = n; + + memset(cmac_cb.text, 0, len); + diff = len - length; + + if (input != NULL && length > 0) { + memcpy(&cmac_cb.text[diff] , input, (int)length); + cmac_cb.len = length; + } else { + cmac_cb.len = 0; + } + + /* prepare calculation for subkey s and last block of data */ + if (cmac_generate_subkey(key)) { + /* start calculation */ + ret = cmac_aes_k_calculate(key, p_signature, tlen); + } + /* clean up */ + cmac_aes_cleanup(); } else { - cmac_cb.len = 0; + ret = FALSE; + SMP_TRACE_ERROR("No resources"); } - - /* prepare calculation for subkey s and last block of data */ - if (cmac_generate_subkey(key)) { - /* start calculation */ - ret = cmac_aes_k_calculate(key, p_signature, tlen); - } - /* clean up */ - cmac_aes_cleanup(); - } else { - ret = FALSE; - SMP_TRACE_ERROR("No resources"); } +#endif /* SMP_CRYPTO_MBEDTLS */ return ret; } diff --git a/components/bt/host/bluedroid/stack/smp/smp_keys.c b/components/bt/host/bluedroid/stack/smp/smp_keys.c index 24ef814279..f96751c72a 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_keys.c +++ b/components/bt/host/bluedroid/stack/smp/smp_keys.c @@ -34,8 +34,29 @@ #include "btm_int.h" #include "btm_ble_int.h" #include "stack/hcimsgs.h" +#if (SMP_CRYPTO_MBEDTLS == TRUE) +#include "mbedtls/aes.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" +#include "esp_random.h" + +/* Random number generator function for mbedTLS ECP operations */ +static int smp_mbedtls_rng(void *ctx, unsigned char *output, size_t len) +{ + (void)ctx; /* Unused parameter */ + esp_fill_random(output, len); + return 0; +} +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) +#include "tinycrypt/aes.h" +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/ecc_dh.h" +#include "tinycrypt/ecc.h" +#include "tinycrypt/constants.h" +#else #include "aes.h" #include "p_256_ecc_pp.h" +#endif /* SMP_CRYPTO_MBEDTLS */ #include "device/controller.h" #ifndef SMP_MAX_ENC_REPEAT @@ -159,12 +180,11 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len, UINT8 *plain_text, UINT8 pt_len, tSMP_ENC *p_out) { - aes_context ctx; UINT8 *p_start = NULL; UINT8 *p = NULL; - UINT8 *p_rev_data = NULL; /* input data in big endilan format */ - UINT8 *p_rev_key = NULL; /* input key in big endilan format */ - UINT8 *p_rev_output = NULL; /* encrypted output in big endilan format */ + UINT8 *p_rev_data = NULL; /* input data in big endian format */ + UINT8 *p_rev_key = NULL; /* input key in big endian format */ + UINT8 *p_rev_output = NULL; /* encrypted output in big endian format */ SMP_TRACE_DEBUG ("%s\n", __func__); if ( (p_out == NULL ) || (key_len != SMP_ENCRYT_KEY_SIZE) ) { @@ -194,8 +214,64 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len, smp_debug_print_nbyte_little_endian(p_start, (const UINT8 *)"Plain text", SMP_ENCRYT_DATA_SIZE); #endif p_rev_output = p; - aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx); - bluedroid_aes_encrypt(p_rev_data, p, &ctx); /* outputs in byte 48 to byte 63 */ + +#if (SMP_CRYPTO_MBEDTLS == TRUE) + { + mbedtls_aes_context ctx = {0}; + int rc; + + mbedtls_aes_init(&ctx); + + rc = mbedtls_aes_setkey_enc(&ctx, p_rev_key, 128); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_aes_setkey_enc failed: %d\n", __func__, rc); + mbedtls_aes_free(&ctx); + /* Clear sensitive data before freeing */ + memset(p_start, 0, SMP_ENCRYT_DATA_SIZE * 4); + osi_free(p_start); + return FALSE; + } + + rc = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, p_rev_data, p_rev_output); + mbedtls_aes_free(&ctx); + + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_aes_crypt_ecb failed: %d\n", __func__, rc); + /* Clear sensitive data before freeing */ + memset(p_start, 0, SMP_ENCRYT_DATA_SIZE * 4); + osi_free(p_start); + return FALSE; + } + } +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) + { + struct tc_aes_key_sched_struct sched; + + /* TinyCrypt expects big-endian key and data */ + if (tc_aes128_set_encrypt_key(&sched, p_rev_key) == TC_CRYPTO_FAIL) { + SMP_TRACE_ERROR("%s tc_aes128_set_encrypt_key failed\n", __func__); + memset(&sched, 0, sizeof(sched)); + osi_free(p_start); + return FALSE; + } + + if (tc_aes_encrypt(p_rev_output, p_rev_data, &sched) == TC_CRYPTO_FAIL) { + SMP_TRACE_ERROR("%s tc_aes_encrypt failed\n", __func__); + memset(&sched, 0, sizeof(sched)); + osi_free(p_start); + return FALSE; + } + + /* Clear sensitive data from key schedule */ + memset(&sched, 0, sizeof(sched)); + } +#else + { + aes_context ctx; + aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx); + bluedroid_aes_encrypt(p_rev_data, p_rev_output, &ctx); /* outputs in byte 48 to byte 63 */ + } +#endif /* SMP_CRYPTO_MBEDTLS */ p = p_out->param_buf; REVERSE_ARRAY_TO_STREAM (p, p_rev_output, SMP_ENCRYT_DATA_SIZE); @@ -207,6 +283,8 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len, p_out->status = HCI_SUCCESS; p_out->opcode = HCI_BLE_ENCRYPT; + /* Clear sensitive data (including key at byte 32-47) before freeing */ + memset(p_start, 0, SMP_ENCRYT_DATA_SIZE * 4); osi_free(p_start); return TRUE; @@ -332,7 +410,7 @@ void smp_generate_stk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) output.opcode = HCI_BLE_ENCRYPT; memcpy(output.param_buf, p_cb->ltk, SMP_ENCRYT_DATA_SIZE); } else if (!smp_calculate_legacy_short_term_key(p_cb, &output)) { - SMP_TRACE_ERROR("%s failed", __func__); + SMP_TRACE_ERROR("%s pairing failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); return; } @@ -459,7 +537,7 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT16_TO_STREAM(p, r); if (!SMP_Encrypt(er, BT_OCTET16_LEN, buffer, 4, &output)) { - SMP_TRACE_ERROR("smp_generate_csrk failed\n"); + SMP_TRACE_ERROR("%s pairing failed", __func__); if (p_cb->smp_over_br) { #if (CLASSIC_BT_INCLUDED == TRUE) smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status); @@ -664,7 +742,7 @@ void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda) /* calculate e(k, r XOR p1), where k = TK */ if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p1, BT_OCTET16_LEN, &output)) { - SMP_TRACE_ERROR("smp_generate_csrk failed"); + SMP_TRACE_ERROR("%s calculate TK failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { smp_calculate_comfirm_cont(p_cb, &output); @@ -701,7 +779,7 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p) /* calculate: Confirm = E(k, p1' XOR p2) */ if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p2, BT_OCTET16_LEN, &output)) { - SMP_TRACE_ERROR("smp_calculate_comfirm_cont failed\n"); + SMP_TRACE_ERROR("%s pairing failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { SMP_TRACE_DEBUG("p_cb->rand_enc_proc_state=%d\n", p_cb->rand_enc_proc_state); @@ -861,7 +939,7 @@ static void smp_generate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) /* LTK = d1(ER, DIV, 0)= e(ER, DIV)*/ if (!SMP_Encrypt(er, BT_OCTET16_LEN, (UINT8 *)&p_cb->div, sizeof(UINT16), &output)) { - SMP_TRACE_ERROR("%s failed\n", __func__); + SMP_TRACE_ERROR("%s failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { /* mask the LTK */ @@ -1118,8 +1196,6 @@ void smp_continue_private_key_creation (tSMP_CB *p_cb, tBTM_RAND_ENC *p) *******************************************************************************/ void smp_process_private_key(tSMP_CB *p_cb) { - Point public_key; - BT_OCTET32 private_key; tSMP_LOC_OOB_DATA *p_loc_oob = &p_cb->sc_oob_data.loc_oob_data; SMP_TRACE_DEBUG ("%s", __FUNCTION__); @@ -1131,10 +1207,101 @@ void smp_process_private_key(tSMP_CB *p_cb) memcpy(p_cb->loc_publ_key.y, p_loc_oob->publ_key_used.y, BT_OCTET32_LEN); memcpy(p_cb->local_random, p_loc_oob->randomizer, BT_OCTET16_LEN); } else { +#if (SMP_CRYPTO_MBEDTLS == TRUE) + mbedtls_ecp_keypair keypair = {0}; + int rc; + size_t olen; + + mbedtls_ecp_keypair_init(&keypair); + + /* Load the group */ + rc = mbedtls_ecp_group_load(&keypair.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_ecp_group_load failed: %d\n", __FUNCTION__, rc); + goto mbedtls_pubkey_cleanup; + } + + /* Import private key (little-endian) */ + rc = mbedtls_mpi_read_binary(&keypair.MBEDTLS_PRIVATE(d), p_cb->private_key, BT_OCTET32_LEN); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_mpi_read_binary failed: %d\n", __FUNCTION__, rc); + goto mbedtls_pubkey_cleanup; + } + + /* Validate private key */ + rc = mbedtls_ecp_check_privkey(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(d)); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_ecp_check_privkey failed: %d\n", __FUNCTION__, rc); + goto mbedtls_pubkey_cleanup; + } + + /* Compute public key from private key */ + /* mbedtls_ecp_keypair_calc_public requires a non-NULL RNG function for side-channel protection */ + rc = mbedtls_ecp_keypair_calc_public(&keypair, smp_mbedtls_rng, NULL); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_ecp_keypair_calc_public failed: %d\n", __FUNCTION__, rc); + goto mbedtls_pubkey_cleanup; + } + + /* Export public key in uncompressed format: 0x04 || X || Y */ + UINT8 pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; + rc = mbedtls_ecp_point_write_binary(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, pub_be, sizeof(pub_be)); + if (rc != 0 || olen != sizeof(pub_be)) { + SMP_TRACE_ERROR("%s mbedtls_ecp_point_write_binary failed: %d\n", __FUNCTION__, rc); + goto mbedtls_pubkey_cleanup; + } + + /* Convert X and Y from big-endian to little-endian */ + /* pub_be: 0x04 || X (32 bytes) || Y (32 bytes) */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + p_cb->loc_publ_key.x[i] = pub_be[1 + BT_OCTET32_LEN - 1 - i]; + p_cb->loc_publ_key.y[i] = pub_be[33 + BT_OCTET32_LEN - 1 - i]; + } + +mbedtls_pubkey_cleanup: + /* Clear sensitive data - mbedtls_ecp_keypair_free will zero the private key */ + mbedtls_ecp_keypair_free(&keypair); + /* Note: pub_be contains public key data, no need to clear */ +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) + { + UINT8 pub_key[64]; /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */ + UINT8 priv_be[BT_OCTET32_LEN]; + + /* Convert private key from little-endian to big-endian */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + priv_be[i] = p_cb->private_key[BT_OCTET32_LEN - 1 - i]; + } + + /* Compute public key from private key */ + /* uECC_compute_public_key returns 1 if successful, 0 if failed */ + if (uECC_compute_public_key(priv_be, pub_key, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { + SMP_TRACE_ERROR("%s uECC_compute_public_key failed\n", __FUNCTION__); + memset(priv_be, 0, sizeof(priv_be)); + memset(pub_key, 0, sizeof(pub_key)); + return; + } + + /* Convert X and Y from big-endian to little-endian */ + /* TinyCrypt format: X (32 bytes) || Y (32 bytes) */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + p_cb->loc_publ_key.x[i] = pub_key[BT_OCTET32_LEN - 1 - i]; + p_cb->loc_publ_key.y[i] = pub_key[BT_OCTET32_LEN + BT_OCTET32_LEN - 1 - i]; + } + + /* Clear sensitive data from stack */ + memset(priv_be, 0, sizeof(priv_be)); + memset(pub_key, 0, sizeof(pub_key)); + } +#else + Point public_key; + BT_OCTET32 private_key; + memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN); ECC_PointMult(&public_key, &(curve_p256.G), (DWORD *) private_key, KEY_LENGTH_DWORDS_P256); memcpy(p_cb->loc_publ_key.x, public_key.x, BT_OCTET32_LEN); memcpy(p_cb->loc_publ_key.y, public_key.y, BT_OCTET32_LEN); +#endif /* SMP_CRYPTO_MBEDTLS */ } smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private", @@ -1161,11 +1328,137 @@ void smp_process_private_key(tSMP_CB *p_cb) *******************************************************************************/ void smp_compute_dhkey (tSMP_CB *p_cb) { + SMP_TRACE_DEBUG ("%s\n", __FUNCTION__); + +#if (SMP_CRYPTO_MBEDTLS == TRUE) + mbedtls_ecp_group grp = {0}; + mbedtls_ecp_point Q = {0}; + mbedtls_mpi d = {0}; + mbedtls_mpi z = {0}; + int rc; + UINT8 peer_pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */ + + mbedtls_ecp_group_init(&grp); + mbedtls_ecp_point_init(&Q); + mbedtls_mpi_init(&d); + mbedtls_mpi_init(&z); + + /* Load the group */ + rc = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_ecp_group_load failed: %d\n", __FUNCTION__, rc); + goto mbedtls_dhkey_cleanup; + } + + /* Import private key (little-endian) */ + rc = mbedtls_mpi_read_binary(&d, p_cb->private_key, BT_OCTET32_LEN); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_mpi_read_binary failed: %d\n", __FUNCTION__, rc); + goto mbedtls_dhkey_cleanup; + } + + /* Construct peer public key in uncompressed format: 0x04 || X || Y */ + peer_pub_be[0] = 0x04; + for (int i = 0; i < BT_OCTET32_LEN; i++) { + peer_pub_be[1 + i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i]; + peer_pub_be[33 + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i]; + } + + /* Read peer public key */ + rc = mbedtls_ecp_point_read_binary(&grp, &Q, peer_pub_be, sizeof(peer_pub_be)); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_ecp_point_read_binary failed: %d\n", __FUNCTION__, rc); + goto mbedtls_dhkey_cleanup; + } + + /* Validate peer public key */ + rc = mbedtls_ecp_check_pubkey(&grp, &Q); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_ecp_check_pubkey failed: %d\n", __FUNCTION__, rc); + goto mbedtls_dhkey_cleanup; + } + + /* Compute ECDH shared secret */ + /* mbedtls_ecdh_compute_shared requires a non-NULL RNG function for side-channel protection */ + rc = mbedtls_ecdh_compute_shared(&grp, &z, &Q, &d, smp_mbedtls_rng, NULL); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_ecdh_compute_shared failed: %d\n", __FUNCTION__, rc); + goto mbedtls_dhkey_cleanup; + } + + /* Export shared secret (big-endian) and convert to little-endian for DHKey */ + UINT8 shared_secret[BT_OCTET32_LEN]; + rc = mbedtls_mpi_write_binary(&z, shared_secret, BT_OCTET32_LEN); + if (rc != 0) { + SMP_TRACE_ERROR("%s mbedtls_mpi_write_binary failed: %d\n", __FUNCTION__, rc); + goto mbedtls_dhkey_cleanup; + } + + /* Convert shared secret from big-endian to little-endian for DHKey */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + p_cb->dhkey[i] = shared_secret[BT_OCTET32_LEN - 1 - i]; + } + +mbedtls_dhkey_cleanup: + /* Clear sensitive data - mbedtls_mpi_free will zero the memory */ + mbedtls_mpi_free(&z); + mbedtls_mpi_free(&d); + mbedtls_ecp_point_free(&Q); + mbedtls_ecp_group_free(&grp); + /* Clear sensitive data from stack */ + memset(shared_secret, 0, sizeof(shared_secret)); + /* Note: peer_pub_be contains public key data, no need to clear */ +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) + { + UINT8 priv_be[BT_OCTET32_LEN]; + UINT8 peer_pub_be[64]; /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */ + UINT8 shared_secret[BT_OCTET32_LEN]; + + /* Convert private key from little-endian to big-endian */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + priv_be[i] = p_cb->private_key[BT_OCTET32_LEN - 1 - i]; + } + + /* Convert peer public key from little-endian to big-endian */ + /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + peer_pub_be[i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i]; + peer_pub_be[BT_OCTET32_LEN + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i]; + } + + /* Validate peer public key */ + /* uECC_valid_public_key returns 0 if valid, negative value if invalid */ + if (uECC_valid_public_key(peer_pub_be, uECC_secp256r1()) < 0) { + SMP_TRACE_ERROR("%s Invalid peer public key\n", __FUNCTION__); + memset(priv_be, 0, sizeof(priv_be)); + memset(peer_pub_be, 0, sizeof(peer_pub_be)); + return; + } + + /* Compute ECDH shared secret */ + /* uECC_shared_secret returns TC_CRYPTO_SUCCESS (1) if successful, TC_CRYPTO_FAIL (0) if failed */ + if (uECC_shared_secret(peer_pub_be, priv_be, shared_secret, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { + SMP_TRACE_ERROR("%s uECC_shared_secret failed\n", __FUNCTION__); + memset(priv_be, 0, sizeof(priv_be)); + memset(peer_pub_be, 0, sizeof(peer_pub_be)); + memset(shared_secret, 0, sizeof(shared_secret)); + return; + } + + /* Convert shared secret from big-endian to little-endian for DHKey */ + for (int i = 0; i < BT_OCTET32_LEN; i++) { + p_cb->dhkey[i] = shared_secret[BT_OCTET32_LEN - 1 - i]; + } + + /* Clear sensitive data from stack */ + memset(priv_be, 0, sizeof(priv_be)); + memset(peer_pub_be, 0, sizeof(peer_pub_be)); + memset(shared_secret, 0, sizeof(shared_secret)); + } +#else Point peer_publ_key, new_publ_key; BT_OCTET32 private_key; - SMP_TRACE_DEBUG ("%s\n", __FUNCTION__); - memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN); memcpy(peer_publ_key.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN); memcpy(peer_publ_key.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN); @@ -1173,8 +1466,9 @@ void smp_compute_dhkey (tSMP_CB *p_cb) ECC_PointMult(&new_publ_key, &peer_publ_key, (DWORD *) private_key, KEY_LENGTH_DWORDS_P256); memcpy(p_cb->dhkey, new_publ_key.x, BT_OCTET32_LEN); +#endif /* SMP_CRYPTO_MBEDTLS */ - smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Old DHKey", + smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"DHKey", BT_OCTET32_LEN); smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private", @@ -1183,8 +1477,6 @@ void smp_compute_dhkey (tSMP_CB *p_cb) BT_OCTET32_LEN); smp_debug_print_nbyte_little_endian (p_cb->peer_publ_key.y, (const UINT8 *)"rem public(y)", BT_OCTET32_LEN); - smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Reverted DHKey", - BT_OCTET32_LEN); } /******************************************************************************* @@ -1373,6 +1665,8 @@ void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb, } if (p_cb->number_to_display >= (BTM_MAX_PASSKEY_VAL + 1)) { + SMP_TRACE_ERROR("%s pairing failed - invalid number to display %u", + __func__, p_cb->number_to_display); UINT8 reason; reason = p_cb->failure = SMP_PAIR_FAIL_UNKNOWN; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); diff --git a/components/bt/host/bluedroid/stack/smp/smp_utils.c b/components/bt/host/bluedroid/stack/smp/smp_utils.c index 8ec4d548ac..f4d0987029 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_utils.c +++ b/components/bt/host/bluedroid/stack/smp/smp_utils.c @@ -366,6 +366,7 @@ BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb) } if (!sent) { + SMP_TRACE_ERROR("%s failed, cmd_code=0x%02x", __func__, cmd_code); if (p_cb->smp_over_br) { #if (CLASSIC_BT_INCLUDED == TRUE) smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure); @@ -392,7 +393,7 @@ void smp_rsp_timeout(TIMER_LIST_ENT *p_tle) UINT8 failure = SMP_RSP_TIMEOUT; UNUSED(p_tle); - SMP_TRACE_EVENT("%s state:%d br_state:%d", __FUNCTION__, p_cb->state, p_cb->br_state); + SMP_TRACE_ERROR("%s state=%d br_state=%d", __func__, p_cb->state, p_cb->br_state); if (p_cb->smp_over_br) { #if (CLASSIC_BT_INCLUDED == TRUE) diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index cc3b71a8f8..dc82f62561 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -80,28 +80,28 @@ menu "Roles and Profiles" depends on BT_NIMBLE_ENABLED default y help - Enables central role + Enables BLE Central role config BT_NIMBLE_ROLE_PERIPHERAL bool "Enable BLE Peripheral role" depends on BT_NIMBLE_ENABLED default y help - Enable peripheral role + Enable BLE Peripheral role config BT_NIMBLE_ROLE_BROADCASTER bool "Enable BLE Broadcaster role" depends on BT_NIMBLE_ENABLED default y help - Enables broadcaster role + Enables BLE broadcaster role config BT_NIMBLE_ROLE_OBSERVER bool "Enable BLE Observer role" depends on BT_NIMBLE_ENABLED default y help - Enables observer role + Enables BLE Observer role config BT_NIMBLE_GATT_CLIENT bool "Enable BLE GATT Client support" @@ -127,57 +127,84 @@ menu "Security (SMP)" help Enable BLE sm feature - config BT_NIMBLE_SM_LEGACY - bool "Security manager legacy pairing" - depends on BT_NIMBLE_SECURITY_ENABLE - default y - help - Enable security manager legacy pairing + if BT_NIMBLE_SECURITY_ENABLE + config BT_NIMBLE_SM_LEGACY + bool "Security manager legacy pairing" + default y + help + Enable security manager legacy pairing - config BT_NIMBLE_SM_SC - bool "Security manager secure connections (4.2)" - depends on BT_NIMBLE_SECURITY_ENABLE - default y - help - Enable security manager secure connections + config BT_NIMBLE_SM_SC + bool "Security manager secure connections (4.2)" + default y + help + Enable security manager secure connections - config BT_NIMBLE_SM_SC_DEBUG_KEYS - bool "Use predefined public-private key pair" - default n - depends on BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_SM_SC - help - If this option is enabled, SM uses predefined DH key pair as described - in Core Specification, Vol. 3, Part H, 2.3.5.6.1. This allows to - decrypt air traffic easily and thus should only be used for debugging. + config BT_NIMBLE_SM_SC_DEBUG_KEYS + bool "Use predefined public-private key pair" + default n + depends on BT_NIMBLE_SM_SC + help + If this option is enabled, SM uses predefined DH key pair as described + in Core Specification, Vol. 3, Part H, 2.3.5.6.1. This allows to + decrypt air traffic easily and thus should only be used for debugging. - config BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION - bool "Enable LE encryption" - depends on BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_ENABLED - default y - help - Enable encryption connection + config BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION + bool "Enable LE encryption" + default y + help + Enable encryption connection - config BT_NIMBLE_SM_LVL - int "Security level" - depends on BT_NIMBLE_SECURITY_ENABLE - default 0 - help - LE Security Mode 1 Levels: - 1. No Security - 2. Unauthenticated pairing with encryption - 3. Authenticated pairing with encryption - 4. Authenticated LE Secure Connections pairing with encryption using a 128-bit strength encryption key. + config BT_NIMBLE_SM_LVL + int "Security level" + default 0 + help + LE Security Mode 1 Levels: + 1. No Security + 2. Unauthenticated pairing with encryption + 3. Authenticated pairing with encryption + 4. Authenticated LE Secure Connections pairing with encryption using a 128-bit strength encryption key. - config BT_NIMBLE_SM_SC_ONLY - int "Enable Secure Connections Only Mode" - depends on BT_NIMBLE_SECURITY_ENABLE - default 0 - help - Enable Secure Connections Only Mode + config BT_NIMBLE_SM_SC_ONLY + int "Enable Secure Connections Only Mode" + default 0 + help + Enable Secure Connections Only Mode + config BT_NIMBLE_SMP_ID_RESET + bool "Reset device identity when all bonding records are deleted" + default n + help + There are tracking risks associated with using a fixed or static IRK. + If enabled this option, NimBLE will assign a new randomly-generated IRK + when all pairing and bonding records are deleted. This would decrease the ability + of a previously paired peer to be used to determine whether a device + with which it previously shared an IRK is within range. + + config BT_NIMBLE_NVS_PERSIST + bool "Persist the BLE Bonding keys in NVS" + default n + help + Enable this flag to make bonding persistent across device reboots + + config BT_NIMBLE_MAX_BONDS + int "Maximum number of bonds to save across reboots" + default 3 + help + Defines maximum number of bonds to save for peer security and our security + + config BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION + bool "Enable stack handling of repeat pairing" + default n + help + Use this option to let stack internally handle the request for repeat pairing. + Enabling this option will delete the pairing of the device and stack will NOT post any event + to application. If this option is disabled, application will get BLE_GAP_EVENT_REPEAT_PAIRING + event. + endif endmenu #SMP -menu "GAP / GATT / Device Settings" +menu "GAP" config BT_NIMBLE_RPA_TIMEOUT int "RPA timeout in seconds" range 1 41400 @@ -193,15 +220,15 @@ menu "GAP / GATT / Device Settings" range 1 15 default 12 help - BLE list size + BLE Whitelist size config BT_NIMBLE_ENABLE_CONN_REATTEMPT bool "Enable connection reattempts on connection establishment error" default y if (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || SOC_ESP_NIMBLE_CONTROLLER) default n if IDF_TARGET_ESP32 help - Enable to make the NimBLE host to reattempt GAP connection on connection - establishment failure. + Enable to make the NimBLE host to reattempt GAP connection attempt in case of + connection establishment failure due to reason 0x3E. config BT_NIMBLE_MAX_CONN_REATTEMPT int "Maximum number connection reattempts" @@ -211,23 +238,23 @@ menu "GAP / GATT / Device Settings" help Defines maximum number of connection reattempts. - config BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION - bool "Enable stack handling of repeat pairing" - default n + config BT_NIMBLE_HS_PVCY + bool "Enable privacy related APIs" + default y depends on BT_NIMBLE_ENABLED help - Use this option to let stack internally handle the request for repeat pairing. - Enabling this option will delete the pairing of the device and stack will NOT post any event - to application. If this option is disabled, application will get BLE_GAP_EVENT_REPEAT_PAIRING - event. + Enable this option to include host-side APIs related to BLE privacy. + Disable it if your application does not require privacy features (such as + RPA generation, resolving, or privacy-based pairing). Disabling this option + excludes privacy-related code from the host to reduce memory usage. config BT_NIMBLE_HOST_BASED_PRIVACY bool "Enable host based privacy for random address." default n - depends on BT_NIMBLE_ENABLED && IDF_TARGET_ESP32 + depends on BT_NIMBLE_ENABLED && BT_NIMBLE_HS_PVCY && IDF_TARGET_ESP32 help Use this option to do host based Random Private Address resolution. - If this option is disabled then controller based privacy is used. + This option is valid only for ESP32 config BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN bool "Allow Connections with scanning in progress" @@ -246,6 +273,7 @@ menu "GAP / GATT / Device Settings" config BT_NIMBLE_MAX_CONNECTIONS int "Maximum number of concurrent connections" + depends on BT_NIMBLE_ROLE_CENTRAL || BT_NIMBLE_ROLE_PERIPHERAL range 1 2 if IDF_TARGET_ESP32C2 range 1 70 if SOC_ESP_NIMBLE_CONTROLLER range 1 9 @@ -259,60 +287,13 @@ menu "GAP / GATT / Device Settings" configure BT_CTRL_BLE_MAX_ACT from controller menu. For ESP32C2, ESP32C6 and ESP32H2, each connection will take about 1k DRAM. - config BT_NIMBLE_MAX_BONDS - int "Maximum number of bonds to save across reboots" - default 3 - depends on BT_NIMBLE_ENABLED - help - Defines maximum number of bonds to save for peer security and our security - config BT_NIMBLE_MAX_CCCDS int "Maximum number of CCC descriptors to save across reboots" default 8 - depends on BT_NIMBLE_ENABLED + depends on BT_NIMBLE_ENABLED && BT_NIMBLE_NVS_PERSIST help Defines maximum number of CCC descriptors to save - - config BT_NIMBLE_NVS_PERSIST - bool "Persist the BLE Bonding keys in NVS" - depends on BT_NIMBLE_ENABLED - default n - help - Enable this flag to make bonding persistent across device reboots - - config BT_NIMBLE_SMP_ID_RESET - bool "Reset device identity when all bonding records are deleted" - default n - help - There are tracking risks associated with using a fixed or static IRK. - If enabled this option, NimBLE will assign a new randomly-generated IRK - when all pairing and bonding records are deleted. This would decrease the ability - of a previously paired peer to be used to determine whether a device - with which it previously shared an IRK is within range. - - config BT_NIMBLE_ATT_PREFERRED_MTU - int "Preferred MTU size in octets" - depends on BT_NIMBLE_ENABLED - default 256 - help - This is the default value of ATT MTU indicated by the device during an ATT MTU exchange. - This value can be changed using API ble_att_set_preferred_mtu() - - config BT_NIMBLE_ATT_MAX_PREP_ENTRIES - int "Max Prepare write entries" - depends on BT_NIMBLE_ENABLED - default 64 - help - This is the default value of ATT Maximum prepare entries - - config BT_NIMBLE_GATT_MAX_PROCS - int "Maximum number of GATT client procedures" - depends on BT_NIMBLE_ENABLED - default 4 - help - Maximum number of GATT client procedures that can be executed. - config BT_NIMBLE_CRYPTO_STACK_MBEDTLS bool "Override TinyCrypt with mbedTLS for crypto computations" default y @@ -329,19 +310,12 @@ menu "GAP / GATT / Device Settings" help BLE Host stop procedure timeout in milliseconds. - config BT_NIMBLE_USE_ESP_TIMER bool "Enable Esp Timer for Nimble" default y help Set this option to use Esp Timer which has higher priority timer instead of FreeRTOS timer - config BT_NIMBLE_BLE_GATT_BLOB_TRANSFER - bool "Blob transfer" - help - This option is used when data to be sent is more than 512 bytes. For peripheral role, - BT_NIMBLE_MSYS_1_BLOCK_COUNT needs to be increased according to the need. - config BT_NIMBLE_HS_FLOW_CTRL bool "Enable Host Flow control" depends on BT_NIMBLE_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER @@ -376,6 +350,113 @@ menu "GAP / GATT / Device Settings" endmenu #GAP +menu "GATT / ATT" + config BT_NIMBLE_ATT_PREFERRED_MTU + int "Preferred MTU size in octets" + depends on BT_NIMBLE_GATT_CLIENT || BT_NIMBLE_GATT_SERVER + default 256 + help + This is the default value of ATT MTU indicated by the device during an ATT MTU exchange. + This value can be changed using API ble_att_set_preferred_mtu() + + config BT_NIMBLE_ATT_MAX_PREP_ENTRIES + int "Max Prepare write entries" + depends on BT_NIMBLE_GATT_CLIENT || BT_NIMBLE_GATT_SERVER + default 64 + help + This is the default value of ATT Maximum prepare entries + + config BT_NIMBLE_GATT_MAX_PROCS + int "Maximum number of GATT client procedures" + depends on BT_NIMBLE_GATT_CLIENT || BT_NIMBLE_GATT_SERVER + default 4 + help + Maximum number of GATT client procedures that can be executed. + + config BT_NIMBLE_BLE_GATT_BLOB_TRANSFER + bool "Blob transfer" + depends on BT_NIMBLE_GATT_CLIENT || BT_NIMBLE_GATT_SERVER + help + This option is used when data to be sent is more than 512 bytes. For peripheral role, + BT_NIMBLE_MSYS_1_BLOCK_COUNT needs to be increased according to the need. + + + menuconfig BT_NIMBLE_GATT_CACHING + bool "Enable GATT caching" + depends on BT_NIMBLE_ENABLED + select BT_NIMBLE_DYNAMIC_SERVICE + help + Enable GATT caching + + config BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES + bool "Include services in GATT caching" + depends on BT_NIMBLE_GATT_CACHING + default n + help + Enable this option to include *included services* (e.g., services referenced by other services) + in the GATT database cache. Disabling this will skip caching of included service entries. + + config BT_NIMBLE_INCL_SVC_DISCOVERY + bool + default y if BT_NIMBLE_GATT_CACHING && BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES + default n if BT_NIMBLE_GATT_CACHING && !BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES + default n if !BT_NIMBLE_GATT_CACHING + prompt "Enable Included service discovery" if !BT_NIMBLE_GATT_CACHING + help + Enable this option to start discovery for included service. + + config BT_NIMBLE_GATT_CACHING_MAX_CONNS + int "Maximum connections to be cached" + depends on BT_NIMBLE_GATT_CACHING + default BT_NIMBLE_MAX_CONNECTIONS + help + Set this option to set the upper limit on number of connections to be cached. + + config BT_NIMBLE_GATT_CACHING_MAX_SVCS + int "Maximum number of services per connection" + depends on BT_NIMBLE_GATT_CACHING + default 64 + help + Set this option to set the upper limit on number of services per connection to be cached. + + config BT_NIMBLE_GATT_CACHING_MAX_INCL_SVCS + int "Maximum number of included services per connection" + depends on BT_NIMBLE_GATT_CACHING + default 64 + help + Set this option to set the upper limit on number of included services per connection to be cached. + + config BT_NIMBLE_GATT_CACHING_MAX_CHRS + int "Maximum number of characteristics per connection" + depends on BT_NIMBLE_GATT_CACHING + default 64 + help + Set this option to set the upper limit on number of characteristics per connection to be cached. + + config BT_NIMBLE_GATT_CACHING_MAX_DSCS + int "Maximum number of descriptors per connection" + depends on BT_NIMBLE_GATT_CACHING + default 64 + help + Set this option to set the upper limit on number of descriptors per connection to be cached. + + config BT_NIMBLE_GATT_CACHING_DISABLE_AUTO + bool "Do not start discovery procedure automatically upon receiving Out of Sync" + depends on BT_NIMBLE_GATT_CACHING + default n + help + When client receives ATT out-of-sync error message, it will not automatically start the discovery procedure + to correct the invalid cache. + + config BT_NIMBLE_GATT_CACHING_ASSOC_ENABLE + bool "Enable association-based GATT caching" + depends on BT_NIMBLE_GATT_CACHING + default n + help + Enable this option to use associated address caching instead of performing service discovery. + +endmenu #GATT/ATT + menu "L2CAP" config BT_NIMBLE_L2CAP_COC_MAX_NUM int "Maximum number of connection oriented channels" @@ -388,7 +469,7 @@ menu "L2CAP" config BT_NIMBLE_L2CAP_ENHANCED_COC bool "L2CAP Enhanced Connection Oriented Channel" depends on BT_NIMBLE_ENABLED && (BT_NIMBLE_L2CAP_COC_MAX_NUM >= 1) - default 0 + default n help Enable Enhanced Credit Based Flow Control Mode @@ -416,7 +497,7 @@ menu "Memory Settings" int "MSYS_2 Block Count" default 24 help - Dynamic memory count + Dynamic memory count for block 2 config BT_NIMBLE_MSYS_2_BLOCK_SIZE int "MSYS_2 Block Size" @@ -735,7 +816,7 @@ menu "BLE 6.x Features" depends on BT_NIMBLE_ENABLED && (SOC_BLE_60_SUPPORTED || BT_CONTROLLER_DISABLED) default n help - Enable BLE 6 feature + Enable BLE 6.x feature support if BT_NIMBLE_60_FEATURE_SUPPORT config BT_NIMBLE_CHANNEL_SOUNDING @@ -1123,80 +1204,6 @@ menu "Extra Features" help This enables user to add/remove Gatt services at runtime - menuconfig BT_NIMBLE_GATT_CACHING - bool "Enable GATT caching" - depends on BT_NIMBLE_ENABLED - select BT_NIMBLE_DYNAMIC_SERVICE - help - Enable GATT caching - - config BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES - bool "Include services in GATT caching" - depends on BT_NIMBLE_GATT_CACHING - default n - help - Enable this option to include *included services* (e.g., services referenced by other services) - in the GATT database cache. Disabling this will skip caching of included service entries. - - config BT_NIMBLE_INCL_SVC_DISCOVERY - bool - default y if BT_NIMBLE_GATT_CACHING && BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES - default n if BT_NIMBLE_GATT_CACHING && !BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES - default n if !BT_NIMBLE_GATT_CACHING - prompt "Enable Included service discovery" if !BT_NIMBLE_GATT_CACHING - help - Enable this option to start discovery for included service. - - config BT_NIMBLE_GATT_CACHING_MAX_CONNS - int "Maximum connections to be cached" - depends on BT_NIMBLE_GATT_CACHING - default BT_NIMBLE_MAX_CONNECTIONS - help - Set this option to set the upper limit on number of connections to be cached. - - config BT_NIMBLE_GATT_CACHING_MAX_SVCS - int "Maximum number of services per connection" - depends on BT_NIMBLE_GATT_CACHING - default 64 - help - Set this option to set the upper limit on number of services per connection to be cached. - - config BT_NIMBLE_GATT_CACHING_MAX_INCL_SVCS - int "Maximum number of included services per connection" - depends on BT_NIMBLE_GATT_CACHING - default 64 - help - Set this option to set the upper limit on number of included services per connection to be cached. - - config BT_NIMBLE_GATT_CACHING_MAX_CHRS - int "Maximum number of characteristics per connection" - depends on BT_NIMBLE_GATT_CACHING - default 64 - help - Set this option to set the upper limit on number of characteristics per connection to be cached. - - config BT_NIMBLE_GATT_CACHING_MAX_DSCS - int "Maximum number of descriptors per connection" - depends on BT_NIMBLE_GATT_CACHING - default 64 - help - Set this option to set the upper limit on number of descriptors per connection to be cached. - - config BT_NIMBLE_GATT_CACHING_DISABLE_AUTO - bool "Do not start discovery procedure automatically upon receiving Out of Sync" - depends on BT_NIMBLE_GATT_CACHING - default n - help - When client receives ATT out-of-sync error message, it will not automatically start the discovery procedure - to correct the invalid cache. - - config BT_NIMBLE_GATT_CACHING_ASSOC_ENABLE - bool "Enable association-based GATT caching" - depends on BT_NIMBLE_GATT_CACHING - default n - help - Enable this option to use associated address caching instead of performing service discovery. - config BT_NIMBLE_BLUFI_ENABLE bool "Enable blufi functionality" depends on BT_NIMBLE_ENABLED @@ -1234,7 +1241,6 @@ menu "Extra Features" error suggests insufficient security, then the central will initiate pairing and retry the service request. - config BT_NIMBLE_EATT_CHAN_NUM int "Maximum number of EATT channels" default 0 @@ -1249,7 +1255,64 @@ menu "Extra Features" help Enable connection subrate change feature + config BT_NIMBLE_STATIC_PASSKEY + bool "Enable support for Static Passkey" + default n + depends on BT_NIMBLE_ENABLED && BT_NIMBLE_SECURITY_ENABLE + help + Enable support for user defined static passkey for SMP + config BT_NIMBLE_DTM_MODE_TEST + bool "Enable DTM related test procedure support" + default y + depends on BT_NIMBLE_ENABLED + help + Enable DTM related test procedure support + + config BT_NIMBLE_MEM_OPTIMIZATION + bool "Enable memory optimization" + depends on BT_NIMBLE_ENABLED + default y + help + This option enables memory optimizations in the NimBLE stack. + + config BT_NIMBLE_STATIC_TO_DYNAMIC + bool "Use Dynamic Memory allocations instead of static" + depends on BT_NIMBLE_ENABLED + default y + help + This option enables use of dynamic memory allocation instead of static + allocation for variable global / local variable. This helps in improving + memory footprint + + config BT_NIMBLE_SM_SIGN_CNT + bool "Enable Sign counter operations" + default y + depends on BT_NIMBLE_ENABLED + help + Enable Sign counter operations + + config BT_NIMBLE_CPFD_CAFD + bool "Enable CPFD/CAPD support" + default y + depends on BT_NIMBLE_ENABLED + help + Enable CPFD and CAPD gatt descriptors support + + config BT_NIMBLE_RECONFIG_MTU + bool "Reconfig L2CAP MTU support" + default y + depends on BT_NIMBLE_ENABLED + help + Enable Support to reconfigure L2CAP MTU / MPS + + config BT_NIMBLE_LOW_SPEED_MODE + bool "Reduce DRAM/IRAM usage by moving GATT/GAP/NPL functions to FLASH" + default n + help + Disabling IRAM-optimized paths will place functions in FLASH (.irom.text) + instead of DRAM (.iram.text/.text in internal RAM). Suitable for low-speed + GAP/GATT operations to reduce RAM usage. endmenu menu "NimBLE Mesh" @@ -1469,6 +1532,16 @@ menu "Host-controller Transport" endmenu #Transport menu "Debugging/Testing" + config BT_NIMBLE_MEM_DEBUG + bool "NimBLE memory debug" + depends on BT_NIMBLE_ENABLED && !BT_NIMBLE_ISO + default n + help + Enable NimBLE memory debug to track memory allocations and deallocations. + This feature records the function name, line number, and size of each allocation, + and provides APIs to display memory usage statistics, find memory leaks, and + monitor peak memory usage. + choice BT_NIMBLE_LOG_LEVEL prompt "NimBLE Host log verbosity" depends on BT_NIMBLE_ENABLED @@ -1547,3 +1620,28 @@ menu "Vendor / Optimization" help This enable BLE high duty advertising interval feature endmenu #Vendor + +menu "Helper Utils" + config BT_NIMBLE_CHK_HOST_STATUS + bool "Enable host status query support" + default y + depends on BT_NIMBLE_ENABLED + help + Enable support to query host status + + config BT_NIMBLE_UTIL_API + bool "Enable helper APIs" + default y + depends on BT_NIMBLE_ENABLED + help + Enable support for misc APIs like set data addr change, read local resolv addr + and set host feature + + config BT_NIMBLE_EXTRA_ADV_FIELDS + bool "Enable extra Adv report fields parsing" + default y + depends on BT_NIMBLE_ENABLED + help + Enable support for parsing of more adv fields as per spec + +endmenu diff --git a/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c b/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c index bffd7ee140..6dded0363b 100644 --- a/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c +++ b/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c @@ -35,8 +35,10 @@ static ble_hci_trans_rx_cmd_fn *ble_hci_rx_cmd_hs_cb; static void *ble_hci_rx_cmd_hs_arg; +#if NIMBLE_BLE_CONNECT static ble_hci_trans_rx_acl_fn *ble_hci_rx_acl_hs_cb; static void *ble_hci_rx_acl_hs_arg; +#endif /* * The MBUF payload size must accommodate the HCI data header size plus the @@ -54,8 +56,9 @@ const static char *TAG = "NimBLE"; int os_msys_buf_alloc(void); void os_msys_buf_free(void); +#if !MYNEWT_VAL(BLE_STATIC_TO_DYNAMIC) extern uint8_t ble_hs_enabled_state; - +#endif void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, void *cmd_arg, ble_hci_trans_rx_acl_fn *acl_cb, @@ -63,8 +66,10 @@ void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, { ble_hci_rx_cmd_hs_cb = cmd_cb; ble_hci_rx_cmd_hs_arg = cmd_arg; +#if NIMBLE_BLE_CONNECT ble_hci_rx_acl_hs_cb = acl_cb; ble_hci_rx_acl_hs_arg = acl_arg; +#endif } void esp_vhci_host_send_packet_wrapper(uint8_t *data, uint16_t len) @@ -112,6 +117,7 @@ int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev) return rc; } +#if NIMBLE_BLE_CONNECT int ble_hci_trans_hs_acl_tx(struct os_mbuf *om) { uint16_t len = 0; @@ -141,6 +147,7 @@ int ble_hci_trans_hs_acl_tx(struct os_mbuf *om) return rc; } +#endif int ble_hci_trans_ll_acl_tx(struct os_mbuf *om) { @@ -160,7 +167,7 @@ int ble_hci_trans_reset(void) return 0; } - +#if NIMBLE_BLE_CONNECT static void ble_hci_rx_acl(uint8_t *data, uint16_t len) { struct os_mbuf *m = NULL; @@ -203,6 +210,7 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len) ble_transport_to_hs_acl(m); OS_EXIT_CRITICAL(sr); } +#endif /* * @brief: BT controller callback function, used to notify the upper layer that @@ -255,7 +263,11 @@ static int host_rcv_pkt(uint8_t *data, uint16_t len) bt_record_hci_data(data, len); - if(!ble_hs_enabled_state) { +#if MYNEWT_VAL(BLE_STATIC_TO_DYNAMIC) + if (!ble_hs_get_enabled_state()) { +#else + if (!ble_hs_enabled_state) { +#endif /* If host is not enabled, drop the packet */ esp_rom_printf("Host not enabled. Dropping the packet!"); return 0; @@ -299,7 +311,9 @@ static int host_rcv_pkt(uint8_t *data, uint16_t len) rc = ble_hci_trans_ll_evt_tx(evbuf); assert(rc == 0); } else if (data[0] == BLE_HCI_UART_H4_ACL) { +#if NIMBLE_BLE_CONNECT ble_hci_rx_acl(data + 1, len - 1); +#endif } return 0; } diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index 9551ac31af..112925dfe7 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit 9551ac31af0348d7de6cbe7527de3e5ba205460d +Subproject commit 112925dfe7712ecfe9ccfe37510c7fdcb1fd962a diff --git a/components/bt/host/nimble/port/include/esp_nimble_cfg.h b/components/bt/host/nimble/port/include/esp_nimble_cfg.h index 445c0e2957..8155a2a6d0 100644 --- a/components/bt/host/nimble/port/include/esp_nimble_cfg.h +++ b/components/bt/host/nimble/port/include/esp_nimble_cfg.h @@ -125,10 +125,12 @@ #define BLE_SCAN_RSP_DATA_MAX_LEN_N (MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE) #endif -#ifndef CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS -#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (0) -#else +#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS +#ifdef CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS #define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS) +#else +#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (0) +#endif #endif #ifndef CONFIG_BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST @@ -279,6 +281,7 @@ #else #define MYNEWT_VAL_BLE_CONN_SUBRATING (CONFIG_BT_NIMBLE_SUBRATE) #endif + #ifndef CONFIG_BT_NIMBLE_PERIODIC_ADV_ENH #define MYNEWT_VAL_BLE_PERIODIC_ADV_ENH (0) #else @@ -951,13 +954,31 @@ #endif #if CONFIG_IDF_TARGET_ESP32 + +#define MYNEWT_VAL_BLE_HS_PVCY (1) #define MYNEWT_VAL_BLE_HOST_BASED_PRIVACY (1) + #else + #ifndef MYNEWT_VAL_BLE_HOST_BASED_PRIVACY +#if CONFIG_BT_NIMBLE_HOST_BASED_PRIVACY #define MYNEWT_VAL_BLE_HOST_BASED_PRIVACY (CONFIG_BT_NIMBLE_HOST_BASED_PRIVACY) +#else +#define MYNEWT_VAL_BLE_HOST_BASED_PRIVACY (0) #endif #endif +#ifndef MYNEWT_VAL_BLE_HS_PVCY +#ifdef CONFIG_BT_NIMBLE_HS_PVCY +#define MYNEWT_VAL_BLE_HS_PVCY CONFIG_BT_NIMBLE_HS_PVCY +#else +#define MYNEWT_VAL_BLE_HS_PVCY (0) +#endif +#endif + + +#endif + #ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT #define MYNEWT_VAL_BLE_RPA_TIMEOUT (CONFIG_BT_NIMBLE_RPA_TIMEOUT) #endif @@ -1040,15 +1061,27 @@ #endif #ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS +#ifdef CONFIG_BT_NIMBLE_MAX_BONDS #define MYNEWT_VAL_BLE_STORE_MAX_BONDS CONFIG_BT_NIMBLE_MAX_BONDS +#else +#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (0) +#endif #endif #ifndef MYNEWT_VAL_BLE_STORE_MAX_CCCDS +#ifdef CONFIG_BT_NIMBLE_MAX_CCCDS #define MYNEWT_VAL_BLE_STORE_MAX_CCCDS CONFIG_BT_NIMBLE_MAX_CCCDS +#else +#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (0) +#endif #endif #ifndef MYNEWT_VAL_BLE_STORE_MAX_CSFCS +#ifdef CONFIG_BT_NIMBLE_MAX_BONDS #define MYNEWT_VAL_BLE_STORE_MAX_CSFCS CONFIG_BT_NIMBLE_MAX_BONDS +#else +#define MYNEWT_VAL_BLE_STORE_MAX_CSFCS (0) +#endif #endif #ifdef CONFIG_BT_NIMBLE_MAX_EADS @@ -2186,11 +2219,11 @@ #endif #endif -#ifndef MYNEWT_VAL_BLE_ERR_CHECK -#ifdef CONFIG_BT_NIMBLE_PRINT_ERR_NAME -#define MYNEWT_VAL_BLE_ERR_CHECK CONFIG_BT_NIMBLE_PRINT_ERR_NAME +#ifndef MYNEWT_VAL_BT_NIMBLE_MEM_OPTIMIZATION +#ifdef CONFIG_BT_NIMBLE_MEM_OPTIMIZATION +#define MYNEWT_VAL_BT_NIMBLE_MEM_OPTIMIZATION CONFIG_BT_NIMBLE_MEM_OPTIMIZATION #else -#define MYNEWT_VAL_BLE_ERR_CHECK (0) +#define MYNEWT_VAL_BT_NIMBLE_MEM_OPTIMIZATION (0) #endif #endif @@ -2214,6 +2247,91 @@ #endif #endif +#ifndef MYNEWT_VAL_BLE_DTM_MODE_TEST +#ifdef CONFIG_BT_NIMBLE_DTM_MODE_TEST +#define MYNEWT_VAL_BLE_DTM_MODE_TEST CONFIG_BT_NIMBLE_DTM_MODE_TEST +#else +#define MYNEWT_VAL_BLE_DTM_MODE_TEST (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_HOST_STATUS +#ifdef CONFIG_BT_NIMBLE_CHK_HOST_STATUS +#define MYNEWT_VAL_BLE_HOST_STATUS CONFIG_BT_NIMBLE_CHK_HOST_STATUS +#else +#define MYNEWT_VAL_BLE_HOST_STATUS (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SIGN_CNT +#ifdef CONFIG_BT_NIMBLE_SM_SIGN_CNT +#define MYNEWT_VAL_BLE_SM_SIGN_CNT CONFIG_BT_NIMBLE_SM_SIGN_CNT +#else +#define MYNEWT_VAL_BLE_SM_SIGN_CNT (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_CPFD_CAFD +#ifdef CONFIG_BT_NIMBLE_CPFD_CAFD +#define MYNEWT_VAL_BLE_CPFD_CAFD CONFIG_BT_NIMBLE_CPFD_CAFD +#else +#define MYNEWT_VAL_BLE_CPFD_CAFD (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_RECONFIG_MTU +#ifdef CONFIG_BT_NIMBLE_RECONFIG_MTU +#define MYNEWT_VAL_BLE_RECONFIG_MTU CONFIG_BT_NIMBLE_RECONFIG_MTU +#else +#define MYNEWT_VAL_BLE_RECONFIG_MTU (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_ERR_NAME +#ifdef CONFIG_BT_NIMBLE_PRINT_ERR_NAME +#define MYNEWT_VAL_BLE_ERR_NAME CONFIG_BT_NIMBLE_PRINT_ERR_NAME +#else +#define MYNEWT_VAL_BLE_ERR_NAME (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_UTIL_API +#ifdef CONFIG_BT_NIMBLE_UTIL_API +#define MYNEWT_VAL_BLE_UTIL_API CONFIG_BT_NIMBLE_UTIL_API +#else +#define MYNEWT_VAL_BLE_UTIL_API (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_EXTRA_ADV_FIELDS +#ifdef CONFIG_BT_NIMBLE_EXTRA_ADV_FIELDS +#define MYNEWT_VAL_BLE_EXTRA_ADV_FIELDS CONFIG_BT_NIMBLE_EXTRA_ADV_FIELDS +#else +#define CONFIG_BT_NIMBLE_EXTRA_ADV_FIELDS (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_LOW_SPEED_MODE +#ifdef CONFIG_BT_NIMBLE_LOW_SPEED_MODE +#define MYNEWT_VAL_BLE_LOW_SPEED_MODE CONFIG_BT_NIMBLE_LOW_SPEED_MODE +#else +#define MYNEWT_VAL_BLE_LOW_SPEED_MODE (0) +#endif +#endif + + +#ifndef MYNEWT_VAL_BLE_STATIC_TO_DYNAMIC +#ifdef CONFIG_BT_NIMBLE_STATIC_TO_DYNAMIC +#define MYNEWT_VAL_BLE_STATIC_TO_DYNAMIC CONFIG_BT_NIMBLE_STATIC_TO_DYNAMIC +#else +#define MYNEWT_VAL_BLE_STATIC_TO_DYNAMIC (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_RESTART_PAIR +#define MYNEWT_VAL_BLE_RESTART_PAIR (1) +#endif + #ifndef MYNEWT_VAL_MP_RUNTIME_ALLOC #ifdef CONFIG_BT_NIMBLE_MEMPOOL_RUNTIME_ALLOC #define MYNEWT_VAL_MP_RUNTIME_ALLOC (1) @@ -2230,4 +2348,12 @@ #endif #endif +#ifndef MYNEWT_VAL_STATIC_PASSKEY +#ifdef CONFIG_BT_NIMBLE_STATIC_PASSKEY +#define MYNEWT_VAL_STATIC_PASSKEY CONFIG_BT_NIMBLE_STATIC_PASSKEY +#else +#define CONFIG_BT_NIMBLE_STATIC_PASSKEY (0) +#endif +#endif + #endif diff --git a/components/bt/host/nimble/port/include/esp_nimble_mem.h b/components/bt/host/nimble/port/include/esp_nimble_mem.h index 0b5e5aae74..d0c5a75185 100644 --- a/components/bt/host/nimble/port/include/esp_nimble_mem.h +++ b/components/bt/host/nimble/port/include/esp_nimble_mem.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,10 +16,55 @@ extern "C" { // #pragma message "This file should be replaced with bt_osi_mem.h, used here for compatibility" #include "bt_osi_mem.h" + +#if CONFIG_BT_NIMBLE_MEM_DEBUG + +#define nimble_platform_mem_malloc(size) \ +({ \ + void *p; \ + do { \ + p = bt_osi_mem_malloc(size); \ + nimble_mem_dbg_record(p, size, __func__, __LINE__); \ + } while (0); \ + p; \ +}) + +#define nimble_platform_mem_calloc(count, size) \ +({ \ + void *p; \ + do { \ + p = bt_osi_mem_calloc(count, size); \ + nimble_mem_dbg_record(p, (count) * (size), __func__, __LINE__); \ + } while (0); \ + p; \ +}) + +#define nimble_platform_mem_realloc(ptr, new_size) \ +({ \ + void *p; \ + do { \ + p = nimble_mem_dbg_realloc(ptr, new_size, __func__, __LINE__); \ + } while (0); \ + p; \ +}) + +#define nimble_platform_mem_free(ptr) \ +do { \ + void *tmp_ptr = (void *)(ptr); \ + nimble_mem_dbg_clean(tmp_ptr, __func__, __LINE__); \ + bt_osi_mem_free(tmp_ptr); \ +} while (0) + +#else + #define nimble_platform_mem_malloc bt_osi_mem_malloc #define nimble_platform_mem_calloc bt_osi_mem_calloc +#define nimble_platform_mem_realloc realloc #define nimble_platform_mem_free bt_osi_mem_free +#endif // CONFIG_BT_NIMBLE_MEM_DEBUG + + #ifdef __cplusplus } #endif diff --git a/components/bt/host/nimble/port/src/nvs_port.c b/components/bt/host/nimble/port/src/nvs_port.c index 19d89a063c..02a22afc5b 100644 --- a/components/bt/host/nimble/port/src/nvs_port.c +++ b/components/bt/host/nimble/port/src/nvs_port.c @@ -32,9 +32,11 @@ link_storage_fn(void *storage_cb) struct cache_fn_mapping cache_fn; cache_fn.open = nvs_open_custom; cache_fn.close = nvs_close; + cache_fn.erase_key_item = nvs_erase_key; cache_fn.erase_all = nvs_erase_all; cache_fn.write = nvs_set_blob; cache_fn.read = nvs_get_blob; + cache_fn.commit = nvs_commit; return cache_fn; } #endif diff --git a/components/bt/include/esp32c5/include/esp_bt.h b/components/bt/include/esp32c5/include/esp_bt.h index b44c861e72..478c4df11a 100644 --- a/components/bt/include/esp32c5/include/esp_bt.h +++ b/components/bt/include/esp32c5/include/esp_bt.h @@ -159,7 +159,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type */ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); -#define CONFIG_VERSION 0x20251104 +#define CONFIG_VERSION 0x20251125 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -236,6 +236,7 @@ typedef struct { uint8_t conn_rsv_cnt; /*!< BLE conn state machine reserve count number */ uint8_t priority_level_cfg; /*!< The option for priority level configuration */ uint8_t slv_fst_rx_lat_en; /*!< The option for enabling slave fast PDU reception during latency. */ + uint8_t dl_itvl_phy_sync_en; /*!< The option for automatically initiate the data length update when phy update or connect interval update. */ uint32_t config_magic; /*!< Magic number for configuration validation */ } esp_bt_controller_config_t; @@ -299,6 +300,7 @@ typedef struct { .conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \ .priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \ .slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \ + .dl_itvl_phy_sync_en = DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN, \ .config_magic = CONFIG_MAGIC, \ } diff --git a/components/bt/include/esp32c6/include/esp_bt.h b/components/bt/include/esp32c6/include/esp_bt.h index 3ccdeb7cb7..5771335a99 100644 --- a/components/bt/include/esp32c6/include/esp_bt.h +++ b/components/bt/include/esp32c6/include/esp_bt.h @@ -156,7 +156,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type */ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); -#define CONFIG_VERSION 0x20251104 +#define CONFIG_VERSION 0x20251125 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -236,6 +236,7 @@ typedef struct { uint8_t conn_rsv_cnt; /*!< BLE conn state machine reserve count number */ uint8_t priority_level_cfg; /*!< The option for priority level configuration */ uint8_t slv_fst_rx_lat_en; /*!< The option for enabling slave fast PDU reception during latency. */ + uint8_t dl_itvl_phy_sync_en; /*!< The option for automatically initiate the data length update when phy update or connect interval update. */ uint32_t config_magic; /*!< Magic number for configuration validation */ } esp_bt_controller_config_t; @@ -301,7 +302,8 @@ typedef struct { .adv_rsv_cnt = BLE_LL_ADV_SM_RESERVE_CNT_N, \ .conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \ .priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \ - .slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \ + .slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \ + .dl_itvl_phy_sync_en = DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN, \ .config_magic = CONFIG_MAGIC, \ } #elif CONFIG_IDF_TARGET_ESP32C61 @@ -365,6 +367,7 @@ typedef struct { .conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \ .priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \ .slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \ + .dl_itvl_phy_sync_en = DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN, \ .config_magic = CONFIG_MAGIC, \ } #endif diff --git a/components/bt/include/esp32h2/include/esp_bt.h b/components/bt/include/esp32h2/include/esp_bt.h index a171b52a6b..f3d06ac7c5 100644 --- a/components/bt/include/esp32h2/include/esp_bt.h +++ b/components/bt/include/esp32h2/include/esp_bt.h @@ -161,7 +161,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type */ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); -#define CONFIG_VERSION 0x20251104 +#define CONFIG_VERSION 0x20251125 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -238,6 +238,7 @@ typedef struct { uint8_t conn_rsv_cnt; /*!< BLE conn state machine reserve count number */ uint8_t priority_level_cfg; /*!< The option for priority level configuration */ uint8_t slv_fst_rx_lat_en; /*!< The option for enabling slave fast PDU reception during latency. */ + uint8_t dl_itvl_phy_sync_en; /*!< The option for automatically initiate the data length update when phy update or connect interval update. */ uint32_t config_magic; /*!< Configuration magic value */ } esp_bt_controller_config_t; @@ -302,6 +303,7 @@ typedef struct { .conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \ .priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \ .slv_fst_rx_lat_en = DEFAULT_BT_LE_CTRL_SLV_FAST_RX_CONN_DATA_EN, \ + .dl_itvl_phy_sync_en = DEFAULT_BT_LE_CTRL_DL_ITVL_PHY_SYNC_EN, \ .config_magic = CONFIG_MAGIC, \ } diff --git a/components/bt/porting/include/bt_osi_mem.h b/components/bt/porting/include/bt_osi_mem.h index a97165d707..8a8c448b1d 100644 --- a/components/bt/porting/include/bt_osi_mem.h +++ b/components/bt/porting/include/bt_osi_mem.h @@ -29,3 +29,82 @@ void bt_osi_mem_count_limit_set(uint16_t count_limit); size_t bt_osi_mem_internal_used_size_get(void); size_t bt_osi_mem_used_size_get(void); #endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + +#if CONFIG_BT_NIMBLE_MEM_DEBUG +/** + * @brief Initialize NimBLE memory debug module + */ +void nimble_mem_dbg_init(void); + +/** + * @brief Record memory allocation information + * + * @param p Pointer to allocated memory + * @param size Size of allocation + * @param func Function name where allocation occurred + * @param line Line number where allocation occurred + */ +void nimble_mem_dbg_record(void *p, int size, const char *func, int line); + +/** + * @brief Clean up memory allocation record + * + * @param p Pointer to memory being freed + * @param func Function name where free occurred + * @param line Line number where free occurred + */ +void nimble_mem_dbg_clean(void *p, const char *func, int line); + +/** + * @brief Display all memory debug information + */ +void nimble_mem_dbg_show(void); + +/** + * @brief Get maximum memory size used + * + * @return Maximum memory size in bytes + */ +uint32_t nimble_mem_dbg_get_max_size(void); + +/** + * @brief Get current memory size in use + * + * @return Current memory size in bytes + */ +uint32_t nimble_mem_dbg_get_current_size(void); + +/** + * @brief Start tracking memory usage for a specific section + * + * @param index Section index (0 to NIMBLE_MEM_DBG_MAX_SECTION_NUM-1) + */ +void nimble_mem_dbg_set_section_start(uint8_t index); + +/** + * @brief Stop tracking memory usage for a specific section + * + * @param index Section index (0 to NIMBLE_MEM_DBG_MAX_SECTION_NUM-1) + */ +void nimble_mem_dbg_set_section_end(uint8_t index); + +/** + * @brief Get maximum memory size used in a specific section + * + * @param index Section index (0 to NIMBLE_MEM_DBG_MAX_SECTION_NUM-1) + * @return Maximum memory size in bytes for this section + */ +uint32_t nimble_mem_dbg_get_max_size_section(uint8_t index); + +/** + * @brief Reallocate memory with debug tracking + * + * @param ptr Pointer to memory to reallocate + * @param new_size New size of allocation + * @param func Function name where realloc occurred + * @param line Line number where realloc occurred + * @return Pointer to reallocated memory + */ +void *nimble_mem_dbg_realloc(void *ptr, size_t new_size, const char *func, int line); + +#endif // CONFIG_BT_NIMBLE_MEM_DEBUG diff --git a/components/bt/porting/mem/bt_osi_mem.c b/components/bt/porting/mem/bt_osi_mem.c index 306ec8290e..e020abbf77 100644 --- a/components/bt/porting/mem/bt_osi_mem.c +++ b/components/bt/porting/mem/bt_osi_mem.c @@ -19,7 +19,248 @@ static size_t host_mem_used_size = 0; static uint16_t mem_count_limit = 0; static uint16_t curr_mem_count; #endif // CONFIG_BT_LE_MEM_CHECK_ENABLED -IRAM_ATTR void *bt_osi_mem_malloc(size_t size) + +#if CONFIG_BT_NIMBLE_MEM_DEBUG + +#define NIMBLE_MEM_DBG_INFO_MAX 1024*3 +typedef struct { + void *p; + int size; + const char *func; + int line; +} nimble_mem_dbg_info_t; + +static uint32_t nimble_mem_dbg_count = 0; +static nimble_mem_dbg_info_t nimble_mem_dbg_info[NIMBLE_MEM_DBG_INFO_MAX]; +static uint32_t nimble_mem_dbg_current_size = 0; +static uint32_t nimble_mem_dbg_max_size = 0; + +#define NIMBLE_MEM_DBG_MAX_SECTION_NUM 5 +typedef struct { + bool used; + uint32_t max_size; +} nimble_mem_dbg_max_size_section_t; +static nimble_mem_dbg_max_size_section_t nimble_mem_dbg_max_size_section[NIMBLE_MEM_DBG_MAX_SECTION_NUM]; + +void nimble_mem_dbg_init(void) +{ + int i; + + for (i = 0; i < NIMBLE_MEM_DBG_INFO_MAX; i++) { + nimble_mem_dbg_info[i].p = NULL; + nimble_mem_dbg_info[i].size = 0; + nimble_mem_dbg_info[i].func = NULL; + nimble_mem_dbg_info[i].line = 0; + } + nimble_mem_dbg_count = 0; + nimble_mem_dbg_current_size = 0; + nimble_mem_dbg_max_size = 0; + + for (i = 0; i < NIMBLE_MEM_DBG_MAX_SECTION_NUM; i++){ + nimble_mem_dbg_max_size_section[i].used = false; + nimble_mem_dbg_max_size_section[i].max_size = 0; + } +} + +void nimble_mem_dbg_record(void *p, int size, const char *func, int line) +{ + int i; + + if (!p || size == 0) { + ESP_LOGE("BT_NIMBLE_MEM", "%s invalid !!\n", __func__); + return; + } + + for (i = 0; i < NIMBLE_MEM_DBG_INFO_MAX; i++) { + if (nimble_mem_dbg_info[i].p == NULL) { + nimble_mem_dbg_info[i].p = p; + nimble_mem_dbg_info[i].size = size; + nimble_mem_dbg_info[i].func = func; + nimble_mem_dbg_info[i].line = line; + nimble_mem_dbg_count++; + break; + } + } + + if (i >= NIMBLE_MEM_DBG_INFO_MAX) { + ESP_LOGE("BT_NIMBLE_MEM", "%s full %s %d !!\n", __func__, func, line); + } + + nimble_mem_dbg_current_size += size; + if(nimble_mem_dbg_max_size < nimble_mem_dbg_current_size) { + nimble_mem_dbg_max_size = nimble_mem_dbg_current_size; + } + + for (i = 0; i < NIMBLE_MEM_DBG_MAX_SECTION_NUM; i++){ + if (nimble_mem_dbg_max_size_section[i].used) { + if(nimble_mem_dbg_max_size_section[i].max_size < nimble_mem_dbg_current_size) { + nimble_mem_dbg_max_size_section[i].max_size = nimble_mem_dbg_current_size; + } + } + } +} + +void nimble_mem_dbg_clean(void *p, const char *func, int line) +{ + int i; + + if (!p) { + ESP_LOGE("BT_NIMBLE_MEM", "%s %d free->%p invalid\n", func, line, p); + return; + } + + for (i = 0; i < NIMBLE_MEM_DBG_INFO_MAX; i++) { + if (nimble_mem_dbg_info[i].p == p) { + nimble_mem_dbg_current_size -= nimble_mem_dbg_info[i].size; + nimble_mem_dbg_info[i].p = NULL; + nimble_mem_dbg_info[i].size = 0; + nimble_mem_dbg_info[i].func = NULL; + nimble_mem_dbg_info[i].line = 0; + nimble_mem_dbg_count--; + break; + } + } + + if (i >= NIMBLE_MEM_DBG_INFO_MAX) { + ESP_LOGE("BT_NIMBLE_MEM", "%s full %s %d !!\n", __func__, func, line); + } +} + +void nimble_mem_dbg_show(void) +{ + int i; + + for (i = 0; i < NIMBLE_MEM_DBG_INFO_MAX; i++) { + if (nimble_mem_dbg_info[i].p || nimble_mem_dbg_info[i].size != 0 ) { + ESP_LOGE("BT_NIMBLE_MEM", "--> p %p, s %d, f %s, l %d\n", + nimble_mem_dbg_info[i].p, nimble_mem_dbg_info[i].size, + nimble_mem_dbg_info[i].func, nimble_mem_dbg_info[i].line); + } + } + ESP_LOGE("BT_NIMBLE_MEM", "--> count %ld\n", nimble_mem_dbg_count); + ESP_LOGE("BT_NIMBLE_MEM", "--> size %ldB\n--> max size %ldB\n", + nimble_mem_dbg_current_size, nimble_mem_dbg_max_size); +} + +uint32_t nimble_mem_dbg_get_max_size(void) +{ + return nimble_mem_dbg_max_size; +} + +uint32_t nimble_mem_dbg_get_current_size(void) +{ + return nimble_mem_dbg_current_size; +} + +void nimble_mem_dbg_set_section_start(uint8_t index) +{ + if (index >= NIMBLE_MEM_DBG_MAX_SECTION_NUM) { + ESP_LOGE("BT_NIMBLE_MEM", "Then range of index should be between 0 and %d, current index is %d.\n", + NIMBLE_MEM_DBG_MAX_SECTION_NUM - 1, index); + return; + } + + if (nimble_mem_dbg_max_size_section[index].used) { + ESP_LOGW("BT_NIMBLE_MEM", "This index(%d) has been started, restart it.\n", index); + } + + nimble_mem_dbg_max_size_section[index].used = true; + nimble_mem_dbg_max_size_section[index].max_size = nimble_mem_dbg_current_size; +} + +void nimble_mem_dbg_set_section_end(uint8_t index) +{ + if (index >= NIMBLE_MEM_DBG_MAX_SECTION_NUM) { + ESP_LOGE("BT_NIMBLE_MEM", "Then range of index should be between 0 and %d, current index is %d.\n", + NIMBLE_MEM_DBG_MAX_SECTION_NUM - 1, index); + return; + } + + if (!nimble_mem_dbg_max_size_section[index].used) { + ESP_LOGE("BT_NIMBLE_MEM", "This index(%d) has not been started.\n", index); + return; + } + + nimble_mem_dbg_max_size_section[index].used = false; +} + +uint32_t nimble_mem_dbg_get_max_size_section(uint8_t index) +{ + if (index >= NIMBLE_MEM_DBG_MAX_SECTION_NUM){ + ESP_LOGE("BT_NIMBLE_MEM", "Then range of index should be between 0 and %d, current index is %d.\n", + NIMBLE_MEM_DBG_MAX_SECTION_NUM - 1, index); + return 0; + } + + return nimble_mem_dbg_max_size_section[index].max_size; +} + +void *nimble_mem_dbg_realloc(void *ptr, size_t new_size, const char *func, int line) +{ + size_t old_size = 0; + int i; + + void *new_ptr = realloc(ptr, new_size); + if (new_ptr == NULL && new_size > 0) { + // realloc failed, keep old ptr record + return NULL; + } + + // Find and clean old record if ptr is not NULL + if (ptr != NULL) { + for (i = 0; i < NIMBLE_MEM_DBG_INFO_MAX; i++) { + if (nimble_mem_dbg_info[i].p == ptr) { + old_size = nimble_mem_dbg_info[i].size; + nimble_mem_dbg_current_size -= old_size; + + nimble_mem_dbg_info[i].p = NULL; + nimble_mem_dbg_info[i].size = 0; + nimble_mem_dbg_info[i].func = NULL; + nimble_mem_dbg_info[i].line = 0; + nimble_mem_dbg_count--; + break; + } + } + } + + // Record the new allocation if new_size > 0 + if (new_ptr != NULL && new_size > 0) { + for (i = 0; i < NIMBLE_MEM_DBG_INFO_MAX; i++) { + if (nimble_mem_dbg_info[i].p == NULL) { + nimble_mem_dbg_info[i].p = new_ptr; + nimble_mem_dbg_info[i].size = new_size; + nimble_mem_dbg_info[i].func = func; + nimble_mem_dbg_info[i].line = line; + nimble_mem_dbg_count++; + break; + } + } + + if (i >= NIMBLE_MEM_DBG_INFO_MAX) { + ESP_LOGE("BT_NIMBLE_MEM", "%s full %s %d !!\n", __func__, func, line); + } + + nimble_mem_dbg_current_size += new_size; + if (nimble_mem_dbg_max_size < nimble_mem_dbg_current_size) { + nimble_mem_dbg_max_size = nimble_mem_dbg_current_size; + } + + for (i = 0; i < NIMBLE_MEM_DBG_MAX_SECTION_NUM; i++) { + if (nimble_mem_dbg_max_size_section[i].used && + nimble_mem_dbg_max_size_section[i].max_size < nimble_mem_dbg_current_size) { + nimble_mem_dbg_max_size_section[i].max_size = nimble_mem_dbg_current_size; + } + } + } + + return new_ptr; +} +#endif // CONFIG_BT_NIMBLE_MEM_DEBUG + +#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE +IRAM_ATTR +#endif +void *bt_osi_mem_malloc(size_t size) { void *mem = NULL; #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL @@ -47,7 +288,10 @@ IRAM_ATTR void *bt_osi_mem_malloc(size_t size) return mem; } -IRAM_ATTR void *bt_osi_mem_calloc(size_t n, size_t size) +#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE +IRAM_ATTR +#endif +void *bt_osi_mem_calloc(size_t n, size_t size) { void *mem = NULL; #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL @@ -67,7 +311,10 @@ IRAM_ATTR void *bt_osi_mem_calloc(size_t n, size_t size) return mem; } -IRAM_ATTR void *bt_osi_mem_malloc_internal(size_t size) +#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE +IRAM_ATTR +#endif +void *bt_osi_mem_malloc_internal(size_t size) { void *mem_ptr; #if CONFIG_BT_LE_MEM_CHECK_ENABLED @@ -87,7 +334,10 @@ IRAM_ATTR void *bt_osi_mem_malloc_internal(size_t size) return mem_ptr; } -IRAM_ATTR void *bt_osi_mem_calloc_internal(size_t n, size_t size) +#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE +IRAM_ATTR +#endif +void *bt_osi_mem_calloc_internal(size_t n, size_t size) { void *mem_ptr; #if CONFIG_BT_LE_MEM_CHECK_ENABLED @@ -107,7 +357,10 @@ IRAM_ATTR void *bt_osi_mem_calloc_internal(size_t n, size_t size) return mem_ptr; } -IRAM_ATTR void bt_osi_mem_free_internal(void *ptr) +#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE +IRAM_ATTR +#endif +void bt_osi_mem_free_internal(void *ptr) { #if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED if (ptr) { @@ -116,10 +369,15 @@ IRAM_ATTR void bt_osi_mem_free_internal(void *ptr) controller_mem_used_size -= alloc_size; } #endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED - heap_caps_free(ptr); + if (ptr) { + heap_caps_free(ptr); + } } -IRAM_ATTR void bt_osi_mem_free(void *ptr) +#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE +IRAM_ATTR +#endif +void bt_osi_mem_free(void *ptr) { #if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED if (ptr) { @@ -128,7 +386,9 @@ IRAM_ATTR void bt_osi_mem_free(void *ptr) host_mem_used_size -= alloc_size; } #endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED - heap_caps_free(ptr); + if (ptr) { + heap_caps_free(ptr); + } } #if CONFIG_BT_LE_MEM_CHECK_ENABLED diff --git a/components/bt/porting/mem/os_msys_init.c b/components/bt/porting/mem/os_msys_init.c index 1a121e6d0b..b0340f42cf 100644 --- a/components/bt/porting/mem/os_msys_init.c +++ b/components/bt/porting/mem/os_msys_init.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2019-2025 Espressif Systems (Shanghai) CO LTD */ #include @@ -12,6 +12,7 @@ #include "mem_api.h" #include "bt_osi_mem.h" #include "esp_err.h" +#include "esp_nimble_mem.h" #if CONFIG_BT_NIMBLE_ENABLED #include "syscfg/syscfg.h" @@ -168,17 +169,17 @@ int os_msys_buf_alloc(void) { #if OS_MSYS_1_BLOCK_COUNT > 0 - os_msys_init_1_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE)); + os_msys_init_1_data = (os_membuf_t *)nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE)); if (!os_msys_init_1_data) { return ESP_ERR_NO_MEM; } #endif #if OS_MSYS_2_BLOCK_COUNT > 0 - os_msys_init_2_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE)); + os_msys_init_2_data = (os_membuf_t *)nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE)); if (!os_msys_init_2_data) { #if OS_MSYS_1_BLOCK_COUNT > 0 - bt_osi_mem_free(os_msys_init_1_data); + nimble_platform_mem_free(os_msys_init_1_data); os_msys_init_1_data = NULL; #endif return ESP_ERR_NO_MEM; @@ -192,12 +193,12 @@ void os_msys_buf_free(void) { #if OS_MSYS_1_BLOCK_COUNT > 0 - bt_osi_mem_free(os_msys_init_1_data); + nimble_platform_mem_free(os_msys_init_1_data); os_msys_init_1_data = NULL; #endif #if OS_MSYS_2_BLOCK_COUNT > 0 - bt_osi_mem_free(os_msys_init_2_data); + nimble_platform_mem_free(os_msys_init_2_data); os_msys_init_2_data = NULL; #endif diff --git a/components/bt/porting/npl/freertos/src/npl_os_freertos.c b/components/bt/porting/npl/freertos/src/npl_os_freertos.c index 4103e62042..1e98cf8933 100644 --- a/components/bt/porting/npl/freertos/src/npl_os_freertos.c +++ b/components/bt/porting/npl/freertos/src/npl_os_freertos.c @@ -165,6 +165,13 @@ npl_freertos_eventq_deinit(struct ble_npl_eventq *evq) { struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq; +#if CONFIG_BT_NIMBLE_STATIC_TO_DYNAMIC + /* Deinit can be invoked twice without init . Handle this case */ + if (eventq == NULL) { + return; + } +#endif + BLE_LL_ASSERT(eventq); vQueueDelete(eventq->q); #if OS_MEM_ALLOC diff --git a/components/bt/porting/transport/src/hci_transport.c b/components/bt/porting/transport/src/hci_transport.c index 29c2e00131..52658697ba 100644 --- a/components/bt/porting/transport/src/hci_transport.c +++ b/components/bt/porting/transport/src/hci_transport.c @@ -26,9 +26,12 @@ hci_transport_controller_packet_rx(hci_driver_data_type_t data_type, uint8_t *da r_ble_hci_trans_hs_cmd_tx(data); } +#if CONFIG_BT_CONTROLLER_ONLY || CONFIG_BT_BLUEDROID_ENABLED || \ + (CONFIG_BT_NIMBLE_ENABLED && (CONFIG_BT_NIMBLE_ROLE_CENTRAL || CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)) if (data_type == HCI_DRIVER_TYPE_ACL) { r_ble_hci_trans_hs_acl_tx((struct os_mbuf *) data); } +#endif return 0; } diff --git a/components/esp_adc/test_apps/adc/pytest_adc.py b/components/esp_adc/test_apps/adc/pytest_adc.py index 3cc1661ac2..b914333b98 100644 --- a/components/esp_adc/test_apps/adc/pytest_adc.py +++ b/components/esp_adc/test_apps/adc/pytest_adc.py @@ -32,6 +32,7 @@ def test_adc_esp32c2_xtal_26mhz(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=120, reset=True) +# TODO: IDF-15005 # P4 REV2 adc @pytest.mark.adc @pytest.mark.esp32p4_eco4 diff --git a/components/esp_coex/lib b/components/esp_coex/lib index 63e292b57b..ee5cd79583 160000 --- a/components/esp_coex/lib +++ b/components/esp_coex/lib @@ -1 +1 @@ -Subproject commit 63e292b57b2cda9f9496a71a04bec43e1f0caeba +Subproject commit ee5cd79583c02f23e43e62931ffb55f5a4992d0f diff --git a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c index f9a9f5bc7a..9405ca9c25 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c +++ b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c @@ -85,7 +85,7 @@ static void test_gptimer_sleep_retention(bool allow_pd) printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // check if the power domain also is powered down TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif @@ -202,7 +202,7 @@ static void test_gptimer_etm_sleep_retention(bool back_up_before_sleep) printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // check if the power domain also is powered down TEST_ASSERT_EQUAL(back_up_before_sleep ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py b/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py index b398c74ff0..ab1886a3f5 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py +++ b/components/esp_driver_gptimer/test_apps/gptimer/pytest_gptimer.py @@ -1,8 +1,9 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @@ -14,11 +15,40 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize('target', ['supported_targets'], indirect=['target']) +@idf_parametrize( + 'target', soc_filtered_targets('SOC_GPTIMER_SUPPORTED == 1 and IDF_TARGET not in ["esp32c5"]'), indirect=['target'] +) def test_gptimer(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'cache_safe', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_gptimer_esp32c5(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_gptimer_esp32c5_eco3(dut: Dut) -> None: + dut.run_all_single_board_cases() + + @pytest.mark.generic @pytest.mark.xtal_26mhz @pytest.mark.parametrize( diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index b1da9d1cae..73d1e6b58e 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -1202,6 +1202,12 @@ found: chan_info->dir = handle->dir; chan_info->role = handle->role; chan_info->mode = handle->mode; + chan_info->is_enabled = handle->state == I2S_CHAN_STATE_RUNNING; + chan_info->clk_src = handle->clk_src; + chan_info->sclk_hz = handle->sclk_hz; + chan_info->mclk_hz = handle->curr_mclk_hz; + chan_info->bclk_hz = handle->bclk_hz; + chan_info->mode_cfg = handle->mode_info; chan_info->total_dma_buf_size = handle->state >= I2S_CHAN_STATE_READY ? handle->dma.desc_num * handle->dma.buf_size : 0; if (handle->controller->full_duplex) { if (handle->dir == I2S_DIR_TX) { diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index 280518418c..526ec4f7b3 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -104,6 +104,7 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx handle->sclk_hz = clk_info.sclk; handle->origin_mclk_hz = ((uint64_t)clk_info.sclk * ret_mclk_div.denominator) / tmp_div; handle->curr_mclk_hz = handle->origin_mclk_hz; + handle->bclk_hz = clk_info.bclk; ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); @@ -435,6 +436,7 @@ static esp_err_t i2s_pdm_rx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_rx handle->sclk_hz = clk_info.sclk; handle->origin_mclk_hz = ((uint64_t)clk_info.sclk * ret_mclk_div.denominator) / tmp_div; handle->curr_mclk_hz = handle->origin_mclk_hz; + handle->bclk_hz = clk_info.bclk; ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); diff --git a/components/esp_driver_i2s/i2s_private.h b/components/esp_driver_i2s/i2s_private.h index fdd697fcf8..3ccd93f576 100644 --- a/components/esp_driver_i2s/i2s_private.h +++ b/components/esp_driver_i2s/i2s_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -176,6 +176,7 @@ struct i2s_channel_obj_t { uint32_t sclk_hz; /*!< Source clock frequency */ uint32_t origin_mclk_hz; /*!< Original mclk frequency */ uint32_t curr_mclk_hz; /*!< Current mclk frequency */ + uint32_t bclk_hz; /*!< BCLK frequency */ /* Locks and queues */ SemaphoreHandle_t mutex; /*!< Mutex semaphore for the channel operations */ SemaphoreHandle_t binary; /*!< Binary semaphore for writing / reading / enabling / disabling */ diff --git a/components/esp_driver_i2s/i2s_std.c b/components/esp_driver_i2s/i2s_std.c index 9f8ce6abce..32f4e4125c 100644 --- a/components/esp_driver_i2s/i2s_std.c +++ b/components/esp_driver_i2s/i2s_std.c @@ -105,6 +105,7 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c handle->sclk_hz = clk_info.sclk; handle->origin_mclk_hz = ((uint64_t)clk_info.sclk * ret_mclk_div.denominator) / tmp_div; handle->curr_mclk_hz = handle->origin_mclk_hz; + handle->bclk_hz = clk_info.bclk; ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); @@ -112,13 +113,24 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c return ret; } +static i2s_std_slot_config_t s_i2s_std_normalize_slot_config(const i2s_std_slot_config_t *slot_cfg) +{ + i2s_std_slot_config_t normalized_slot_cfg = *slot_cfg; + /* 1. Normalize the slot bit width */ + normalized_slot_cfg.slot_bit_width = (int)normalized_slot_cfg.slot_bit_width < (int)normalized_slot_cfg.data_bit_width ? + normalized_slot_cfg.data_bit_width : normalized_slot_cfg.slot_bit_width; + + return normalized_slot_cfg; +} + static esp_err_t i2s_std_set_slot(i2s_chan_handle_t handle, const i2s_std_slot_config_t *slot_cfg) { + i2s_std_slot_config_t norm_slot_cfg = s_i2s_std_normalize_slot_config(slot_cfg); /* Update the total slot num and active slot num */ handle->total_slot = 2; - handle->active_slot = slot_cfg->slot_mode == I2S_SLOT_MODE_MONO ? 1 : 2; + handle->active_slot = norm_slot_cfg.slot_mode == I2S_SLOT_MODE_MONO ? 1 : 2; - uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); + uint32_t buf_size = i2s_get_buf_size(handle, norm_slot_cfg.data_bit_width, handle->dma.frame_num); ESP_RETURN_ON_FALSE(buf_size != 0, ESP_ERR_INVALID_ARG, TAG, "invalid data_bit_width"); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { @@ -137,18 +149,15 @@ static esp_err_t i2s_std_set_slot(i2s_chan_handle_t handle, const i2s_std_slot_c portENTER_CRITICAL(&g_i2s.spinlock); /* Configure the hardware to apply STD format */ if (handle->dir == I2S_DIR_TX) { - i2s_hal_std_set_tx_slot(&(handle->controller->hal), is_slave, (i2s_hal_slot_config_t *)slot_cfg); + i2s_hal_std_set_tx_slot(&(handle->controller->hal), is_slave, (i2s_hal_slot_config_t *)&norm_slot_cfg); } else { - i2s_hal_std_set_rx_slot(&(handle->controller->hal), is_slave, (i2s_hal_slot_config_t *)slot_cfg); + i2s_hal_std_set_rx_slot(&(handle->controller->hal), is_slave, (i2s_hal_slot_config_t *)&norm_slot_cfg); } portEXIT_CRITICAL(&g_i2s.spinlock); /* Update the mode info: slot configuration */ i2s_std_config_t *std_cfg = (i2s_std_config_t *)(handle->mode_info); memcpy(&(std_cfg->slot_cfg), slot_cfg, sizeof(i2s_std_slot_config_t)); - /* Update the slot bit width to the actual slot bit width */ - std_cfg->slot_cfg.slot_bit_width = (int)std_cfg->slot_cfg.slot_bit_width < (int)std_cfg->slot_cfg.data_bit_width ? - std_cfg->slot_cfg.data_bit_width : std_cfg->slot_cfg.slot_bit_width; return ESP_OK; } @@ -244,9 +253,8 @@ static esp_err_t s_i2s_channel_try_to_constitude_std_duplex(i2s_chan_handle_t ha /* Judge if the two channels can constitute full-duplex */ if (!handle->controller->full_duplex) { i2s_std_config_t curr_cfg = *std_cfg; - /* Override the slot bit width to the actual slot bit width */ - curr_cfg.slot_cfg.slot_bit_width = (int)curr_cfg.slot_cfg.slot_bit_width < (int)curr_cfg.slot_cfg.data_bit_width ? - curr_cfg.slot_cfg.data_bit_width : curr_cfg.slot_cfg.slot_bit_width; + i2s_std_slot_config_t norm_slot_cfg = s_i2s_std_normalize_slot_config(&(std_cfg->slot_cfg)); + memcpy(&curr_cfg.slot_cfg, &norm_slot_cfg, sizeof(i2s_std_slot_config_t)); /* Compare the hardware configurations of the two channels, constitute the full-duplex if they are the same */ if (memcmp(another_handle->mode_info, &curr_cfg, sizeof(i2s_std_config_t)) == 0) { handle->controller->full_duplex = true; diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index b6ce716a2e..1aa4cf9d7f 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -102,6 +102,7 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c handle->sclk_hz = clk_info.sclk; handle->origin_mclk_hz = ((uint64_t)clk_info.sclk * ret_mclk_div.denominator) / tmp_div; handle->curr_mclk_hz = handle->origin_mclk_hz; + handle->bclk_hz = clk_info.bclk; ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); @@ -109,20 +110,39 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c return ret; } +static i2s_tdm_slot_config_t s_i2s_tdm_normalize_slot_config(const i2s_tdm_slot_config_t *slot_cfg) +{ + i2s_tdm_slot_config_t normalized_slot_cfg = *slot_cfg; + uint32_t max_slot_num = 32 - __builtin_clz(normalized_slot_cfg.slot_mask); + /* 1. Normalize the ws width */ + normalized_slot_cfg.ws_width = normalized_slot_cfg.ws_width == I2S_TDM_AUTO_WS_WIDTH ? + normalized_slot_cfg.total_slot * normalized_slot_cfg.slot_bit_width / 2 : normalized_slot_cfg.ws_width; + + /* 2. Normalize the total slot number */ + normalized_slot_cfg.total_slot = normalized_slot_cfg.total_slot < max_slot_num ? max_slot_num : normalized_slot_cfg.total_slot; + // At least two slots in a frame if not using PCM short format + normalized_slot_cfg.total_slot = ((normalized_slot_cfg.total_slot < 2) && (normalized_slot_cfg.ws_width != 1)) ? 2 : normalized_slot_cfg.total_slot; + + /* 3. Normalize the slot bit width */ + normalized_slot_cfg.slot_bit_width = normalized_slot_cfg.slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? + normalized_slot_cfg.data_bit_width : normalized_slot_cfg.slot_bit_width; + return normalized_slot_cfg; +} + static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_config_t *slot_cfg) { ESP_RETURN_ON_FALSE(slot_cfg->slot_mask, ESP_ERR_INVALID_ARG, TAG, "At least one channel should be enabled"); + + i2s_tdm_slot_config_t norm_slot_cfg = s_i2s_tdm_normalize_slot_config(slot_cfg); /* Update the total slot num and active slot num */ - handle->active_slot = slot_cfg->slot_mode == I2S_SLOT_MODE_MONO ? 1 : __builtin_popcount(slot_cfg->slot_mask); - uint32_t max_slot_num = 32 - __builtin_clz(slot_cfg->slot_mask); - handle->total_slot = slot_cfg->total_slot < max_slot_num ? max_slot_num : slot_cfg->total_slot; + handle->active_slot = norm_slot_cfg.slot_mode == I2S_SLOT_MODE_MONO ? 1 : __builtin_popcount(norm_slot_cfg.slot_mask); + handle->total_slot = norm_slot_cfg.total_slot; // At least two slots in a frame if not using PCM short format - handle->total_slot = ((handle->total_slot < 2) && (slot_cfg->ws_width != 1)) ? 2 : handle->total_slot; - uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; + uint32_t slot_bits = norm_slot_cfg.slot_bit_width; ESP_RETURN_ON_FALSE(handle->total_slot * slot_bits <= I2S_LL_SLOT_FRAME_BIT_MAX, ESP_ERR_INVALID_ARG, TAG, "total slots(%"PRIu32") * slot_bit_width(%"PRIu32") exceeds the maximum %d", handle->total_slot, slot_bits, (int)I2S_LL_SLOT_FRAME_BIT_MAX); - uint32_t buf_size = i2s_get_buf_size(handle, slot_cfg->data_bit_width, handle->dma.frame_num); + uint32_t buf_size = i2s_get_buf_size(handle, norm_slot_cfg.data_bit_width, handle->dma.frame_num); ESP_RETURN_ON_FALSE(buf_size != 0, ESP_ERR_INVALID_ARG, TAG, "invalid data_bit_width"); /* The DMA buffer need to re-allocate if the buffer size changed */ if (handle->dma.buf_size != buf_size) { @@ -149,10 +169,7 @@ static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_c /* Update the mode info: slot configuration */ i2s_tdm_config_t *tdm_cfg = (i2s_tdm_config_t *)(handle->mode_info); - memcpy(&(tdm_cfg->slot_cfg), slot_cfg, sizeof(i2s_tdm_slot_config_t)); - /* Update the slot bit width to the actual slot bit width */ - tdm_cfg->slot_cfg.slot_bit_width = (int)tdm_cfg->slot_cfg.slot_bit_width < (int)tdm_cfg->slot_cfg.data_bit_width ? - tdm_cfg->slot_cfg.data_bit_width : tdm_cfg->slot_cfg.slot_bit_width; + memcpy(&(tdm_cfg->slot_cfg), &norm_slot_cfg, sizeof(i2s_tdm_slot_config_t)); return ESP_OK; } @@ -248,9 +265,8 @@ static void s_i2s_channel_try_to_constitude_tdm_duplex(i2s_chan_handle_t handle, if (another_handle && another_handle->state >= I2S_CHAN_STATE_READY) { if (!handle->controller->full_duplex) { i2s_tdm_config_t curr_cfg = *tdm_cfg; - /* Override the slot bit width to the actual slot bit width */ - curr_cfg.slot_cfg.slot_bit_width = (int)curr_cfg.slot_cfg.slot_bit_width < (int)curr_cfg.slot_cfg.data_bit_width ? - curr_cfg.slot_cfg.data_bit_width : curr_cfg.slot_cfg.slot_bit_width; + i2s_tdm_slot_config_t norm_slot_cfg = s_i2s_tdm_normalize_slot_config(&(tdm_cfg->slot_cfg)); + memcpy(&curr_cfg.slot_cfg, &norm_slot_cfg, sizeof(i2s_tdm_slot_config_t)); /* Compare the hardware configurations of the two channels, constitute the full-duplex if they are the same */ if (memcmp(another_handle->mode_info, &curr_cfg, sizeof(i2s_tdm_config_t)) == 0) { handle->controller->full_duplex = true; diff --git a/components/esp_driver_i2s/include/driver/i2s_common.h b/components/esp_driver_i2s/include/driver/i2s_common.h index 6cf5381343..672c51e810 100644 --- a/components/esp_driver_i2s/include/driver/i2s_common.h +++ b/components/esp_driver_i2s/include/driver/i2s_common.h @@ -89,11 +89,22 @@ typedef struct { i2s_role_t role; /*!< I2S role, I2S_ROLE_MASTER or I2S_ROLE_SLAVE */ i2s_dir_t dir; /*!< I2S channel direction */ i2s_comm_mode_t mode; /*!< I2S channel communication mode */ + bool is_enabled; /*!< I2S channel is enabled or not */ i2s_chan_handle_t pair_chan; /*!< I2S pair channel handle in duplex mode, always NULL in simplex mode */ uint32_t total_dma_buf_size; /*!< Total size of all the allocated DMA buffers * - 0 if the channel has not been initialized * - non-zero if the channel has been initialized */ + i2s_clock_src_t clk_src; /*!< Clock source of I2S */ + uint32_t sclk_hz; /*!< Source clock frequency */ + uint32_t mclk_hz; /*!< MCLK frequency */ + uint32_t bclk_hz; /*!< BCLK frequency */ + const void *mode_cfg; /*!< Mode configuration, it need to be casted to the corresponding type according to the communication mode + * - I2S_COMM_MODE_STD: i2s_std_config_t* + * - I2S_COMM_MODE_TDM: i2s_tdm_config_t* + * - I2S_COMM_MODE_PDM + I2S_DIR_RX: i2s_pdm_rx_config_t* + * - I2S_COMM_MODE_PDM + I2S_DIR_TX: i2s_pdm_tx_config_t* + */ } i2s_chan_info_t; /************************************************** Basic APIs ********************************************************/ diff --git a/components/esp_driver_i2s/include/driver/i2s_types.h b/components/esp_driver_i2s/include/driver/i2s_types.h index 9b501586b8..46d38ed870 100644 --- a/components/esp_driver_i2s/include/driver/i2s_types.h +++ b/components/esp_driver_i2s/include/driver/i2s_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c index 2a0a208de0..6b5b944f31 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c @@ -42,7 +42,7 @@ static void s_test_i2s_enter_light_sleep(int sec, bool allow_power_down) printf("Woke up from light sleep\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_I2S_SUPPORT_SLEEP_RETENTION && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_I2S_SUPPORT_SLEEP_RETENTION // check if the power domain also is powered down TEST_ASSERT_EQUAL(allow_power_down ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py b/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py index 9c34a48bbb..769cae7499 100644 --- a/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py +++ b/components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut @@ -16,13 +16,48 @@ from pytest_embedded_idf.utils import idf_parametrize ) @idf_parametrize( 'target', - ['esp32', 'esp32s2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], + ['esp32', 'esp32s2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], indirect=['target'], ) def test_i2s(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'iram_safe', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32c5'], + indirect=['target'], +) +def test_i2s_esp32c5(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32c5'], + indirect=['target'], +) +def test_i2s_esp32c5_eco3(dut: Dut) -> None: + dut.run_all_single_board_cases() + + @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', diff --git a/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py b/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py index db2527a9ec..8045374fbb 100644 --- a/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py +++ b/components/esp_driver_i2s/test_apps/lp_i2s/pytest_lp_i2s.py @@ -6,6 +6,13 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.lp_i2s +@pytest.mark.parametrize( + 'config', + [ + 'default', + ], + indirect=True, +) @idf_parametrize('target', ['esp32p4'], indirect=['target']) def test_lp_i2s(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=200) diff --git a/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults b/components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.default similarity index 100% rename from components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.defaults rename to components/esp_driver_i2s/test_apps/lp_i2s/sdkconfig.ci.default diff --git a/components/esp_driver_isp/include/driver/isp_awb.h b/components/esp_driver_isp/include/driver/isp_awb.h index 4cd508cd10..070c3390e5 100644 --- a/components/esp_driver_isp/include/driver/isp_awb.h +++ b/components/esp_driver_isp/include/driver/isp_awb.h @@ -27,12 +27,18 @@ typedef struct { * If your camera doesn't support the manual gain or don't want to change the camera configuration, * then you can choose to sample after CCM, and set the calculated gain to the CCM */ - isp_window_t window; /*!< Statistic window of AWB. + isp_window_t window; /*!< Statistic main window of AWB. * Suggest to set it at the middle of the image and a little smaller than the whole image. * It will be more reliable because the edges of image are easily to be overexposure, * the overexposure pixels are almost at maximum luminance, * which are not good references to calculate the gain for white balance. */ + isp_window_t subwindow; /*!< Statistic subwindow of AWB. + * Need to be set no greater than the main window. + * It will be evenly divided into a grid of ISP_AWB_WINDOW_X_NUM * ISP_AWB_WINDOW_Y_NUM blocks. + * The blocks share the same restrictions in R/G, B/G and luminance range as the main window. + * The statistics result of each block will be returned in the `isp_awb_stat_result_t::subwin_result` field. + */ struct { isp_u32_range_t luminance; /*!< Luminance range of the white patch. Range [0, 255 * 3] * Not suggest to set the max value to 255 * 3, diff --git a/components/esp_driver_isp/include/driver/isp_bf.h b/components/esp_driver_isp/include/driver/isp_bf.h index b1301301a9..2669ae3d03 100644 --- a/components/esp_driver_isp/include/driver/isp_bf.h +++ b/components/esp_driver_isp/include/driver/isp_bf.h @@ -24,6 +24,9 @@ typedef struct { uint8_t denoising_level; ///< BF denoising level, from 2 to 20, the bigger the better denoising performance, but the worse detailed uint8_t padding_line_tail_valid_start_pixel; ///< BF edge padding line tail valid start pixel, padding data will only be valid between the valid start pixel and the valid end pixel. Set both the start and end pixel to 0 to make all padding pixel valid uint8_t padding_line_tail_valid_end_pixel; ///< BF edge padding line tail valid end pixel, padding data will only be valid between the valid start pixel and the valid end pixel. Set both the start and end pixel to 0 to make all padding pixel valid + struct { + uint32_t update_once_configured : 1; ///< If set, apply configuration to hardware immediately; otherwise defer to frame boundary + } flags; ///< Driver behaviour flags } esp_isp_bf_config_t; /** diff --git a/components/esp_driver_isp/include/driver/isp_blc.h b/components/esp_driver_isp/include/driver/isp_blc.h index d4a9bd8120..3954e5cfb1 100644 --- a/components/esp_driver_isp/include/driver/isp_blc.h +++ b/components/esp_driver_isp/include/driver/isp_blc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -43,10 +43,13 @@ typedef struct { * @brief ISP BLC configurations */ typedef struct { - isp_window_t window; ///< The sampling windows of BLC, only pixels within the window will be sampled - esp_isp_blc_thresh_t filter_threshold; ///< Black level threshold for each channel of the raw Bayer image - bool filter_enable; ///< Enable filter for BLC, if enabled, only pixels within the threshold will be sampled - esp_isp_blc_stretch_t stretch; ///< Stretch configurations for each channel of the raw Bayer image + isp_window_t window; ///< The sampling windows of BLC, only pixels within the window will be sampled + esp_isp_blc_thresh_t filter_threshold; ///< Black level threshold for each channel of the raw Bayer image + bool filter_enable; ///< Enable filter for BLC, if enabled, only pixels within the threshold will be sampled + esp_isp_blc_stretch_t stretch; ///< Stretch configurations for each channel of the raw Bayer image + struct { + uint32_t update_once_configured : 1; ///< If set, apply configuration to hardware immediately; otherwise defer to frame boundary + } flags; ///< Driver behaviour flags } esp_isp_blc_config_t; /** diff --git a/components/esp_driver_isp/include/driver/isp_ccm.h b/components/esp_driver_isp/include/driver/isp_ccm.h index 1560782894..f779ff3cb7 100644 --- a/components/esp_driver_isp/include/driver/isp_ccm.h +++ b/components/esp_driver_isp/include/driver/isp_ccm.h @@ -26,6 +26,9 @@ typedef struct { * When saturation is true, and final value will be limited to 4.0, and won't rise error * When saturation is false, `esp_isp_ccm_configure` will rise ESP_ERR_INVALID_ARG error */ + struct { + uint32_t update_once_configured : 1; ///< If set, apply configuration to hardware immediately; otherwise defer to frame boundary + } flags; ///< Driver behaviour flags } esp_isp_ccm_config_t; /** diff --git a/components/esp_driver_isp/include/driver/isp_color.h b/components/esp_driver_isp/include/driver/isp_color.h index 5549fdeab3..aaf2906eae 100644 --- a/components/esp_driver_isp/include/driver/isp_color.h +++ b/components/esp_driver_isp/include/driver/isp_color.h @@ -36,6 +36,9 @@ typedef struct { * Zero (0): Maintains the original brightness, without adjusting the image's brightness. * Positive range (1 to 127): Increases brightness, the larger the value, the brighter the image. */ + struct { + uint32_t update_once_configured : 1; ///< If set, apply configuration to hardware immediately; otherwise defer to frame boundary + } flags; ///< Driver behaviour flags } esp_isp_color_config_t; /** diff --git a/components/esp_driver_isp/include/driver/isp_sharpen.h b/components/esp_driver_isp/include/driver/isp_sharpen.h index 636454affb..01dc51873c 100644 --- a/components/esp_driver_isp/include/driver/isp_sharpen.h +++ b/components/esp_driver_isp/include/driver/isp_sharpen.h @@ -27,6 +27,9 @@ typedef struct { uint8_t sharpen_template[ISP_SHARPEN_TEMPLATE_X_NUMS][ISP_SHARPEN_TEMPLATE_Y_NUMS]; ///< Sharpen template data uint8_t padding_line_tail_valid_start_pixel; ///< Sharpen edge padding line tail valid start pixel, padding data will only be valid between the valid start pixel and the valid end pixel. Set both the start and end pixel to 0 to make all padding pixel valid uint8_t padding_line_tail_valid_end_pixel; ///< Sharpen edge padding line tail valid end pixel, padding data will only be valid between the valid start pixel and the valid end pixel. Set both the start and end pixel to 0 to make all padding pixel valid + struct { + uint32_t update_once_configured : 1; ///< If set, apply configuration to hardware immediately; otherwise defer to frame boundary + } flags; ///< Driver behaviour flags } esp_isp_sharpen_config_t; /** diff --git a/components/esp_driver_isp/include/driver/isp_wbg.h b/components/esp_driver_isp/include/driver/isp_wbg.h index b8add5cd50..c4545aed18 100644 --- a/components/esp_driver_isp/include/driver/isp_wbg.h +++ b/components/esp_driver_isp/include/driver/isp_wbg.h @@ -21,7 +21,9 @@ extern "C" { * @brief ISP BLC configurations */ typedef struct { - //for future proof + struct { + uint32_t update_once_configured : 1; ///< If set, apply configuration to hardware immediately; otherwise defer to frame boundary + } flags; ///< Driver behaviour flags } esp_isp_wbg_config_t; /** diff --git a/components/esp_driver_isp/src/isp_awb.c b/components/esp_driver_isp/src/isp_awb.c index 28ab0393bb..b9f25de790 100644 --- a/components/esp_driver_isp/src/isp_awb.c +++ b/components/esp_driver_isp/src/isp_awb.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,7 @@ #include "esp_heap_caps.h" #include "driver/isp_awb.h" #include "esp_private/isp_private.h" +#include "hal/efuse_hal.h" typedef struct isp_awb_controller_t { _Atomic isp_fsm_t fsm; @@ -71,14 +72,61 @@ static esp_err_t s_esp_isp_awb_config_hardware(isp_proc_handle_t isp_proc, const { isp_ll_awb_set_sample_point(isp_proc->hal.hw, awb_cfg->sample_point); ESP_RETURN_ON_FALSE(isp_hal_awb_set_window_range(&isp_proc->hal, &awb_cfg->window), - ESP_ERR_INVALID_ARG, TAG, "invalid window"); + ESP_ERR_INVALID_ARG, TAG, "invalid window range"); + + bool subwindow_is_zero = awb_cfg->subwindow.top_left.x == 0 && + awb_cfg->subwindow.top_left.y == 0 && + awb_cfg->subwindow.btm_right.x == 0 && + awb_cfg->subwindow.btm_right.y == 0; + // Subwindow feature is only supported on REV >= 3.0 + if (efuse_hal_chip_revision() < 300) { + if (!subwindow_is_zero) { + ESP_LOGW(TAG, "Subwindow feature is not supported on REV < 3.0, subwindow will not be configured"); + } + } else { + if (!subwindow_is_zero) { + // Subwindow is just checked and configured on REV >= 3.0 + isp_window_t subwindow = awb_cfg->subwindow; + ESP_RETURN_ON_FALSE( + (subwindow.top_left.x >= awb_cfg->window.top_left.x) && + (subwindow.top_left.y >= awb_cfg->window.top_left.y) && + (subwindow.btm_right.x <= awb_cfg->window.btm_right.x) && + (subwindow.btm_right.y <= awb_cfg->window.btm_right.y), + ESP_ERR_INVALID_ARG, TAG, "subwindow exceeds window range" + ); + + if ((subwindow.btm_right.x - subwindow.top_left.x + 1) / ISP_AWB_WINDOW_X_NUM < 4 || + (subwindow.btm_right.y - subwindow.top_left.y + 1) / ISP_AWB_WINDOW_Y_NUM < 4) { + ESP_LOGE(TAG, "subwindow block size is too small: width and height must be at least 4 (got %d x %d)", + (subwindow.btm_right.x - subwindow.top_left.x + 1) / ISP_AWB_WINDOW_X_NUM, + (subwindow.btm_right.y - subwindow.top_left.y + 1) / ISP_AWB_WINDOW_Y_NUM); + return ESP_ERR_INVALID_ARG; + } + + int size_x = subwindow.btm_right.x - subwindow.top_left.x + 1; + int size_y = subwindow.btm_right.y - subwindow.top_left.y + 1; + if ((size_x % ISP_AWB_WINDOW_X_NUM != 0) || (size_y % ISP_AWB_WINDOW_Y_NUM != 0)) { + ESP_LOGW(TAG, "subwindow size (%d x %d) is not divisible by AWB subwindow blocks grid (%d x %d). \ + Resolution will be floored to the nearest divisible value.", + size_x, size_y, ISP_AWB_WINDOW_X_NUM, ISP_AWB_WINDOW_Y_NUM); + // floor to the nearest divisible value + subwindow.btm_right.x -= size_x % ISP_AWB_WINDOW_X_NUM; + subwindow.btm_right.y -= size_y % ISP_AWB_WINDOW_Y_NUM; + } + ESP_RETURN_ON_FALSE(isp_hal_awb_set_subwindow_range(&isp_proc->hal, &subwindow), + ESP_ERR_INVALID_ARG, TAG, "invalid subwindow range"); + } + } + isp_u32_range_t lum_range = awb_cfg->white_patch.luminance; ESP_RETURN_ON_FALSE(isp_hal_awb_set_luminance_range(&isp_proc->hal, lum_range.min, lum_range.max), ESP_ERR_INVALID_ARG, TAG, "invalid luminance range"); + isp_float_range_t rg_range = awb_cfg->white_patch.red_green_ratio; ESP_RETURN_ON_FALSE(rg_range.min < rg_range.max && rg_range.min >= 0 && isp_hal_awb_set_rg_ratio_range(&isp_proc->hal, rg_range.min, rg_range.max), ESP_ERR_INVALID_ARG, TAG, "invalid range of Red Green ratio"); + isp_float_range_t bg_range = awb_cfg->white_patch.blue_green_ratio; ESP_RETURN_ON_FALSE(bg_range.min < bg_range.max && bg_range.min >= 0 && isp_hal_awb_set_bg_ratio_range(&isp_proc->hal, bg_range.min, bg_range.max), diff --git a/components/esp_driver_isp/src/isp_bf.c b/components/esp_driver_isp/src/isp_bf.c index 1c71d0eefd..23fd164428 100644 --- a/components/esp_driver_isp/src/isp_bf.c +++ b/components/esp_driver_isp/src/isp_bf.c @@ -43,7 +43,7 @@ esp_err_t esp_isp_bf_configure(isp_proc_handle_t proc, const esp_isp_bf_config_t isp_hal_bf_config(&(proc->hal), NULL); } - bool valid = isp_ll_shadow_update_bf(proc->hal.hw); + bool valid = isp_ll_shadow_update_bf(proc->hal.hw, config->flags.update_once_configured); ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update bf shadow register"); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_blc.c b/components/esp_driver_isp/src/isp_blc.c index f8faa2774b..9a9ca10445 100644 --- a/components/esp_driver_isp/src/isp_blc.c +++ b/components/esp_driver_isp/src/isp_blc.c @@ -58,7 +58,7 @@ esp_err_t esp_isp_blc_configure(isp_proc_handle_t isp_proc, const esp_isp_blc_co // Configure stretch enable for each channel isp_ll_blc_enable_stretch(isp_proc->hal.hw, config->stretch.top_left_chan_stretch_en, config->stretch.top_right_chan_stretch_en, config->stretch.bottom_left_chan_stretch_en, config->stretch.bottom_right_chan_stretch_en); - bool valid = isp_ll_shadow_update_blc(isp_proc->hal.hw); + bool valid = isp_ll_shadow_update_blc(isp_proc->hal.hw, config->flags.update_once_configured); ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update blc shadow register"); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_ccm.c b/components/esp_driver_isp/src/isp_ccm.c index 4168a1ad52..cb688dc7f3 100644 --- a/components/esp_driver_isp/src/isp_ccm.c +++ b/components/esp_driver_isp/src/isp_ccm.c @@ -26,7 +26,7 @@ esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config portENTER_CRITICAL(&proc->spinlock); isp_ll_ccm_set_clk_ctrl_mode(proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); ret = isp_hal_ccm_set_matrix(&proc->hal, ccm_cfg->saturation, ccm_cfg->matrix); - valid = isp_ll_shadow_update_ccm(proc->hal.hw); + valid = isp_ll_shadow_update_ccm(proc->hal.hw, ccm_cfg->flags.update_once_configured); portEXIT_CRITICAL(&proc->spinlock); ESP_RETURN_ON_FALSE(ret, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ccm matrix contain NaN or out of range"); ESP_RETURN_ON_FALSE(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update ccm shadow register"); diff --git a/components/esp_driver_isp/src/isp_color.c b/components/esp_driver_isp/src/isp_color.c index c3da6d5cdc..cea2d7945f 100644 --- a/components/esp_driver_isp/src/isp_color.c +++ b/components/esp_driver_isp/src/isp_color.c @@ -43,7 +43,7 @@ esp_err_t esp_isp_color_configure(isp_proc_handle_t proc, const esp_isp_color_co isp_hal_color_config(&(proc->hal), NULL); } - bool valid = isp_ll_shadow_update_color(proc->hal.hw); + bool valid = isp_ll_shadow_update_color(proc->hal.hw, config->flags.update_once_configured); ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update color shadow register"); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_sharpen.c b/components/esp_driver_isp/src/isp_sharpen.c index c0dd2fc258..e0746946d0 100644 --- a/components/esp_driver_isp/src/isp_sharpen.c +++ b/components/esp_driver_isp/src/isp_sharpen.c @@ -45,7 +45,7 @@ esp_err_t esp_isp_sharpen_configure(isp_proc_handle_t proc, const esp_isp_sharpe isp_hal_sharpen_config(&(proc->hal), NULL); } - bool valid = isp_ll_shadow_update_sharpen(proc->hal.hw); + bool valid = isp_ll_shadow_update_sharpen(proc->hal.hw, config->flags.update_once_configured); ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update sharp shadow register"); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_wbg.c b/components/esp_driver_isp/src/isp_wbg.c index 96b809840c..b17d7d9ecc 100644 --- a/components/esp_driver_isp/src/isp_wbg.c +++ b/components/esp_driver_isp/src/isp_wbg.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,11 +32,14 @@ esp_err_t esp_isp_wbg_configure(isp_proc_handle_t isp_proc, const esp_isp_wbg_co } #endif - ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); // Configure clock control mode isp_ll_awb_set_wb_gain_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); + bool valid = isp_ll_shadow_update_wbg(isp_proc->hal.hw, config->flags.update_once_configured); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update wbg shadow register"); + return ESP_OK; } @@ -61,9 +64,6 @@ esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gai // Set WBG gain isp_ll_awb_set_wb_gain(isp_proc->hal.hw, gain); - bool valid = isp_ll_shadow_update_wbg(isp_proc->hal.hw); - ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update wbg shadow register"); - return ESP_OK; } diff --git a/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c b/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c index d14f6033a2..e73b45fb4e 100644 --- a/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c +++ b/components/esp_driver_isp/test_apps/isp/main/test_isp_driver.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -210,15 +210,20 @@ TEST_CASE("ISP CCM basic function", "[isp]") esp_isp_ccm_config_t ccm_cfg = { .matrix = { - {5.0, 0.0, 0.0}, + {16.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} }, .saturation = false, + .flags = { + .update_once_configured = true, + }, }; // Out of range case TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_isp_ccm_configure(isp_proc, &ccm_cfg)); + // saturation case + ccm_cfg.matrix[0][0] = 5.0; ccm_cfg.saturation = true; TEST_ESP_OK(esp_isp_ccm_configure(isp_proc, &ccm_cfg)); TEST_ESP_OK(esp_isp_ccm_enable(isp_proc)); diff --git a/components/esp_driver_isp/test_apps/isp/pytest_isp.py b/components/esp_driver_isp/test_apps/isp/pytest_isp.py index 92c6291f7c..44884efbeb 100644 --- a/components/esp_driver_isp/test_apps/isp/pytest_isp.py +++ b/components/esp_driver_isp/test_apps/isp/pytest_isp.py @@ -1,7 +1,35 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 -from pytest_embedded_idf import IdfDut +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets -def test_isp(dut: IdfDut) -> None: +@pytest.mark.camera +@pytest.mark.ov5647 +@pytest.mark.parametrize( + 'config', + [ + ('default'), + ], + indirect=True, +) +@idf_parametrize('target', soc_filtered_targets('SOC_ISP_SUPPORTED == 1'), indirect=['target']) +def test_isp(dut: Dut) -> None: dut.run_all_single_board_cases() + + +# TODO: IDF-15006 +# @pytest.mark.generic +# @pytest.mark.esp32p4_eco4 +# @pytest.mark.parametrize( +# 'config', +# [ +# ('esp32p4_eco4'), +# ], +# indirect=True, +# ) +# @idf_parametrize('target', ['esp32p4'], indirect=['target']) +# def test_isp_esp32p4_rev2(dut: Dut) -> None: +# dut.run_all_single_board_cases() diff --git a/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.default b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.default new file mode 100644 index 0000000000..7c05891852 --- /dev/null +++ b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.default @@ -0,0 +1 @@ +# For pytest to run default tests diff --git a/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.esp32p4_eco4 b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.esp32p4_eco4 new file mode 100644 index 0000000000..2c6c907fab --- /dev/null +++ b/components/esp_driver_isp/test_apps/isp/sdkconfig.ci.esp32p4_eco4 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32p4" +CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c index 39bea57ef1..980d65b9ed 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c @@ -59,7 +59,7 @@ static void test_ledc_sleep_retention(bool allow_pd) printf("Check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_PMU_SUPPORTED && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_PMU_SUPPORTED // check if the TOP power domain on/off as desired TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py index 42f19403bf..0e0a2c9895 100644 --- a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py +++ b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py @@ -1,8 +1,9 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_ledc_psram') @@ -15,12 +16,41 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize('target', ['supported_targets'], indirect=['target']) +@idf_parametrize( + 'target', soc_filtered_targets('SOC_LEDC_SUPPORTED == 1 and IDF_TARGET not in ["esp32c5"]'), indirect=['target'] +) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14398') def test_ledc(dut: IdfDut) -> None: dut.run_all_single_board_cases(reset=True) +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'iram_safe', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_ledc_esp32c5(dut: IdfDut) -> None: + dut.run_all_single_board_cases(reset=True) + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_ledc_esp32c5_eco3(dut: IdfDut) -> None: + dut.run_all_single_board_cases(reset=True) + + @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sleep.c b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sleep.c index 94aa6b48c8..6c9a78bbec 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sleep.c +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/main/test_mcpwm_sleep.c @@ -84,7 +84,7 @@ static void test_mcpwm_timer_sleep_retention(bool allow_pd) printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_MCPWM_SUPPORT_SLEEP_RETENTION && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_MCPWM_SUPPORT_SLEEP_RETENTION // check if the power domain also is powered down TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif @@ -189,7 +189,7 @@ static void test_mcpwm_capture_timer_sleep_retention(bool allow_pd) printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_MCPWM_SUPPORT_SLEEP_RETENTION && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_MCPWM_SUPPORT_SLEEP_RETENTION // check if the power domain also is powered down TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py b/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py index fc6313a7e2..8e97681969 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/pytest_mcpwm.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @@ -14,7 +14,34 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14412') def test_mcpwm(dut: Dut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'cache_safe', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_mcpwm_esp32c5(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_mcpwm_esp32c5_eco3(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index 706a4e4e64..8f5e7a7fa4 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -660,6 +660,9 @@ esp_err_t parlio_tx_unit_transmit(parlio_tx_unit_handle_t tx_unit, const void *p ESP_RETURN_ON_FALSE(payload_bits <= tx_unit->max_transfer_bits, ESP_ERR_INVALID_ARG, TAG, "payload bit length too large"); #if !SOC_PARLIO_TRANS_BIT_ALIGN ESP_RETURN_ON_FALSE((payload_bits % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "payload bit length must be multiple of 8"); + if (payload_bits % 32 != 0) { + ESP_LOGW(TAG, "payload bit length %d is not multiple of 32, it may cause unexpected behavior", payload_bits); + } #endif // !SOC_PARLIO_TRANS_BIT_ALIGN #if SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_sleep.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_sleep.c index e035b48bea..30223bb9e0 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_sleep.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_sleep.c @@ -133,7 +133,7 @@ static void test_parlio_sleep_retention(bool allow_pd) printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_PARLIO_SUPPORT_SLEEP_RETENTION && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_PARLIO_SUPPORT_SLEEP_RETENTION // check if the power domain also is powered down TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py b/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py index 55b9dbb6c9..cd36a5fd07 100644 --- a/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py +++ b/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @@ -14,7 +14,34 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) +@idf_parametrize('target', ['esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14413') def test_parlio(dut: Dut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'cache_safe', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_parlio_esp32c5(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_parlio_esp32c5_eco3(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c index f53f4db335..9328d78ac1 100644 --- a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c +++ b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c @@ -107,7 +107,7 @@ static void test_rmt_tx_rx_sleep_retention(bool allow_pd) printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_RMT_SUPPORT_SLEEP_RETENTION && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_RMT_SUPPORT_SLEEP_RETENTION // check if the power domain also is powered down TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py b/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py index 1ef07f27e3..2d5686c658 100644 --- a/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py +++ b/components/esp_driver_rmt/test_apps/rmt/pytest_rmt.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @@ -14,14 +14,39 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize( - 'target', ['esp32', 'esp32s2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target'] -) +@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14414') def test_rmt(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'cache_safe', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_rmt_esp32c5(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_rmt_esp32c5_eco3(dut: Dut) -> None: + dut.run_all_single_board_cases() + + @pytest.mark.octal_psram @pytest.mark.parametrize( 'config', diff --git a/components/esp_driver_sdio/src/sdio_slave.c b/components/esp_driver_sdio/src/sdio_slave.c index b5cbc62649..2398018add 100644 --- a/components/esp_driver_sdio/src/sdio_slave.c +++ b/components/esp_driver_sdio/src/sdio_slave.c @@ -611,7 +611,7 @@ static void sdio_intr_send(void *arg) esp_err_t sdio_slave_send_queue(uint8_t *addr, size_t len, void *arg, TickType_t wait) { - SDIO_SLAVE_CHECK(len > 0, "len <= 0", ESP_ERR_INVALID_ARG); + SDIO_SLAVE_CHECK(len > 0 && len <= 4092, "length out of range: (0, 4092]", ESP_ERR_INVALID_ARG); SDIO_SLAVE_CHECK(esp_ptr_dma_capable(addr) && (uint32_t)addr % 4 == 0, "buffer to send should be DMA capable and 32-bit aligned", ESP_ERR_INVALID_ARG); diff --git a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py index 7f614064ab..c8fafe70fc 100644 --- a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py +++ b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded_idf import IdfDut @@ -14,8 +14,23 @@ CONFIGS = [ @pytest.mark.parametrize('config', CONFIGS, indirect=True) @idf_parametrize( 'target', - ['esp32', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32h2', 'esp32p4'], + ['esp32', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32s2', 'esp32s3', 'esp32h2', 'esp32p4'], indirect=['target'], ) def test_sdm(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='sdm') + + +@pytest.mark.generic +@pytest.mark.parametrize('config', ['iram_safe'], indirect=True) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_sdm_esp32c5(dut: IdfDut) -> None: + dut.run_all_single_board_cases(group='sdm') + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize('config', ['release'], indirect=True) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_sdm_esp32c5_eco3(dut: IdfDut) -> None: + dut.run_all_single_board_cases(group='sdm') diff --git a/components/esp_driver_sdspi/include/driver/sdspi_host.h b/components/esp_driver_sdspi/include/driver/sdspi_host.h index 73410bdb02..c397930b9e 100644 --- a/components/esp_driver_sdspi/include/driver/sdspi_host.h +++ b/components/esp_driver_sdspi/include/driver/sdspi_host.h @@ -80,6 +80,10 @@ typedef struct { 0 means "active low", i.e. card is protected when the GPIO is low; 1 means "active high", i.e. card is protected when GPIO is high. */ uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128. + int8_t wait_for_miso; /*!< Timeout value in the driver will be waiting for MISO to be high before sending commands. Possible values are the following: + 0: default value (40ms); -1: no waiting (0ms); 1-127: timeout in ms; else: invalid value, default will be used. + This can be used to speed up transactions in certain scenarios but should not be needed if correct pull-up resistors are used. + Use with care on devices where multiple SPI slaves use the same SPI bus.*/ } sdspi_device_config_t; #define SDSPI_SLOT_NO_CS GPIO_NUM_NC ///< indicates that card select line is not used @@ -91,14 +95,15 @@ typedef struct { /** * Macro defining default configuration of SD SPI device. */ -#define SDSPI_DEVICE_CONFIG_DEFAULT() {\ +#define SDSPI_DEVICE_CONFIG_DEFAULT() { \ .host_id = SDSPI_DEFAULT_HOST, \ .gpio_cs = GPIO_NUM_13, \ .gpio_cd = SDSPI_SLOT_NO_CD, \ .gpio_wp = SDSPI_SLOT_NO_WP, \ .gpio_int = GPIO_NUM_NC, \ .gpio_wp_polarity = SDSPI_IO_ACTIVE_LOW, \ - .duty_cycle_pos = 0,\ + .duty_cycle_pos = 0, \ + .wait_for_miso = 0, \ } /** diff --git a/components/esp_driver_sdspi/src/sdspi_host.c b/components/esp_driver_sdspi/src/sdspi_host.c index 90f4df8042..6fa6633021 100644 --- a/components/esp_driver_sdspi/src/sdspi_host.c +++ b/components/esp_driver_sdspi/src/sdspi_host.c @@ -43,10 +43,15 @@ typedef struct { spi_host_device_t host_id; //!< SPI host id. spi_device_handle_t spi_handle; //!< SPI device handle, used for transactions + uint8_t* block_buf; + /// semaphore of gpio interrupt + SemaphoreHandle_t semphr_int; + uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128. uint8_t gpio_cs; //!< CS GPIO, or GPIO_UNUSED uint8_t gpio_cd; //!< Card detect GPIO, or GPIO_UNUSED uint8_t gpio_wp; //!< Write protect GPIO, or GPIO_UNUSED uint8_t gpio_int; //!< Write protect GPIO, or GPIO_UNUSED + uint8_t poll_busy_start_command_timeout; ///< Timeout value in milliseconds the driver will be waiting for MISO to be high before sending commands. /// GPIO write protect polarity. /// 0 means "active low", i.e. card is protected when the GPIO is low; /// 1 means "active high", i.e. card is protected when GPIO is high. @@ -55,10 +60,6 @@ typedef struct { uint8_t data_crc_enabled : 1; /// Intermediate buffer used when application buffer is not in DMA memory; /// allocated on demand, SDSPI_BLOCK_BUF_SIZE bytes long. May be zero. - uint8_t* block_buf; - /// semaphore of gpio interrupt - SemaphoreHandle_t semphr_int; - uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128. } slot_info_t; // Reserved for old API to be back-compatible @@ -327,6 +328,28 @@ static void gpio_intr(void* arg) } } +static inline int wait_for_miso_to_poll_busy_timeout_ms(int8_t wait_for_miso) +{ + static int default_timeout = 40; // default timeout in ms + int ret; + switch (wait_for_miso) { + case -1: + ret = 0; // no waiting + break; + case 0: + ret = default_timeout; + break; + case 1 ... 127: + ret = (int) wait_for_miso; // timeout in ms + break; + default: + ret = default_timeout; // unsupported values (from -128 to -2), use default + break; + } + assert(ret >= 0); + return ret; +} + esp_err_t sdspi_host_init_device(const sdspi_device_config_t* slot_config, sdspi_dev_handle_t* out_handle) { ESP_LOGD(TAG, "%s: SPI%d cs=%d cd=%d wp=%d wp_polarity:%d", @@ -341,6 +364,7 @@ esp_err_t sdspi_host_init_device(const sdspi_device_config_t* slot_config, sdspi .host_id = slot_config->host_id, .gpio_cs = slot_config->gpio_cs, .duty_cycle_pos = slot_config->duty_cycle_pos, + .poll_busy_start_command_timeout = wait_for_miso_to_poll_busy_timeout_ms(slot_config->wait_for_miso), }; // Attach the SD card to the SPI bus @@ -452,7 +476,6 @@ cleanup: } free(slot); return ret; - } esp_err_t sdspi_host_start_command(sdspi_dev_handle_t handle, sdspi_hw_cmd_t *cmd, void *data, @@ -473,8 +496,21 @@ esp_err_t sdspi_host_start_command(sdspi_dev_handle_t handle, sdspi_hw_cmd_t *cm ESP_LOGV(TAG, "%s: slot=%i, CMD%d, arg=0x%08"PRIx32" flags=0x%x, data=%p, data_size=%"PRIu32" crc=0x%02x", __func__, handle, cmd_index, cmd_arg, flags, data, data_size, cmd->crc7); - spi_device_acquire_bus(slot->spi_handle, portMAX_DELAY); - poll_busy(slot, 40, true); + esp_err_t ret; + ret = spi_device_acquire_bus(slot->spi_handle, portMAX_DELAY); + if (ret != ESP_OK) { + ESP_LOGD(TAG, "%s: spi_device_acquire_bus returned 0x%x", __func__, ret); + return ret; + } + + ret = poll_busy(slot, slot->poll_busy_start_command_timeout, true); + if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) { + ESP_LOGD(TAG, "%s: poll_busy error=0x%x", __func__, ret); + cs_high(slot); + release_bus(slot); + spi_device_release_bus(slot->spi_handle); + return ret; + } // For CMD0, clock out 80 cycles to help the card enter idle state, // *before* CS is asserted. @@ -482,7 +518,7 @@ esp_err_t sdspi_host_start_command(sdspi_dev_handle_t handle, sdspi_hw_cmd_t *cm go_idle_clockout(slot); } // actual transaction - esp_err_t ret = ESP_OK; + ret = ESP_OK; cs_low(slot); if (flags & SDSPI_CMD_FLAG_DATA) { @@ -574,6 +610,11 @@ static esp_err_t start_command_default(slot_info_t *slot, int flags, sdspi_hw_cm // Wait until MISO goes high static esp_err_t poll_busy(slot_info_t *slot, int timeout_ms, bool polling) { + if (timeout_ms < 0) { + return ESP_ERR_INVALID_ARG; + } else if (timeout_ms == 0) { + return ESP_OK; + } uint8_t t_rx; spi_transaction_t t = { .tx_buffer = &t_rx, diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.c b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.c index 53cb1f08fa..bc426cdaf4 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.c +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,13 +37,24 @@ void sdmmc_test_spi_skip_if_board_incompatible(int slot, int freq_khz) } -void sdmmc_test_spi_begin(int slot, int freq_khz, sdmmc_card_t *out_card) +void sdmmc_test_spi_begin(int slot, int freq_khz, sdmmc_card_t *out_card, + sdmmc_host_t *_config, sdspi_device_config_t *_dev_config, spi_bus_config_t *_bus_config) { sdmmc_host_t config = SDSPI_HOST_DEFAULT(); sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT(); spi_bus_config_t bus_config = {}; - sdspi_dev_handle_t handle; + if (_config != NULL) { + config = *_config; + } + if (_dev_config != NULL) { + dev_config = *_dev_config; + } + if (_bus_config != NULL) { + bus_config = *_bus_config; + } + + sdspi_dev_handle_t handle; /* Similar to the checks in sdmmc_test_spi_skip_if_board_incompatible, but * we fail the test if we somehow got to this point with an incompatible board. */ diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.h b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.h index 95f20c8a2a..d45bf5fc3b 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.h +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_begin_end_spi.h @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include "sd_protocol_types.h" +#include "driver/sdspi_host.h" #ifdef __cplusplus extern "C" { @@ -29,7 +30,8 @@ void sdmmc_test_spi_skip_if_board_incompatible(int slot, int freq_khz); * @brief Helper function to initialize the SDMMC host and slot for the test using the given settings, for SPI mode * @see sdmmc_test_sd_begin */ -void sdmmc_test_spi_begin(int slot, int freq_khz, sdmmc_card_t *out_card); +void sdmmc_test_spi_begin(int slot, int freq_khz, sdmmc_card_t *out_card, + sdmmc_host_t *_config, sdspi_device_config_t *_dev_config, spi_bus_config_t *_bus_config); /** * @brief Helper function to deinitialize the SDMMC host and slot after the test, for SPI mode diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_erase_spi.c b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_erase_spi.c index 5f1e3c10f3..4303191766 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_erase_spi.c +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_erase_spi.c @@ -16,7 +16,7 @@ static void do_one_sdspi_erase(int slot, int freq_khz) { sdmmc_card_t card; sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz); - sdmmc_test_spi_begin(slot, freq_khz, &card); + sdmmc_test_spi_begin(slot, freq_khz, &card, NULL, NULL, NULL); sdmmc_card_print_info(stdout, &card); sdmmc_test_sd_erase_blocks(&card); sdmmc_test_spi_end(slot, &card); diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_probe_spi.c b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_probe_spi.c index f765e52a65..c669727338 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_probe_spi.c +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_probe_spi.c @@ -14,7 +14,7 @@ static void do_one_sdspi_probe(int slot, int freq_khz) { sdmmc_card_t card; sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz); - sdmmc_test_spi_begin(slot, freq_khz, &card); + sdmmc_test_spi_begin(slot, freq_khz, &card, NULL, NULL, NULL); sdmmc_card_print_info(stdout, &card); uint8_t* buffer = heap_caps_calloc(512, 1, MALLOC_CAP_DMA); TEST_ESP_OK(sdmmc_read_sectors(&card, buffer, 0, 1)); diff --git a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c index 916498b3c9..986ff591ad 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c +++ b/components/esp_driver_sdspi/test_apps/sdspi/components/sdspi_tests/sdmmc_test_rw_spi.c @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include "unity.h" #include "sdmmc_cmd.h" +#include "driver/sdspi_host.h" #include "sdmmc_test_begin_end_spi.h" #include "sdmmc_test_rw_common.h" @@ -15,7 +16,7 @@ static void do_one_sdspi_perf_test(int slot, int freq_khz) { sdmmc_card_t card; sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz); - sdmmc_test_spi_begin(slot, freq_khz, &card); + sdmmc_test_spi_begin(slot, freq_khz, &card, NULL, NULL, NULL); sdmmc_card_print_info(stdout, &card); sdmmc_test_rw_performance(&card, NULL); sdmmc_test_spi_end(slot, &card); @@ -39,7 +40,7 @@ static void do_one_sdspi_rw_test_with_offset(int slot, int freq_khz) { sdmmc_card_t card; sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz); - sdmmc_test_spi_begin(slot, freq_khz, &card); + sdmmc_test_spi_begin(slot, freq_khz, &card, NULL, NULL, NULL); sdmmc_card_print_info(stdout, &card); sdmmc_test_rw_with_offset(&card); sdmmc_test_spi_end(slot, &card); @@ -63,7 +64,7 @@ static void do_one_sdspi_rw_test_unaligned_buffer(int slot, int freq_khz) { sdmmc_card_t card; sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz); - sdmmc_test_spi_begin(slot, freq_khz, &card); + sdmmc_test_spi_begin(slot, freq_khz, &card, NULL, NULL, NULL); sdmmc_card_print_info(stdout, &card); sdmmc_test_rw_unaligned_buffer(&card); sdmmc_test_spi_end(slot, &card); @@ -78,3 +79,31 @@ TEST_CASE("sdspi read/write using unaligned buffer, slot 1", "[sdspi]") { do_one_sdspi_rw_test_unaligned_buffer(SLOT_1, SDMMC_FREQ_DEFAULT); } + +/* ========== Read/write performance tests with wait_for_miso == -1, SPI ========== */ + +static void do_one_sdspi_perf_test_dont_wait_for_miso(int slot, int freq_khz) +{ + sdmmc_card_t card; + sdmmc_host_t config = SDSPI_HOST_DEFAULT(); + sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT(); + dev_config.wait_for_miso = -1; // no waiting for MISO + spi_bus_config_t bus_config = {}; + sdmmc_test_spi_skip_if_board_incompatible(slot, freq_khz); + sdmmc_test_spi_begin(slot, freq_khz, &card, &config, &dev_config, &bus_config); + sdmmc_card_print_info(stdout, &card); + sdmmc_test_rw_performance(&card, NULL); + sdmmc_test_spi_end(slot, &card); +} + +TEST_CASE("sdspi read/write performance - wait_for_miso == -1, slot 0", "[sdspi]") +{ + do_one_sdspi_perf_test_dont_wait_for_miso(SLOT_0, SDMMC_FREQ_HIGHSPEED); +} + +TEST_CASE("sdspi read/write performance - wait_for_miso == -1, slot 1", "[sdspi]") +{ + //TODO: IDF-8749 + //here freq should be changed to SDMMC_FREQ_HIGHSPEED after fixing IDF-8749 + do_one_sdspi_perf_test_dont_wait_for_miso(SLOT_1, SDMMC_FREQ_DEFAULT); +} diff --git a/components/esp_driver_spi/CMakeLists.txt b/components/esp_driver_spi/CMakeLists.txt index cb1efc7488..945d920b5f 100644 --- a/components/esp_driver_spi/CMakeLists.txt +++ b/components/esp_driver_spi/CMakeLists.txt @@ -27,6 +27,6 @@ idf_component_register( SRCS ${srcs} INCLUDE_DIRS ${public_include} REQUIRES esp_pm - PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio + PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio spi_flash esp_psram #For CONFIG_SPIRAM_SPEED LDFRAGMENTS "linker.lf" ) diff --git a/components/esp_driver_spi/Kconfig b/components/esp_driver_spi/Kconfig index ee180564da..a50a321872 100644 --- a/components/esp_driver_spi/Kconfig +++ b/components/esp_driver_spi/Kconfig @@ -44,7 +44,7 @@ menu "ESP-Driver:SPI Configurations" help Normally only the ISR of SPI slave is placed in the IRAM, so that it can work without the flash when interrupt is triggered. - For other functions, there's some possibility that the flash cache + For other functions, there is some possibility that the flash cache miss when running inside and out of SPI functions, which may increase the interval of SPI transactions. Enable this to put ``queue_trans``, ``get_trans_result`` and diff --git a/components/esp_driver_spi/include/driver/spi_master.h b/components/esp_driver_spi/include/driver/spi_master.h index a432e62334..3567c45e9a 100644 --- a/components/esp_driver_spi/include/driver/spi_master.h +++ b/components/esp_driver_spi/include/driver/spi_master.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -104,6 +104,7 @@ typedef struct { */ } spi_device_interface_config_t; +// Input flags #define SPI_TRANS_MODE_DIO (1<<0) ///< Transmit/receive data in 2-bit mode #define SPI_TRANS_MODE_QIO (1<<1) ///< Transmit/receive data in 4-bit mode #define SPI_TRANS_USE_RXDATA (1<<2) ///< Receive into rx_data member of spi_transaction_t instead into memory at rx_buffer. @@ -117,6 +118,11 @@ typedef struct { #define SPI_TRANS_MODE_OCT (1<<10) ///< Transmit/receive data in 8-bit mode #define SPI_TRANS_MULTILINE_ADDR SPI_TRANS_MODE_DIOQIO_ADDR ///< The data lines used at address phase is the same as data phase (otherwise, only one data line is used at address phase) #define SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL (1<<11) ///< By default driver will automatically re-alloc dma buffer if it doesn't meet hardware alignment or dma_capable requirements, this flag is for you to disable this feature, you will need to take care of the alignment otherwise driver will return you error ESP_ERR_INVALID_ARG +#define SPI_TRANS_DMA_USE_PSRAM (1<<12) ///< Use PSRAM for DMA buffer directly, has speed limit, but no temp buffer and save memory + +// Output flags +#define SPI_TRANS_DMA_RX_FAIL (1<<30) ///< RX transaction data lose flag, indicate DMA RX overflow +#define SPI_TRANS_DMA_TX_FAIL (1<<31) ///< TX transaction data lose flag, indicate DMA TX underflow /** * This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes. diff --git a/components/esp_driver_spi/include/esp_private/spi_common_internal.h b/components/esp_driver_spi/include/esp_private/spi_common_internal.h index 9e374c991d..ba0a11a692 100644 --- a/components/esp_driver_spi/include/esp_private/spi_common_internal.h +++ b/components/esp_driver_spi/include/esp_private/spi_common_internal.h @@ -56,7 +56,8 @@ typedef struct { uint32_t flags; ///< Flags (attributes) of the bus int max_transfer_sz; ///< Maximum length of bytes available to send bool dma_enabled; ///< To enable DMA or not - size_t internal_mem_align_size; ///< Buffer align byte requirement for internal memory + size_t cache_align_int; ///< Internal memory align byte requirement + size_t cache_align_ext; ///< External memory align byte requirement spi_bus_lock_handle_t lock; #ifdef CONFIG_PM_ENABLE esp_pm_lock_handle_t pm_lock; ///< Power management lock @@ -71,9 +72,13 @@ typedef struct { spi_dma_chan_handle_t tx_dma_chan; ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same spi_dma_chan_handle_t rx_dma_chan; ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same #endif - int dma_desc_num; ///< DMA descriptor number of dmadesc_tx or dmadesc_rx. - spi_dma_desc_t *dmadesc_tx; ///< DMA descriptor array for TX - spi_dma_desc_t *dmadesc_rx; ///< DMA descriptor array for RX + size_t dma_align_tx_int; ///< Internal memory align byte requirement for TX + size_t dma_align_tx_ext; ///< External memory align byte requirement for TX + size_t dma_align_rx_int; ///< Internal memory align byte requirement for RX + size_t dma_align_rx_ext; ///< External memory align byte requirement for RX + int dma_desc_num; ///< DMA descriptor number of dmadesc_tx or dmadesc_rx. + spi_dma_desc_t *dmadesc_tx; ///< DMA descriptor array for TX + spi_dma_desc_t *dmadesc_rx; ///< DMA descriptor array for RX } spi_dma_ctx_t; /// Destructor called when a bus is deinitialized. diff --git a/components/esp_driver_spi/include/esp_private/spi_dma.h b/components/esp_driver_spi/include/esp_private/spi_dma.h index 32c4c9e94b..38cf08020d 100644 --- a/components/esp_driver_spi/include/esp_private/spi_dma.h +++ b/components/esp_driver_spi/include/esp_private/spi_dma.h @@ -5,6 +5,7 @@ */ #pragma once +#include #include "stdbool.h" #include "hal/spi_types.h" @@ -36,6 +37,15 @@ typedef struct { */ void spi_dma_enable_burst(spi_dma_chan_handle_t chan_handle, bool data_burst, bool desc_burst); +/** + * Get the alignment constraints for DMA + * + * @param chan_handle Context of the spi_dma channel. + * @param internal_size The alignment size for internal memory. + * @param external_size The alignment size for external memory. + */ +void spi_dma_get_alignment_constraints(spi_dma_chan_handle_t chan_handle, size_t *internal_size, size_t *external_size); + /** * Re-trigger a HW pre-load to pick up appended linked descriptor * diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 98da337c77..978881aa8f 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -6,6 +6,7 @@ #include #include +#include #include "sdkconfig.h" #include "esp_types.h" #include "esp_attr.h" @@ -214,6 +215,10 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch spi_dma_enable_burst(dma_ctx->tx_dma_chan, true, true); spi_dma_enable_burst(dma_ctx->rx_dma_chan, true, true); + + // Get DMA alignment constraints + spi_dma_get_alignment_constraints(dma_ctx->tx_dma_chan, &dma_ctx->dma_align_tx_int, &dma_ctx->dma_align_tx_ext); + spi_dma_get_alignment_constraints(dma_ctx->rx_dma_chan, &dma_ctx->dma_align_rx_int, &dma_ctx->dma_align_rx_ext); return ret; } @@ -227,7 +232,6 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch if (dma_chan == SPI_DMA_CH_AUTO) { gdma_channel_alloc_config_t tx_alloc_config = { - .flags.reserve_sibling = 1, #if CONFIG_SPI_MASTER_ISR_IN_IRAM .flags.isr_cache_safe = true, #endif @@ -237,7 +241,6 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch gdma_channel_alloc_config_t rx_alloc_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, - .sibling_chan = dma_ctx->tx_dma_chan, #if CONFIG_SPI_MASTER_ISR_IN_IRAM .flags.isr_cache_safe = true, #endif @@ -254,13 +257,16 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch gdma_connect(dma_ctx->rx_dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 3)); } #endif - // TODO: add support to allow SPI transfer PSRAM buffer gdma_transfer_config_t trans_cfg = { .max_data_burst_size = 32, - .access_ext_mem = false, + .access_ext_mem = true, // allow to transfer data from/to external memory directly by DMA }; ESP_RETURN_ON_ERROR(gdma_config_transfer(dma_ctx->tx_dma_chan, &trans_cfg), SPI_TAG, "config gdma tx transfer failed"); ESP_RETURN_ON_ERROR(gdma_config_transfer(dma_ctx->rx_dma_chan, &trans_cfg), SPI_TAG, "config gdma rx transfer failed"); + + // Get DMA alignment constraints + gdma_get_alignment_constraints(dma_ctx->tx_dma_chan, &dma_ctx->dma_align_tx_int, &dma_ctx->dma_align_tx_ext); + gdma_get_alignment_constraints(dma_ctx->rx_dma_chan, &dma_ctx->dma_align_rx_int, &dma_ctx->dma_align_rx_ext); } return ret; } @@ -646,7 +652,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT); esp_rom_gpio_connect_out_signal(bus_config->mosi_io_num, spi_periph_signal[host].spid_out, false, false); } else { - gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT); + gpio_input_enable(bus_config->mosi_io_num); } esp_rom_gpio_connect_in_signal(bus_config->mosi_io_num, spi_periph_signal[host].spid_in, false); #if CONFIG_IDF_TARGET_ESP32S2 @@ -659,7 +665,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT); esp_rom_gpio_connect_out_signal(bus_config->miso_io_num, spi_periph_signal[host].spiq_out, false, false); } else { - gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT); + gpio_input_enable(bus_config->miso_io_num); } esp_rom_gpio_connect_in_signal(bus_config->miso_io_num, spi_periph_signal[host].spiq_in, false); #if CONFIG_IDF_TARGET_ESP32S2 @@ -837,9 +843,9 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t * bus_attr = &ctx->bus_attr; bus_attr->bus_cfg = *bus_config; - if (dma_chan != SPI_DMA_DISABLED) { - bus_attr->dma_enabled = 1; - + bus_attr->dma_enabled = (dma_chan != SPI_DMA_DISABLED); + bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE; + if (bus_attr->dma_enabled) { err = spicommon_dma_chan_alloc(host_id, dma_chan, &ctx->dma_ctx); if (err != ESP_OK) { goto cleanup; @@ -848,14 +854,10 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t * if (err != ESP_OK) { goto cleanup; } -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE - esp_cache_get_alignment(MALLOC_CAP_DMA, (size_t *)&bus_attr->internal_mem_align_size); -#else - bus_attr->internal_mem_align_size = 4; -#endif - } else { - bus_attr->dma_enabled = 0; - bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE; + + // Get cache alignment constraints + esp_cache_get_alignment(MALLOC_CAP_DMA, &bus_attr->cache_align_int); + esp_cache_get_alignment(MALLOC_CAP_SPIRAM, &bus_attr->cache_align_ext); } spi_bus_lock_config_t lock_config = { @@ -939,11 +941,14 @@ cleanup: void *spi_bus_dma_memory_alloc(spi_host_device_t host_id, size_t size, uint32_t extra_heap_caps) { - (void) host_id; //remain for extendability - ESP_RETURN_ON_FALSE((extra_heap_caps & MALLOC_CAP_SPIRAM) == 0, NULL, SPI_TAG, "external memory is not supported now"); - - size_t dma_requir = 16; //TODO: IDF-10111, using max alignment temp, refactor to "gdma_get_alignment_constraints" instead - return heap_caps_aligned_calloc(dma_requir, 1, size, extra_heap_caps | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + size_t alignment = 16; + // As don't know the buffer will used for TX or RX, so use the max alignment requirement + if (bus_ctx[host_id] && bus_ctx[host_id]->dma_ctx) { + alignment = (extra_heap_caps & MALLOC_CAP_SPIRAM) ? \ + MAX(bus_ctx[host_id]->dma_ctx->dma_align_tx_ext, bus_ctx[host_id]->dma_ctx->dma_align_rx_ext) : \ + MAX(bus_ctx[host_id]->dma_ctx->dma_align_tx_int, bus_ctx[host_id]->dma_ctx->dma_align_rx_int); + } + return heap_caps_aligned_calloc(alignment, 1, size, extra_heap_caps | MALLOC_CAP_DMA); } const spi_bus_attr_t* spi_bus_get_attr(spi_host_device_t host_id) diff --git a/components/esp_driver_spi/src/gpspi/spi_dma.c b/components/esp_driver_spi/src/gpspi/spi_dma.c index a02bf43df8..84c913a13c 100644 --- a/components/esp_driver_spi/src/gpspi/spi_dma.c +++ b/components/esp_driver_spi/src/gpspi/spi_dma.c @@ -27,6 +27,18 @@ void spi_dma_enable_burst(spi_dma_chan_handle_t chan_handle, bool data_burst, bo } } +void spi_dma_get_alignment_constraints(spi_dma_chan_handle_t chan_handle, size_t *internal_size, size_t *external_size) +{ + spi_dma_dev_t *spi_dma = SPI_LL_GET_HW(chan_handle.host_id); + + if (chan_handle.dir == DMA_CHANNEL_DIRECTION_TX) { + *internal_size = 1; // TX don't need to follow dma alignment in driver design + *external_size = 1; + } else { + spi_dma_ll_get_rx_alignment_require(spi_dma, (uint32_t *)internal_size, (uint32_t *)external_size); + } +} + #if SOC_SPI_SUPPORT_SLAVE_HD_VER2 void spi_dma_append(spi_dma_chan_handle_t chan_handle) { diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index 62f06ae604..e59f8bb8b4 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -116,11 +116,14 @@ We have two bits to control the interrupt: #include "esp_private/spi_common_internal.h" #include "esp_private/spi_master_internal.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/cache_utils.h" #include "driver/spi_master.h" #include "clk_ctrl_os.h" #include "esp_log.h" #include "esp_check.h" #include "esp_ipc.h" +#include "esp_cache.h" +#include "esp_heap_caps.h" #include "freertos/task.h" #include "freertos/queue.h" #include "soc/soc_memory_layout.h" @@ -128,10 +131,6 @@ We have two bits to control the interrupt: #include "hal/spi_hal.h" #include "hal/spi_ll.h" #include "hal/hal_utils.h" -#include "esp_heap_caps.h" -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE -#include "esp_cache.h" -#endif #ifdef CONFIG_SPI_MASTER_ISR_IN_IRAM #define SPI_MASTER_ISR_ATTR IRAM_ATTR @@ -159,6 +158,24 @@ We have two bits to control the interrupt: #define SPI_PERIPH_SRC_FREQ_MAX (80*1000*1000) //peripheral hardware limitation for clock source into peripheral +/** + * The approx time for dma setup and pop data into peripheral + * This time is theoretically inverse proportion to the PSRAM speed(bandwidth), and direct proportion to the SPI speed, but hard to accurately calculated + * Below is an engineering value based on experience test result, e.g. delay 5us for 20MHz PSRAM speed, 1us for 80M + * Then the formula is: Delay_time = K * (SPI_SPEED / PSRAM_SPEED) + B + * delay + * ▲ + * │ x + * │ x + * │ x + * │ x x + * ─┼─────────────────► + * │ psram speed + */ +#define K_EDMA_SETUP_RATIO 1 / 50000 +#define B_EDMA_SETUP_TIME_US 1 +#define SPI_EDMA_SETUP_TIME_US(spi_speed) ((spi_speed) * K_EDMA_SETUP_RATIO / CONFIG_SPIRAM_SPEED + B_EDMA_SETUP_TIME_US) + static const char *SPI_TAG = "spi_master"; #define SPI_CHECK(a, str, ret_val, ...) ESP_RETURN_ON_FALSE_ISR(a, ret_val, SPI_TAG, str, ##__VA_ARGS__) @@ -755,31 +772,13 @@ static void SPI_MASTER_ISR_ATTR s_spi_dma_prepare_data(spi_host_t *host, spi_hal } } -static void SPI_MASTER_ISR_ATTR s_spi_prepare_data(spi_device_t *dev, const spi_hal_trans_config_t *hal_trans) -{ - spi_host_t *host = dev->host; - spi_hal_dev_config_t *hal_dev = &(dev->hal_dev); - spi_hal_context_t *hal = &(host->hal); - - if (host->bus_attr->dma_enabled) { - s_spi_dma_prepare_data(host, hal, hal_dev, hal_trans); - } else { - //Need to copy data to registers manually - spi_hal_push_tx_buffer(hal, hal_trans); - } - - //in ESP32 these registers should be configured after the DMA is set - spi_hal_enable_data_line(hal->hw, (!hal_dev->half_duplex && hal_trans->rcv_buffer) || hal_trans->send_buffer, !!hal_trans->rcv_buffer); -} - static void SPI_MASTER_ISR_ATTR spi_format_hal_trans_struct(spi_device_t *dev, spi_trans_priv_t *trans_buf, spi_hal_trans_config_t *hal_trans) { - spi_host_t *host = dev->host; spi_transaction_t *trans = trans_buf->trans; hal_trans->tx_bitlen = trans->length; hal_trans->rx_bitlen = trans->rxlength; - hal_trans->rcv_buffer = (uint8_t*)host->cur_trans_buf.buffer_to_rcv; - hal_trans->send_buffer = (uint8_t*)host->cur_trans_buf.buffer_to_send; + hal_trans->rcv_buffer = (uint8_t *)trans_buf->buffer_to_rcv; + hal_trans->send_buffer = (uint8_t *)trans_buf->buffer_to_send; hal_trans->cmd = trans->cmd; hal_trans->addr = trans->addr; @@ -815,6 +814,7 @@ static void SPI_MASTER_ISR_ATTR spi_format_hal_trans_struct(spi_device_t *dev, s // Setup the transaction-specified registers and linked-list used by the DMA (or FIFO if DMA is not used) static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_t *trans_buf) { + spi_host_t *host = dev->host; spi_transaction_t *trans = trans_buf->trans; spi_hal_context_t *hal = &(dev->host->hal); spi_hal_dev_config_t *hal_dev = &(dev->hal_dev); @@ -828,12 +828,27 @@ static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_ spi_hal_trans_config_t hal_trans = {}; spi_format_hal_trans_struct(dev, trans_buf, &hal_trans); spi_hal_setup_trans(hal, hal_dev, &hal_trans); - s_spi_prepare_data(dev, &hal_trans); + + if (host->bus_attr->dma_enabled) { + s_spi_dma_prepare_data(host, hal, hal_dev, &hal_trans); + } else { + //Need to copy data to registers manually + spi_hal_push_tx_buffer(hal, &hal_trans); + } + //these registers should be configured after the DMA is set + spi_hal_enable_data_line(hal->hw, (!hal_dev->half_duplex && hal_trans.rcv_buffer) || hal_trans.send_buffer, !!hal_trans.rcv_buffer); //Call pre-transmission callback, if any if (dev->cfg.pre_cb) { dev->cfg.pre_cb(trans); } +#if CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE + spi_hal_clear_intr_mask(hal, SPI_LL_INTR_IN_FULL | SPI_LL_INTR_OUT_EMPTY); + if (esp_ptr_dma_ext_capable(hal_trans.send_buffer)) { + // ! Delay here is required for EDMA to pass data from PSRAM to GPSPI + esp_rom_delay_us(SPI_EDMA_SETUP_TIME_US(hal_dev->timing_conf.real_freq)); + } +#endif //Kick off transfer spi_hal_user_start(hal); } @@ -931,6 +946,26 @@ static void SPI_MASTER_ISR_ATTR spi_post_sct_trans(spi_host_t *host) } #endif //#if SOC_SPI_SCT_SUPPORTED +static void SPI_MASTER_ISR_ATTR spi_trans_dma_error_check(spi_host_t *host) +{ +#if SOC_PSRAM_DMA_CAPABLE && CONFIG_SPIRAM //error checks only for psram dma + if (!host->sct_mode_enabled) { + if (esp_ptr_external_ram(host->cur_trans_buf.buffer_to_rcv) && spi_hal_get_intr_mask(&host->hal, SPI_LL_INTR_IN_FULL)) { + host->cur_trans_buf.trans->flags |= SPI_TRANS_DMA_RX_FAIL; + ESP_DRAM_LOGE(SPI_TAG, "DMA RX overflow detected"); + } else { + host->cur_trans_buf.trans->flags &= ~SPI_TRANS_DMA_RX_FAIL; + } + if (esp_ptr_external_ram(host->cur_trans_buf.buffer_to_send) && spi_hal_get_intr_mask(&host->hal, SPI_LL_INTR_OUT_EMPTY)) { + host->cur_trans_buf.trans->flags |= SPI_TRANS_DMA_TX_FAIL; + ESP_DRAM_LOGE(SPI_TAG, "DMA TX underflow detected"); + } else { + host->cur_trans_buf.trans->flags &= ~SPI_TRANS_DMA_TX_FAIL; + } + } +#endif +} + // This is run in interrupt context. static void SPI_MASTER_ISR_ATTR spi_intr(void *arg) { @@ -968,17 +1003,7 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg) //This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same spicommon_dmaworkaround_idle(dma_ctx->tx_dma_chan.chan_id); #endif //#if CONFIG_IDF_TARGET_ESP32 - -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE //invalidate here to let user access rx data in post_cb if possible - if (host->cur_trans_buf.buffer_to_rcv) { - uint16_t alignment = bus_attr->internal_mem_align_size; - uint32_t buffer_byte_len = (host->cur_trans_buf.trans->rxlength + 7) / 8; - buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); - // invalidate priv_trans.buffer_to_rcv anyway, only user provide aligned buffer can rcv correct data in post_cb - esp_err_t ret = esp_cache_msync((void *)host->cur_trans_buf.buffer_to_rcv, buffer_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C); - assert(ret == ESP_OK); - } -#endif + spi_trans_dma_error_check(host); } #if SOC_SPI_SCT_SUPPORTED @@ -1130,106 +1155,101 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl SPI_CHECK(trans_desc->length <= SPI_LL_CPU_MAX_BIT_LEN, "txdata transfer > hardware max supported len", ESP_ERR_INVALID_ARG); SPI_CHECK(trans_desc->rxlength <= SPI_LL_CPU_MAX_BIT_LEN, "rxdata transfer > hardware max supported len", ESP_ERR_INVALID_ARG); } - + if (esp_ptr_external_ram(trans_desc->tx_buffer) || esp_ptr_external_ram(trans_desc->rx_buffer)) { + SPI_CHECK(spi_flash_cache_enabled(), "Using PSRAM must when cache is enabled", ESP_ERR_INVALID_STATE); + } return ESP_OK; } static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf) { spi_transaction_t *trans_desc = trans_buf->trans; - if ((void *)trans_buf->buffer_to_send != &trans_desc->tx_data[0] && - trans_buf->buffer_to_send != trans_desc->tx_buffer) { + if ((void *)trans_buf->buffer_to_send != trans_desc->tx_data && trans_buf->buffer_to_send != trans_desc->tx_buffer) { free((void *)trans_buf->buffer_to_send); //force free, ignore const } - // copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one. - if (trans_buf->buffer_to_rcv && (void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] && trans_buf->buffer_to_rcv != trans_desc->rx_buffer) { // NOLINT(clang-analyzer-unix.Malloc) - if (trans_desc->flags & SPI_TRANS_USE_RXDATA) { - memcpy((uint8_t *) & trans_desc->rx_data[0], trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8); - } else { - memcpy(trans_desc->rx_buffer, trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8); - } + + // copy data from temporary DMA-capable buffer back to trans_desc buffer and free the temporary one. + void *orig_rx_buffer = (trans_desc->flags & SPI_TRANS_USE_RXDATA) ? trans_desc->rx_data : trans_desc->rx_buffer; + if (trans_buf->buffer_to_rcv != orig_rx_buffer) { + memcpy(orig_rx_buffer, trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8); free(trans_buf->buffer_to_rcv); } } +static SPI_MASTER_ISR_ATTR esp_err_t setup_dma_priv_buffer(spi_host_t *host, uint32_t *buffer, uint32_t len, bool is_tx, uint32_t flags, uint32_t **ret_buffer) +{ +#if CONFIG_IDF_TARGET_ESP32S2 + ESP_RETURN_ON_FALSE_ISR((host->id != SPI3_HOST) || !(flags & SPI_TRANS_DMA_USE_PSRAM), ESP_ERR_NOT_SUPPORTED, SPI_TAG, "SPI3 does not support external memory"); +#endif + bool is_ptr_ext = esp_ptr_external_ram(buffer); + bool use_psram = is_ptr_ext && (flags & SPI_TRANS_DMA_USE_PSRAM); + bool need_malloc = is_ptr_ext ? (!use_psram || !esp_ptr_dma_ext_capable(buffer)) : !esp_ptr_dma_capable(buffer); + uint16_t alignment = 0; + // If psram is wanted, re-malloc also from psram. + uint32_t mem_cap = MALLOC_CAP_DMA | (use_psram ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL); + if (is_tx) { + alignment = use_psram ? host->dma_ctx->dma_align_tx_ext : host->dma_ctx->dma_align_tx_int; + } else { + // RX cache sync still need consider the cache alignment requirement + if (use_psram) { + alignment = MAX(host->dma_ctx->dma_align_rx_ext, host->bus_attr->cache_align_ext); + } else { + alignment = MAX(host->dma_ctx->dma_align_rx_int, host->bus_attr->cache_align_int); + } + } + need_malloc |= (((uint32_t)buffer | len) & (alignment - 1)); + ESP_EARLY_LOGV(SPI_TAG, "%s %p, len %d, is_ptr_ext %d, use_psram: %d, alignment: %d, need_malloc: %d from %s", is_tx ? "TX" : "RX", buffer, len, is_ptr_ext, use_psram, alignment, need_malloc, (mem_cap & MALLOC_CAP_SPIRAM) ? "psram" : "internal"); + if (need_malloc) { + ESP_RETURN_ON_FALSE_ISR(!(flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but %s addr&len not align to %d, or not dma_capable", is_tx ? "TX" : "RX", alignment); + len = (len + alignment - 1) & (~(alignment - 1)); // up align alignment + uint32_t *temp = heap_caps_aligned_alloc(alignment, len, mem_cap); + ESP_RETURN_ON_FALSE_ISR(temp != NULL, ESP_ERR_NO_MEM, SPI_TAG, "Failed to allocate priv %s buffer", is_tx ? "TX" : "RX"); + + if (is_tx) { + memcpy(temp, buffer, len); + } + buffer = temp; + } + if (use_psram) { + esp_err_t ret = esp_cache_msync((void *)buffer, len, is_tx ? (ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED) : ESP_CACHE_MSYNC_FLAG_DIR_M2C); + ESP_RETURN_ON_FALSE_ISR(ret == ESP_OK, ESP_ERR_INVALID_ARG, SPI_TAG, "sync failed for %s buffer", is_tx ? "TX" : "RX"); + } + *ret_buffer = buffer; + return ESP_OK; +} + static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans_priv_t* priv_desc) { spi_transaction_t *trans_desc = priv_desc->trans; const spi_bus_attr_t *bus_attr = host->bus_attr; - uint16_t alignment = bus_attr->internal_mem_align_size; // rx memory assign - uint32_t* rcv_ptr; - if (trans_desc->flags & SPI_TRANS_USE_RXDATA) { - rcv_ptr = (uint32_t *)&trans_desc->rx_data[0]; - } else { - //if not use RXDATA neither rx_buffer, buffer_to_rcv assigned to NULL - rcv_ptr = trans_desc->rx_buffer; - } - + uint32_t* rcv_ptr = (trans_desc->flags & SPI_TRANS_USE_RXDATA) ? (uint32_t *)trans_desc->rx_data : (uint32_t *)trans_desc->rx_buffer; // tx memory assign - const uint32_t *send_ptr; - if (trans_desc->flags & SPI_TRANS_USE_TXDATA) { - send_ptr = (uint32_t *)&trans_desc->tx_data[0]; - } else { - //if not use TXDATA neither tx_buffer, tx data assigned to NULL - send_ptr = trans_desc->tx_buffer ; - } - - uint32_t tx_byte_len = (trans_desc->length + 7) / 8; - uint32_t rx_byte_len = (trans_desc->rxlength + 7) / 8; -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE - bool tx_unaligned = ((((uint32_t)send_ptr) | tx_byte_len) & (alignment - 1)); - bool rx_unaligned = ((((uint32_t)rcv_ptr) | rx_byte_len) & (alignment - 1)); -#else - bool tx_unaligned = false; //tx don't need align on addr or length, for other chips - bool rx_unaligned = (((uint32_t)rcv_ptr) & (alignment - 1)); -#endif + uint32_t *send_ptr = (trans_desc->flags & SPI_TRANS_USE_TXDATA) ? (uint32_t *)trans_desc->tx_data : (uint32_t *)trans_desc->tx_buffer; + esp_err_t ret = ESP_OK; if (send_ptr && bus_attr->dma_enabled) { - if ((!esp_ptr_dma_capable(send_ptr) || tx_unaligned)) { - ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but TX buffer addr&len not align to %d byte, or not dma_capable", alignment); - //if txbuf in the desc not DMA-capable, or not bytes aligned to alignment, malloc a new one - ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA"); - tx_byte_len = (tx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment - uint32_t *temp = heap_caps_aligned_alloc(alignment, tx_byte_len, MALLOC_CAP_DMA); - if (temp == NULL) { - goto clean_up; - } - - memcpy(temp, send_ptr, (trans_desc->length + 7) / 8); - send_ptr = temp; + ret = setup_dma_priv_buffer(host, send_ptr, (trans_desc->length + 7) / 8, true, trans_desc->flags, &send_ptr); + if (ret != ESP_OK) { + goto clean_up; } -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE - esp_err_t ret = esp_cache_msync((void *)send_ptr, tx_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M); - assert(ret == ESP_OK); -#endif } if (rcv_ptr && bus_attr->dma_enabled) { - if ((!esp_ptr_dma_capable(rcv_ptr) || rx_unaligned)) { - ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d byte, or not dma_capable", alignment); - //if rxbuf in the desc not DMA-capable, or not aligned to alignment, malloc a new one - ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA"); - rx_byte_len = (rx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment - rcv_ptr = heap_caps_aligned_alloc(alignment, rx_byte_len, MALLOC_CAP_DMA); - if (rcv_ptr == NULL) { - goto clean_up; - } + ret = setup_dma_priv_buffer(host, rcv_ptr, (trans_desc->rxlength + 7) / 8, false, trans_desc->flags, &rcv_ptr); + if (ret != ESP_OK) { + goto clean_up; } -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE - // do invalid here to hold on cache status to avoid hardware auto write back during dma transaction - esp_err_t ret = esp_cache_msync((void *)rcv_ptr, rx_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C); - assert(ret == ESP_OK); -#endif } + priv_desc->buffer_to_send = send_ptr; priv_desc->buffer_to_rcv = rcv_ptr; return ESP_OK; clean_up: uninstall_priv_desc(priv_desc); - return ESP_ERR_NO_MEM; + return ret; } esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait) @@ -1289,7 +1309,6 @@ esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle BaseType_t r; spi_trans_priv_t trans_buf; SPI_CHECK(handle != NULL, "invalid dev handle", ESP_ERR_INVALID_ARG); - bool use_dma = handle->host->bus_attr->dma_enabled; //if SPI_DEVICE_NO_RETURN_RESULT is set, ret_queue will always be empty SPI_CHECK(!(handle->cfg.flags & SPI_DEVICE_NO_RETURN_RESULT), "API not Supported!", ESP_ERR_NOT_SUPPORTED); @@ -1303,12 +1322,10 @@ esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle return ESP_ERR_TIMEOUT; } //release temporary buffers used by dma - if (use_dma) { - uninstall_priv_desc(&trans_buf); - } + uninstall_priv_desc(&trans_buf); (*trans_desc) = trans_buf.trans; - return ESP_OK; + return (trans_buf.trans->flags & (SPI_TRANS_DMA_RX_FAIL | SPI_TRANS_DMA_TX_FAIL)) ? ESP_ERR_INVALID_STATE : ESP_OK; } //Porcelain to do one blocking transmission. @@ -1457,19 +1474,8 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_end(spi_device_handle_t handle, return ESP_ERR_TIMEOUT; } } - -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE //invalidate here to let user access rx data in post_cb if possible - const spi_bus_attr_t *bus_attr = host->bus_attr; - if (bus_attr->dma_enabled && host->cur_trans_buf.buffer_to_rcv) { - uint16_t alignment = bus_attr->internal_mem_align_size; - uint32_t buffer_byte_len = (host->cur_trans_buf.trans->rxlength + 7) / 8; - buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); - esp_err_t ret = esp_cache_msync((void *)host->cur_trans_buf.buffer_to_rcv, buffer_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C); - if (ret != ESP_OK) { - return ret; - } - } -#endif + spi_trans_dma_error_check(host); + uint32_t trans_flags = host->cur_trans_buf.trans->flags; // save the flags before bus_lock release ESP_LOGV(SPI_TAG, "polling trans done"); //deal with the in-flight transaction @@ -1486,7 +1492,7 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_end(spi_device_handle_t handle, spi_bus_lock_acquire_end(handle->dev_lock); } - return ESP_OK; + return (trans_flags & (SPI_TRANS_DMA_RX_FAIL | SPI_TRANS_DMA_TX_FAIL)) ? ESP_ERR_INVALID_STATE : ESP_OK; } esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_transmit(spi_device_handle_t handle, spi_transaction_t* trans_desc) @@ -1825,20 +1831,16 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_multi_trans(spi_device_handle_t handl SPI_CHECK(handle, "Invalid arguments.", ESP_ERR_INVALID_ARG); SPI_CHECK(SOC_SPI_SCT_SUPPORTED_PERIPH(handle->host->id), "Invalid arguments", ESP_ERR_INVALID_ARG); SPI_CHECK(handle->host->sct_mode_enabled == 1, "SCT mode isn't enabled", ESP_ERR_INVALID_STATE); + esp_err_t ret = ESP_OK; - - uint16_t alignment = handle->host->bus_attr->internal_mem_align_size; - uint32_t *conf_buffer = heap_caps_aligned_alloc(alignment, (trans_num * SOC_SPI_SCT_BUFFER_NUM_MAX * sizeof(uint32_t)), MALLOC_CAP_DMA); - SPI_CHECK(conf_buffer, "No enough memory", ESP_ERR_NO_MEM); - for (int i = 0; i < trans_num; i++) { - ret = check_trans_valid(handle, (spi_transaction_t *)&seg_trans_desc[i]); - if (ret != ESP_OK) { - return ret; - } + ESP_RETURN_ON_ERROR(check_trans_valid(handle, (spi_transaction_t *)&seg_trans_desc[i]), SPI_TAG, "Invalid transaction"); } SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot queue new transaction while previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE); + uint32_t *conf_buffer = heap_caps_malloc(trans_num * SOC_SPI_SCT_BUFFER_NUM_MAX * sizeof(uint32_t), MALLOC_CAP_DMA); + SPI_CHECK(conf_buffer, "No enough memory", ESP_ERR_NO_MEM); + spi_hal_context_t *hal = &handle->host->hal; s_sct_init_conf_buffer(hal, conf_buffer, trans_num); diff --git a/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt b/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt index cc99e1467a..91e5f4d0fc 100644 --- a/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt +++ b/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt @@ -16,6 +16,6 @@ endif() # the component can be registered as WHOLE_ARCHIVE idf_component_register( SRCS ${srcs} - PRIV_REQUIRES esp_driver_spi spi_flash esp_timer + PRIV_REQUIRES esp_driver_spi spi_flash esp_timer esp_driver_gpio esp_mm WHOLE_ARCHIVE ) diff --git a/components/esp_driver_spi/test_apps/master/main/test_spi_master.c b/components/esp_driver_spi/test_apps/master/main/test_spi_master.c index 66942bf579..edf3dfc70e 100644 --- a/components/esp_driver_spi/test_apps/master/main/test_spi_master.c +++ b/components/esp_driver_spi/test_apps/master/main/test_spi_master.c @@ -26,6 +26,7 @@ #include "esp_clk_tree.h" #include "esp_timer.h" #include "esp_log.h" +#include "esp_cache.h" #include "test_utils.h" #include "test_spi_utils.h" #include "spi_performance.h" @@ -123,7 +124,7 @@ TEST_CASE("SPI Master clockdiv calculation routines", "[spi]") // Test All clock source #define TEST_CLK_BYTE_LEN 10000 -#define TEST_TRANS_TIME_BIAS_RATIO (float)5.0/100 // think 5% transfer time bias as acceptable +#define TEST_TRANS_TIME_BIAS_RATIO (float)8.0/100 // think 8% transfer time bias as acceptable TEST_CASE("SPI Master clk_source and divider accuracy", "[spi]") { int64_t start = 0, end = 0; @@ -775,24 +776,27 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]") //connect MOSI to two devices breaks the output, fix it. spitest_gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); -#define TEST_REGION_SIZE 2 +#define TEST_REGION_SIZE 3 static spi_transaction_t trans[TEST_REGION_SIZE]; - int x; memset(trans, 0, sizeof(trans)); - trans[0].length = 320 * 8, - trans[0].tx_buffer = data_malloc + 2; + trans[0].length = 320 * 8; + trans[0].tx_buffer = data_malloc + 2; trans[0].rx_buffer = data_dram; - trans[1].length = 4 * 8, - trans[1].flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA; + trans[1].length = 4 * 8; + trans[1].flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA; uint32_t *ptr = (uint32_t *)trans[1].rx_data; *ptr = 0x54545454; ptr = (uint32_t *)trans[1].tx_data; *ptr = 0xbc124960; + trans[2].length = 64 * 8; + trans[2].tx_buffer = data_drom; + trans[2].rx_buffer = data_malloc; + //Queue all transactions. - for (x = 0; x < TEST_REGION_SIZE; x++) { + for (int x = 0; x < TEST_REGION_SIZE; x++) { ESP_LOGI(TAG, "transmitting %d...", x); ret = spi_device_transmit(spi, &trans[x]); TEST_ASSERT(ret == ESP_OK); @@ -1723,6 +1727,7 @@ static IRAM_ATTR void test_master_iram(void) spi_device_handle_t dev_handle = {0}; spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG(); + devcfg.cs_ena_pretrans = 1; devcfg.post_cb = test_master_iram_post_trans_cbk; TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle)); @@ -1881,7 +1886,7 @@ TEST_CASE("test_spi_master_sleep_retention", "[spi]") // check if the sleep happened as expected TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // check if the power domain also is powered down TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif @@ -1949,7 +1954,7 @@ TEST_CASE("test_spi_master_auto_sleep_retention", "[spi]") // check if the sleep happened as expected TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // check if the power domain also is powered down TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif @@ -1969,3 +1974,100 @@ TEST_CASE("test_spi_master_auto_sleep_retention", "[spi]") } #endif //CONFIG_PM_ENABLE #endif //SOC_LIGHT_SLEEP_SUPPORTED + +#if CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE +#define TEST_EDMA_PSRAM_TRANS_NUM 5 +#define TEST_EDMA_TRANS_LEN 20000 +#define TEST_EDMA_BUFFER_SZ (TEST_EDMA_PSRAM_TRANS_NUM * TEST_EDMA_TRANS_LEN) + +void test_spi_psram_trans(spi_device_handle_t dev_handle, void *tx, void *rx) +{ + spi_transaction_t trans_cfg = { + .tx_buffer = tx, + .rx_buffer = rx, + }; + + int trans_len = TEST_EDMA_TRANS_LEN - TEST_EDMA_PSRAM_TRANS_NUM / 2; + for (uint8_t cnt = 0; cnt < TEST_EDMA_PSRAM_TRANS_NUM; cnt ++) { + trans_cfg.length = trans_len * 8; + trans_cfg.rxlength = trans_len * 8; + trans_cfg.flags = (cnt % 2) ? 0 : SPI_TRANS_DMA_USE_PSRAM; + + // To use psram, hardware will pass data through MSPI and GDMA to GPSPI, which need some time + // GPSPI bandwidth(speed * line_num) should always no more than PSRAM bandwidth + trans_cfg.override_freq_hz = (CONFIG_SPIRAM_SPEED / 4) * 1000 * 1000; + printf("%d TX %p RX %p len %d @%ld kHz\n", cnt, trans_cfg.tx_buffer, trans_cfg.rx_buffer, trans_len, trans_cfg.override_freq_hz / 1000); + TEST_ESP_OK(spi_device_transmit(dev_handle, &trans_cfg)); + TEST_ASSERT(!(trans_cfg.flags & (SPI_TRANS_DMA_RX_FAIL | SPI_TRANS_DMA_TX_FAIL))); + spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, trans_len); + trans_cfg.tx_buffer += trans_len; + trans_cfg.rx_buffer += trans_len; + trans_len ++; + } +} + +TEST_CASE("SPI_Master: PSRAM buffer transaction via EDMA", "[spi]") +{ + spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG(); + buscfg.miso_io_num = buscfg.mosi_io_num; // set spi "self-loopback" + buscfg.max_transfer_sz = TEST_EDMA_BUFFER_SZ; + TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); + + spi_device_handle_t dev_handle = NULL; + spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG(); + devcfg.clock_speed_hz = 80 * 1000 * 1000; // Test error case on highest freq first + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle)); + int real_freq_khz; + spi_device_get_actual_freq(dev_handle, &real_freq_khz); + + uint8_t *internal_1 = heap_caps_calloc(1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_INTERNAL); + uint8_t *external_1 = heap_caps_calloc(1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_SPIRAM); + uint8_t *external_2 = heap_caps_calloc(1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_SPIRAM); + test_fill_random_to_buffers_dualboard(1001, internal_1, external_2, TEST_EDMA_BUFFER_SZ); + + printf("Test error case: High freq @%d kHz\n", real_freq_khz); + spi_transaction_t trans_cfg = { + .length = TEST_EDMA_TRANS_LEN * 8, + .tx_buffer = external_2, + .rx_buffer = external_1, + }; + + // also test on polling API, and automalloc mechanism + for (uint8_t i = 0; i < 2; i++) { + printf("\n==== %s ====\n", i ? "EDMA" : "Auto Malloc"); + trans_cfg.flags = i ? SPI_TRANS_DMA_USE_PSRAM : 0; + uint32_t before = esp_get_free_heap_size(); + spi_device_polling_start(dev_handle, &trans_cfg, portMAX_DELAY); + uint32_t after = esp_get_free_heap_size(); + printf("mem_diff: %ld, trans_len: %d\n", after - before, TEST_EDMA_TRANS_LEN); + // rx buffer still potential re-malloc from psram even if SPI_TRANS_DMA_USE_PSRAM is set + TEST_ASSERT(i ? (before - after) < 2 * TEST_EDMA_TRANS_LEN : (before - after) > 2 * TEST_EDMA_TRANS_LEN); + spi_device_polling_end(dev_handle, portMAX_DELAY); + printf("TX fail: %d, RX fail: %d\n", !!(trans_cfg.flags & SPI_TRANS_DMA_TX_FAIL), !!(trans_cfg.flags & SPI_TRANS_DMA_RX_FAIL)); + TEST_ASSERT((!!i) == !!(trans_cfg.flags & (SPI_TRANS_DMA_TX_FAIL | SPI_TRANS_DMA_RX_FAIL))); + if (!i) { // data should be correct if using auto malloc + spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, TEST_EDMA_TRANS_LEN); + } + } + + printf("\nTest trans: internal -> psram\n"); + memset(external_1, 0, TEST_EDMA_BUFFER_SZ); + TEST_ESP_OK(esp_cache_msync((void *)external_1, TEST_EDMA_BUFFER_SZ, (ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED))); + test_spi_psram_trans(dev_handle, internal_1, external_1); + + printf("\nTest trans: psram -> psram\n"); + memset(external_2, 0, TEST_EDMA_BUFFER_SZ); + TEST_ESP_OK(esp_cache_msync((void *)external_2, TEST_EDMA_BUFFER_SZ, (ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED))); + test_spi_psram_trans(dev_handle, external_1, external_2); + + printf("\nTest trans: psram -> internal\n"); + memset(internal_1, 0, TEST_EDMA_BUFFER_SZ); + test_spi_psram_trans(dev_handle, external_2, internal_1); + + free(internal_1); + free(external_1); + free(external_2); + spi_bus_remove_device(dev_handle); + spi_bus_free(TEST_SPI_HOST); +} +#endif diff --git a/components/esp_driver_spi/test_apps/master/main/test_spi_sio.c b/components/esp_driver_spi/test_apps/master/main/test_spi_sio.c index 8df60daa13..c8d9c9cff3 100644 --- a/components/esp_driver_spi/test_apps/master/main/test_spi_sio.c +++ b/components/esp_driver_spi/test_apps/master/main/test_spi_sio.c @@ -140,7 +140,6 @@ TEST_CASE("SPI Single Board Test SIO", "[spi]") } #endif //#if (TEST_SPI_PERIPH_NUM >= 2) -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) //IDF-7503 slave support /******************************************************************************** * Test SIO Master * SIO Slave is not supported, and one unit test is limited to one feature, so,,, @@ -271,7 +270,7 @@ void test_sio_slave_emulate(bool sio_master_in) unity_wait_for_signal("Master ready"); for (int i = 0; i < TEST_NUM; i++) { - spi_slave_transaction_t trans = {}; + spi_slave_transaction_t trans = { .flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, }; if (sio_master_in) { // slave output only section trans.length = (i + 1) * 8 * 8; @@ -324,4 +323,3 @@ void test_slave_run(void) } TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test_SIO_Mode_Multi_Board", "[spi_ms][test_env=generic_multi_device]", test_master_run, test_slave_run); -#endif //p4 slave support diff --git a/components/esp_driver_spi/test_apps/master/pytest_spi_master.py b/components/esp_driver_spi/test_apps/master/pytest_spi_master.py index 24b40d0dd9..f3e9beb454 100644 --- a/components/esp_driver_spi/test_apps/master/pytest_spi_master.py +++ b/components/esp_driver_spi/test_apps/master/pytest_spi_master.py @@ -1,7 +1,8 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @@ -13,7 +14,9 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize('target', ['supported_targets'], indirect=['target']) +@idf_parametrize( + 'target', soc_filtered_targets('SOC_GPSPI_SUPPORTED == 1 and IDF_TARGET not in ["esp32c5"]'), indirect=['target'] +) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14399') def test_master_single_dev(case_tester) -> None: # type: ignore for case in case_tester.test_menu: @@ -22,6 +25,39 @@ def test_master_single_dev(case_tester) -> None: # type: ignore case_tester.run_normal_case(case=case, reset=True) +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'freertos_flash', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_master_single_dev_esp32c5(case_tester) -> None: # type: ignore + for case in case_tester.test_menu: + if 'test_env' in case.attributes: + continue # If `test_env` is defined, should not run on generic runner + case_tester.run_normal_case(case=case, reset=True) + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_master_single_dev_esp32c5_eco3(case_tester) -> None: # type: ignore + for case in case_tester.test_menu: + if 'test_env' in case.attributes: + continue # If `test_env` is defined, should not run on generic runner + case_tester.run_normal_case(case=case, reset=True) + + # Job for test_env `external_flash` just for esp32 only @pytest.mark.flash_multi @pytest.mark.parametrize( diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32c5 b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32c5 new file mode 100644 index 0000000000..cc641ea603 --- /dev/null +++ b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32c5 @@ -0,0 +1 @@ +CONFIG_SPIRAM=y diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32c61 b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32c61 new file mode 100644 index 0000000000..cc641ea603 --- /dev/null +++ b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32c61 @@ -0,0 +1 @@ +CONFIG_SPIRAM=y diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32p4 b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32p4 new file mode 100644 index 0000000000..cc641ea603 --- /dev/null +++ b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32p4 @@ -0,0 +1 @@ +CONFIG_SPIRAM=y diff --git a/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32s3 b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32s3 new file mode 100644 index 0000000000..cc641ea603 --- /dev/null +++ b/components/esp_driver_spi/test_apps/master/sdkconfig.ci.release.esp32s3 @@ -0,0 +1 @@ +CONFIG_SPIRAM=y diff --git a/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c b/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c index 34c9e0a09a..6f126c7dbd 100644 --- a/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c +++ b/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c @@ -312,6 +312,7 @@ static void test_slave_iram_master_normal(void) spi_device_handle_t dev_handle = {0}; spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG(); + devcfg.cs_ena_pretrans = 1; TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle)); uint8_t *master_send = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DMA); @@ -688,7 +689,7 @@ TEST_CASE("test_spi_slave_sleep_retention", "[spi]") // check if the sleep happened as expected TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // check if the power domain also is powered down TEST_ASSERT_EQUAL((buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py b/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py index 90c6c17575..c85e7b1057 100644 --- a/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py +++ b/components/esp_driver_spi/test_apps/slave/pytest_spi_slave.py @@ -1,17 +1,35 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['release', 'iram_safe'], indirect=True) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14399') -@idf_parametrize('target', ['supported_targets'], indirect=['target']) +@idf_parametrize( + 'target', soc_filtered_targets('SOC_GPSPI_SUPPORTED == 1 and IDF_TARGET not in ["esp32c5"]'), indirect=['target'] +) def test_slave_single_dev(case_tester) -> None: # type: ignore case_tester.run_all_normal_cases(reset=True) +@pytest.mark.generic +@pytest.mark.parametrize('config', ['iram_safe'], indirect=True) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_slave_single_dev_esp32c5(case_tester) -> None: # type: ignore + case_tester.run_all_normal_cases(reset=True) + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize('config', ['release'], indirect=True) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_slave_single_dev_esp32c5_eco3(case_tester) -> None: # type: ignore + case_tester.run_all_normal_cases(reset=True) + + @pytest.mark.generic_multi_device @pytest.mark.parametrize('count, config', [(2, 'release'), (2, 'iram_safe')], indirect=True) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration # TODO: IDF-14399') diff --git a/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c b/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c index 293b1e24ec..491c0fee36 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c +++ b/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c @@ -945,7 +945,7 @@ TEST_CASE("test_spi_slave_hd_sleep_retention", "[spi]") printf("Waked up!\n"); // check if the sleep happened as expected TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // check if the power domain also is powered down TEST_ASSERT_EQUAL((bus_cfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif @@ -1023,7 +1023,7 @@ TEST_CASE("test_spi_slave_hd_append_sleep_retention", "[spi]") printf("Waked up!\n"); // check if the sleep happened as expected TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // check if the power domain also is powered down TEST_ASSERT_EQUAL((bus_cfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #endif diff --git a/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py b/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py index b19a86ab8a..b2332a18a2 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py +++ b/components/esp_driver_spi/test_apps/slave_hd/pytest_spi_slave_hd.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded_idf.utils import idf_parametrize @@ -11,13 +11,21 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c61'], reason='p4 rev3 migration # TODO: IDF-14399') @idf_parametrize( 'target', - ['esp32s2', 'esp32s3', 'esp32c2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], + ['esp32s2', 'esp32s3', 'esp32c2', 'esp32c3', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target'], ) def test_slave_hd_single_dev(case_tester) -> None: # type: ignore case_tester.run_all_normal_cases(reset=True, timeout=180) +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize('config', ['release'], indirect=True) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_slave_hd_single_dev_esp32c5_eco3(case_tester) -> None: # type: ignore + case_tester.run_all_normal_cases(reset=True, timeout=180) + + # if `test_env` not defined, will run on `generic_multi_device` by default @pytest.mark.generic_multi_device @pytest.mark.parametrize('count, config', [(2, 'release')], indirect=True) diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp index b4b32864a8..4fa8069a3e 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp @@ -186,7 +186,7 @@ static void test_temperature_sensor_sleep_retention(bool allow_pd) #endif printf("check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN && !SOC_PM_TOP_PD_NOT_ALLOWED +#if SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN // check if the power domain also is powered down TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); #elif CONFIG_IDF_TARGET_ESP32P4 diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py b/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py index 236a1076ca..8a4e6d093d 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @@ -16,13 +16,31 @@ from pytest_embedded_idf.utils import idf_parametrize ) @idf_parametrize( 'target', - ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'], + ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c61'], indirect=['target'], ) def test_temperature_sensor_driver(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32c5'], + indirect=['target'], +) +def test_temperature_sensor_driver_esp32c5_eco3(dut: Dut) -> None: + dut.run_all_single_board_cases() + + @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -51,8 +69,15 @@ def test_temperature_sensor_cbs_esp32c5(dut: Dut) -> None: @pytest.mark.two_duts @pytest.mark.parametrize('count', [2], indirect=True) +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) @idf_parametrize('target', ['esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32c61'], indirect=['target']) def test_temperature_phy_cases(case_tester: CaseTester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'two_duts') == 'two_duts': - case_tester.run_all_multi_dev_cases(case=case, reset=True) + case_tester.run_multi_dev_case(case=case, reset=True) diff --git a/components/esp_driver_uart/CMakeLists.txt b/components/esp_driver_uart/CMakeLists.txt index bfca544594..6f1bc93c21 100644 --- a/components/esp_driver_uart/CMakeLists.txt +++ b/components/esp_driver_uart/CMakeLists.txt @@ -13,7 +13,7 @@ endif() if(${target} STREQUAL "linux") set(priv_requires esp_ringbuf) else() - set(priv_requires esp_pm esp_driver_gpio esp_ringbuf esp_mm) + set(priv_requires esp_pm esp_driver_gpio esp_ringbuf esp_mm esp_psram) endif() idf_component_register( diff --git a/components/esp_driver_uart/src/uhci.c b/components/esp_driver_uart/src/uhci.c index e390d047c9..be937d796d 100644 --- a/components/esp_driver_uart/src/uhci.c +++ b/components/esp_driver_uart/src/uhci.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,6 +34,7 @@ #include "esp_private/esp_dma_utils.h" #include "esp_private/gdma_link.h" #include "esp_private/esp_cache_private.h" +#include "esp_private/esp_psram_mspi.h" #include "uhci_private.h" #include "esp_memory_utils.h" #include "esp_cache.h" @@ -107,6 +108,7 @@ static bool uhci_gdma_rx_callback_done(gdma_channel_handle_t dma_chan, gdma_even { bool need_yield = false; uhci_controller_handle_t uhci_ctrl = (uhci_controller_handle_t) user_data; + bool is_buf_from_psram = esp_ptr_external_ram(uhci_ctrl->rx_dir.buffer_pointers[uhci_ctrl->rx_dir.node_index]); // If the data is not all received, handle it in not normal_eof block. Otherwise, in eof block. if (!event_data->flags.normal_eof) { size_t rx_size = uhci_ctrl->rx_dir.buffer_size_per_desc_node[uhci_ctrl->rx_dir.node_index]; @@ -116,9 +118,8 @@ static bool uhci_gdma_rx_callback_done(gdma_channel_handle_t dma_chan, gdma_even .flags.totally_received = false, }; - bool need_cache_sync = esp_ptr_internal(uhci_ctrl->rx_dir.buffer_pointers[uhci_ctrl->rx_dir.node_index]) ? (uhci_ctrl->int_mem_cache_line_size > 0) : (uhci_ctrl->ext_mem_cache_line_size > 0); - if (need_cache_sync) { - esp_cache_msync(uhci_ctrl->rx_dir.buffer_pointers[uhci_ctrl->rx_dir.node_index], rx_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + if (is_buf_from_psram) { + esp_psram_mspi_mb(); } if (uhci_ctrl->rx_dir.on_rx_trans_event) { need_yield |= uhci_ctrl->rx_dir.on_rx_trans_event(uhci_ctrl, &evt_data, uhci_ctrl->user_data); @@ -138,10 +139,8 @@ static bool uhci_gdma_rx_callback_done(gdma_channel_handle_t dma_chan, gdma_even .flags.totally_received = true, }; - bool need_cache_sync = esp_ptr_internal(uhci_ctrl->rx_dir.buffer_pointers[uhci_ctrl->rx_dir.node_index]) ? (uhci_ctrl->int_mem_cache_line_size > 0) : (uhci_ctrl->ext_mem_cache_line_size > 0); - size_t m2c_size = UHCI_ALIGN_UP(rx_size, uhci_ctrl->rx_dir.cache_line); - if (need_cache_sync) { - esp_cache_msync(uhci_ctrl->rx_dir.buffer_pointers[uhci_ctrl->rx_dir.node_index], m2c_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + if (is_buf_from_psram) { + esp_psram_mspi_mb(); } // release power manager lock if (uhci_ctrl->pm_lock) { @@ -347,6 +346,13 @@ esp_err_t uhci_receive(uhci_controller_handle_t uhci_ctrl, uint8_t *read_buffer, gdma_link_mount_buffers(uhci_ctrl->rx_dir.dma_link, 0, mount_configs, node_count, NULL); + // Invalidate cache before DMA starts to ensure no dirty cache lines. + // All DMA nodes (mount_configs) share the same contiguous user buffer, so checking mount_configs[0].buffer is sufficient. + bool need_cache_sync = esp_ptr_internal(mount_configs[0].buffer) ? (uhci_ctrl->int_mem_cache_line_size > 0) : (uhci_ctrl->ext_mem_cache_line_size > 0); + if (need_cache_sync) { + ESP_RETURN_ON_ERROR(esp_cache_msync(mount_configs[0].buffer, usable_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), TAG, "cache sync failed"); + } + gdma_reset(uhci_ctrl->rx_dir.dma_chan); gdma_start(uhci_ctrl->rx_dir.dma_chan, gdma_link_get_head_addr(uhci_ctrl->rx_dir.dma_link)); diff --git a/components/esp_eth/test_apps/main/esp_eth_test_apps.c b/components/esp_eth/test_apps/main/esp_eth_test_apps.c index c71686893a..efd0d8a4d4 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_apps.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_apps.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -13,6 +13,7 @@ #include "esp_http_client.h" #include "esp_rom_md5.h" #include "esp_eth_test_common.h" +#include "unity.h" #define LOOPBACK_TEST_PACKET_SIZE 256 @@ -401,7 +402,7 @@ TEST_CASE("ethernet io loopback", "[ethernet]") #endif eth_duplex_t duplex_modes[] = {ETH_DUPLEX_HALF, ETH_DUPLEX_FULL}; - eth_speed_t speeds[] = {ETH_SPEED_10M, ETH_SPEED_100M}; + eth_speed_t speeds[] = {ETH_SPEED_100M, ETH_SPEED_10M}; emac_frame_t* test_packet = malloc(LOOPBACK_TEST_PACKET_SIZE); esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, test_packet->src); esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, test_packet->dest); @@ -447,7 +448,27 @@ TEST_CASE("ethernet io loopback", "[ethernet]") TEST_ASSERT_EQUAL(expected_duplex, actual_duplex); TEST_ESP_OK(esp_eth_transmit(eth_handle, test_packet, LOOPBACK_TEST_PACKET_SIZE)); - TEST_ASSERT(xSemaphoreTake(loopback_test_case_data_received, pdMS_TO_TICKS(10000)) == pdTRUE); + /* 10Mbps RMII loopback may have timing issues due to clock division architecture. RMII CLK stays 50MHz while the data signal must be held still for 10 cycles to + achieve the speed reduction. Everything, including control signals must be perfectly synchronized. This may be a challenge for some PHYs or PCB layouts.*/ + if (expected_speed == ETH_SPEED_10M) { + int i; + for (i = 0; i < 3; i++) { + if(xSemaphoreTake(loopback_test_case_data_received, pdMS_TO_TICKS(1000)) != pdTRUE) { + ESP_LOGW(TAG, "Timeout waiting for data received for 10 Mbps mode, trying again..."); + TEST_ESP_OK(esp_eth_stop(eth_handle)); + bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS)); + TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); + TEST_ESP_OK(esp_eth_start(eth_handle)); + bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS)); + TEST_ESP_OK(esp_eth_transmit(eth_handle, test_packet, LOOPBACK_TEST_PACKET_SIZE)); + } else { + break; + } + } + TEST_ASSERT_LESS_THAN(3, i); + } else { + TEST_ASSERT(xSemaphoreTake(loopback_test_case_data_received, pdMS_TO_TICKS(1000)) == pdTRUE); + } TEST_ESP_OK(esp_eth_stop(eth_handle)); } } diff --git a/components/esp_http_client/lib/http_auth.c b/components/esp_http_client/lib/http_auth.c index 6ba025933e..8de6f0c173 100644 --- a/components/esp_http_client/lib/http_auth.c +++ b/components/esp_http_client/lib/http_auth.c @@ -122,14 +122,15 @@ char *http_auth_digest(const char *username, const char *password, esp_http_auth password == NULL || auth_data->nonce == NULL || auth_data->uri == NULL || - auth_data->realm == NULL) { + auth_data->realm == NULL || + auth_data->algorithm == NULL) { return NULL; } int digest_size = MD5_MAX_LEN; int (*digest_func)(char *digest, const char *fmt, ...) = md5_printf; - if (!memcmp(auth_data->algorithm, "SHA256", strlen("SHA256")) || - !memcmp(auth_data->algorithm, "SHA-256", strlen("SHA-256"))) { + if (strcasecmp(auth_data->algorithm, "SHA256") == 0 || + strcasecmp(auth_data->algorithm, "SHA-256") == 0) { digest_size = SHA256_HEX_LEN; digest_func = sha256_sprintf; } @@ -149,8 +150,7 @@ char *http_auth_digest(const char *username, const char *password, esp_http_auth ESP_LOGD(TAG, "%s %s %s %s", "Digest", username, auth_data->realm, password); if ((strcasecmp(auth_data->algorithm, "md5-sess") == 0) || - (strcasecmp(auth_data->algorithm, "SHA256") == 0) || - (strcasecmp(auth_data->algorithm, "md5-sess") == 0)) { + (strcasecmp(auth_data->algorithm, "SHA-256-sess") == 0)) { if (digest_func(ha1, "%s:%s:%016llx", ha1, auth_data->nonce, auth_data->cnonce) <= 0) { goto _digest_exit; } diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index d10007399d..efaf9a418a 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -1,5 +1,14 @@ menu "Hardware Settings" + config ESP_HW_SUPPORT_FUNC_IN_IRAM + bool + default n if SPI_FLASH_AUTO_SUSPEND + default y + select ESP_PERIPH_CTRL_FUNC_IN_IRAM + select ESP_REGI2C_CTRL_FUNC_IN_IRAM + select RTC_CLK_FUNC_IN_IRAM + select RTC_TIME_FUNC_IN_IRAM + menu "Chip revision" # Insert chip-specific HW config orsource "./port/$IDF_TARGET/Kconfig.hw_support" @@ -219,12 +228,24 @@ menu "Hardware Settings" menu "RTC Clock Config" orsource "./port/$IDF_TARGET/Kconfig.rtc" + + config RTC_CLK_FUNC_IN_IRAM + bool "Place RTC clock module functions into IRAM" + default y + help + Place RTC clock module (all rtc clock functions and const data) into IRAM. + + config RTC_TIME_FUNC_IN_IRAM + bool "Place RTC time module functions into IRAM" + default y + help + Place RTC time module (all rtc clock functions) into IRAM. endmenu menu "Peripheral Control" config ESP_PERIPH_CTRL_FUNC_IN_IRAM bool "Place peripheral control functions into IRAM" - default n + default y help Place peripheral control functions (e.g. periph_module_reset) into IRAM, so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context. diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index 29211df99e..a1348db51c 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -11,7 +11,7 @@ * +-----------------------------------+--+ +--+-----------------------------------+ * | GDMA-Group-X | | | | GDMA-Group-Y | * | +-------------+ +------------+ | | | | +-------------+ +------------+ | - * | | GDMA-Pair-0 |... |GDMA-Pair-N | | | | | | GDMA-Pair-0 |... |GDMA-Pair-N | | + * | | GDMA-Pair-0 |... |GDMA-Pair-N | | | | | | GDMA-Pair-0 |... |GDMA-Pair-M | | * | | | | | | | | | | | | | | * | | TX-Chan |... | TX-Chan | | | | | | TX-Chan |... | TX-Chan | | * | | RX-Chan | | RX-Chan | | | | | | RX-Chan | | RX-Chan | | @@ -70,6 +70,7 @@ typedef struct { int start_group_id; int end_group_id; int pairs_per_group; + uint32_t m2m_capable_mask; void (*hal_init)(gdma_hal_context_t *hal, const gdma_hal_config_t *config); } gdma_channel_search_info_t; @@ -116,6 +117,13 @@ static esp_err_t do_allocate_gdma_channel(const gdma_channel_search_info_t *sear ESP_GOTO_ON_FALSE(group, ESP_ERR_NO_MEM, err, TAG, "no mem for group(%d)", i); group->bus_id = search_info->bus_id; for (int j = 0; j < pairs_per_group && search_code; j++) { // loop to search pair + // Check M2M capability BEFORE acquiring pair to avoid unnecessary allocation + if (config->flags.reserve_sibling) { // Both channels requested (implicit M2M usage) + if (!((1 << j) & search_info->m2m_capable_mask)) { + ESP_LOGV(TAG, "pair(%d,%d) not M2M capable, skip", i, j); + continue; // Skip pairs that don't support M2M + } + } pair = gdma_acquire_pair_handle(group, j); ESP_GOTO_ON_FALSE(pair, ESP_ERR_NO_MEM, err, TAG, "no mem for pair(%d,%d)", i, j); portENTER_CRITICAL(&pair->spinlock); @@ -175,7 +183,7 @@ search_done: } (*ret_chan)->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; - ESP_LOGD(TAG, "new %s channel (%d,%d) at %p", (config->direction == GDMA_CHANNEL_DIRECTION_TX) ? "tx" : "rx", + ESP_LOGV(TAG, "new %s channel (%d,%d) at %p", (config->direction == GDMA_CHANNEL_DIRECTION_TX) ? "tx" : "rx", group->group_id, pair->pair_id, *ret_chan); return ESP_OK; @@ -203,6 +211,7 @@ esp_err_t gdma_new_ahb_channel(const gdma_channel_alloc_config_t *config, gdma_c .start_group_id = GDMA_LL_AHB_GROUP_START_ID, .end_group_id = GDMA_LL_AHB_GROUP_START_ID + GDMA_LL_AHB_NUM_GROUPS, .pairs_per_group = GDMA_LL_AHB_PAIRS_PER_GROUP, + .m2m_capable_mask = GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK, .hal_init = gdma_ahb_hal_init, }; return do_allocate_gdma_channel(&search_info, config, ret_chan); @@ -217,6 +226,7 @@ esp_err_t gdma_new_axi_channel(const gdma_channel_alloc_config_t *config, gdma_c .start_group_id = GDMA_LL_AXI_GROUP_START_ID, .end_group_id = GDMA_LL_AXI_GROUP_START_ID + GDMA_LL_AXI_NUM_GROUPS, .pairs_per_group = GDMA_LL_AXI_PAIRS_PER_GROUP, + .m2m_capable_mask = GDMA_LL_AXI_M2M_CAPABLE_PAIR_MASK, .hal_init = gdma_axi_hal_init, }; return do_allocate_gdma_channel(&search_info, config, ret_chan); @@ -607,7 +617,7 @@ static void gdma_release_group_handle(gdma_group_t *group) gdma_ll_enable_bus_clock(group_id, false); } free(group); - ESP_LOGD(TAG, "del group %d", group_id); + ESP_LOGV(TAG, "del group %d", group_id); } } @@ -644,7 +654,7 @@ static gdma_group_t *gdma_acquire_group_handle(int group_id, void (*hal_init)(gd .group_id = group_id, }; hal_init(&group->hal, &config); - ESP_LOGD(TAG, "new group (%d) at %p", group_id, group); + ESP_LOGV(TAG, "new group (%d) at %p", group_id, group); } else { free(pre_alloc_group); } @@ -672,7 +682,7 @@ static void gdma_release_pair_handle(gdma_pair_t *pair) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION gdma_sleep_retention_deinit(group->group_id, pair_id); #endif - ESP_LOGD(TAG, "del pair (%d,%d)", group->group_id, pair_id); + ESP_LOGV(TAG, "del pair (%d,%d)", group->group_id, pair_id); gdma_release_group_handle(group); } } @@ -712,7 +722,7 @@ static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION gdma_sleep_retention_init(group->group_id, pair_id); #endif - ESP_LOGD(TAG, "new pair (%d,%d) at %p", group->group_id, pair_id, pair); + ESP_LOGV(TAG, "new pair (%d,%d) at %p", group->group_id, pair_id, pair); } else { free(pre_alloc_pair); } @@ -739,11 +749,11 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair->pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "uninstall interrupt service for tx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "uninstall interrupt service for tx channel (%d,%d)", group_id, pair_id); } free(tx_chan); - ESP_LOGD(TAG, "del tx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "del tx channel (%d,%d)", group_id, pair_id); // channel has a reference on pair, release it now gdma_release_pair_handle(pair); return ESP_OK; @@ -768,11 +778,11 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair->pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "uninstall interrupt service for rx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "uninstall interrupt service for rx channel (%d,%d)", group_id, pair_id); } free(rx_chan); - ESP_LOGD(TAG, "del rx channel (%d,%d)", group_id, pair_id); + ESP_LOGV(TAG, "del rx channel (%d,%d)", group_id, pair_id); gdma_release_pair_handle(pair); return ESP_OK; } @@ -884,7 +894,7 @@ static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "install interrupt service for rx channel (%d,%d)", group->group_id, pair_id); + ESP_LOGV(TAG, "install interrupt service for rx channel (%d,%d)", group->group_id, pair_id); err: return ret; @@ -916,7 +926,7 @@ static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan) gdma_hal_enable_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX, false); // disable all interrupt events gdma_hal_clear_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_TX, UINT32_MAX); // clear all pending events portEXIT_CRITICAL(&pair->spinlock); - ESP_LOGD(TAG, "install interrupt service for tx channel (%d,%d)", group->group_id, pair_id); + ESP_LOGV(TAG, "install interrupt service for tx channel (%d,%d)", group->group_id, pair_id); err: return ret; diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index 7f984e947f..96ada2d084 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -149,22 +149,6 @@ esp_err_t esp_deep_sleep_register_phy_hook(esp_deep_sleep_cb_t new_dslp_cb); void esp_deep_sleep_deregister_phy_hook(esp_deep_sleep_cb_t old_dslp_cb); #endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD -/** - * @brief Backup or restore the MMU when the top domain is powered down. - * @param backup_or_restore decide to backup mmu or restore mmu - */ -void esp_sleep_mmu_retention(bool backup_or_restore); - -/** - * @brief Whether to allow the top domain to be powered off due to mmu domain requiring retention. - * - * In light sleep mode, only when the system can provide enough memory - * for mmu retention, the top power domain can be powered off. - */ -bool mmu_domain_pd_allowed(void); -#endif - /** * @brief Notify the sleep process that `sleep_time_overhead_out` needs to be remeasured, which must be called * in the following scenarios: diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 48fb35f098..c5c80bdff1 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -13,13 +13,14 @@ entries: cpu: esp_cpu_compare_and_set (noflash) esp_memory_utils (noflash) clk_utils (noflash) - if PM_SLP_IRAM_OPT = y: + esp_clk_tree: esp_clk_tree_enable_src (noflash) + if RTC_CLK_FUNC_IN_IRAM = y: rtc_clk (noflash) - rtc_time (noflash_text) - esp_clk_tree: esp_clk_tree_enable_src (noflash) if IDF_TARGET_ESP32 = y: rtc_clk:rtc_clk_cpu_freq_to_pll_mhz (noflash) rtc_clk:rtc_clk_cpu_freq_to_xtal (noflash) + if RTC_TIME_FUNC_IN_IRAM = y: + rtc_time (noflash_text) if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED = y: rtc_init:rtc_vddsdio_get_config (noflash) rtc_init:rtc_vddsdio_set_config (noflash) diff --git a/components/esp_hw_support/lowpower/CMakeLists.txt b/components/esp_hw_support/lowpower/CMakeLists.txt index e71f8b67ed..22558a817b 100644 --- a/components/esp_hw_support/lowpower/CMakeLists.txt +++ b/components/esp_hw_support/lowpower/CMakeLists.txt @@ -24,10 +24,6 @@ if(CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND) APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u p4_rev3_mspi_workaround") endif() -if(CONFIG_SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) - list(APPEND srcs "port/${target}/sleep_mmu.c") -endif() - if((CONFIG_SOC_PM_SUPPORT_MODEM_PD OR CONFIG_SOC_PM_SUPPORT_TOP_PD) AND CONFIG_SOC_PAU_SUPPORTED) list(APPEND srcs "port/${target}/sleep_clock.c") endif() diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c deleted file mode 100644 index 3a1cad1728..0000000000 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#include "esp_attr.h" -#include "esp_check.h" -#include "esp_sleep.h" -#include "esp_log.h" -#include "esp_heap_caps.h" -#include "soc/soc_caps.h" -#include "sdkconfig.h" -#include "soc/spi_mem_reg.h" -#include "esp_private/startup_internal.h" - -static const char *TAG = "sleep_mmu"; - -typedef struct { - uint32_t start; - uint32_t end; -} mmu_domain_dev_regs_region_t; - -typedef struct { - mmu_domain_dev_regs_region_t *region; - int region_num; - uint32_t *regs_frame; -} mmu_domain_dev_sleep_frame_t; - -/** - * Internal structure which holds all requested light sleep mmu retention parameters - */ -typedef struct { - struct { - mmu_domain_dev_sleep_frame_t *mmu_table_frame; - } retent; -} sleep_mmu_retention_t; - -static DRAM_ATTR __attribute__((unused)) sleep_mmu_retention_t s_mmu_retention; - -static void * mmu_domain_dev_sleep_frame_alloc_and_init(const mmu_domain_dev_regs_region_t *regions, const int region_num) -{ - const int region_sz = sizeof(mmu_domain_dev_regs_region_t) * region_num; - int regs_frame_sz = 0; - for (int num = 0; num < region_num; num++) { - regs_frame_sz += regions[num].end - regions[num].start; - } - void *frame = heap_caps_malloc(sizeof(mmu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); - if (frame) { - mmu_domain_dev_regs_region_t *region = (mmu_domain_dev_regs_region_t *)(frame + sizeof(mmu_domain_dev_sleep_frame_t)); - memcpy(region, regions, region_num * sizeof(mmu_domain_dev_regs_region_t)); - void *regs_frame = frame + sizeof(mmu_domain_dev_sleep_frame_t) + region_sz; - memset(regs_frame, 0, regs_frame_sz); - *(mmu_domain_dev_sleep_frame_t *)frame = (mmu_domain_dev_sleep_frame_t) { - .region = region, - .region_num = region_num, - .regs_frame = (uint32_t *)regs_frame - }; - } - return frame; -} - -static inline void * mmu_domain_mmu_table_sleep_frame_alloc_and_init(void) -{ - #define MMU_TABLE_SIZE (512 * 4) - const static mmu_domain_dev_regs_region_t regions[] = { - { .start = SPI_MEM_MMU_ITEM_CONTENT_REG(0), .end = SPI_MEM_MMU_ITEM_CONTENT_REG(0) + MMU_TABLE_SIZE} - }; - return mmu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static IRAM_ATTR void mmu_domain_dev_regs_save(mmu_domain_dev_sleep_frame_t *frame) -{ - assert(frame); - mmu_domain_dev_regs_region_t *region = frame->region; - uint32_t *regs_frame = frame->regs_frame; - - int offset = 0; - for (int i = 0; i < frame->region_num; i++) { - for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) { - REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset); - regs_frame[offset++] = REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0)); - } - } -} - -static IRAM_ATTR void mmu_domain_dev_regs_restore(mmu_domain_dev_sleep_frame_t *frame) -{ - assert(frame); - mmu_domain_dev_regs_region_t *region = frame->region; - uint32_t *regs_frame = frame->regs_frame; - - int offset = 0; - for (int i = 0; i < frame->region_num; i++) { - for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) { - REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset); - REG_WRITE(SPI_MEM_MMU_ITEM_CONTENT_REG(0),regs_frame[offset++]); - } - } -} - -IRAM_ATTR void esp_sleep_mmu_retention(bool backup_or_restore) -{ - if (backup_or_restore) { - mmu_domain_dev_regs_save(s_mmu_retention.retent.mmu_table_frame); - } else { - mmu_domain_dev_regs_restore(s_mmu_retention.retent.mmu_table_frame); - } -} - -static esp_err_t esp_sleep_mmu_retention_deinit(void) -{ - if (s_mmu_retention.retent.mmu_table_frame) { - heap_caps_free((void *)s_mmu_retention.retent.mmu_table_frame); - s_mmu_retention.retent.mmu_table_frame = NULL; - } - return ESP_OK; -} - -static esp_err_t esp_sleep_mmu_retention_init(void) -{ - if (s_mmu_retention.retent.mmu_table_frame == NULL) { - void *frame = mmu_domain_mmu_table_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_mmu_retention.retent.mmu_table_frame = (mmu_domain_dev_sleep_frame_t *)frame; - } - return ESP_OK; -err: - esp_sleep_mmu_retention_deinit(); - return ESP_ERR_NO_MEM; -} - -bool mmu_domain_pd_allowed(void) -{ - return (s_mmu_retention.retent.mmu_table_frame != NULL); -} - -ESP_SYSTEM_INIT_FN(sleep_mmu_startup_init, SECONDARY, BIT(0), 108) -{ - esp_err_t ret; - ret = esp_sleep_mmu_retention_init(); - if (ret != ESP_OK) { - ESP_EARLY_LOGW(TAG, "Failed to enable TOP power down during light sleep."); - } - return ESP_OK; -} diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b7f54b6e1e..5d0c46a928 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -156,7 +156,11 @@ #define FAST_CLK_SRC_CAL_CYCLES (2048) /* ~ 127.4 us */ #ifdef CONFIG_IDF_TARGET_ESP32 +#if !CONFIG_PM_SLP_IRAM_OPT +#define DEFAULT_SLEEP_OUT_OVERHEAD_US (476) +#else #define DEFAULT_SLEEP_OUT_OVERHEAD_US (212) +#endif #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (60) #elif CONFIG_IDF_TARGET_ESP32S2 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (147) @@ -164,6 +168,10 @@ #elif CONFIG_IDF_TARGET_ESP32S3 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (382) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (133) +# if !CONFIG_PM_SLP_IRAM_OPT + #undef DEFAULT_SLEEP_OUT_OVERHEAD_US + #define DEFAULT_SLEEP_OUT_OVERHEAD_US (8628) +# endif #elif CONFIG_IDF_TARGET_ESP32C3 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (105) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (37) @@ -217,10 +225,6 @@ #define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ) #endif -#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD -#define SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US (1220) -#endif - #define RTC_MODULE_SLEEP_PREPARE_CYCLES (6) #define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \ @@ -915,9 +919,6 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { -#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD - esp_sleep_mmu_retention(true); -#endif #if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) sleep_retention_do_extra_retention(true); #endif @@ -945,8 +946,8 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { -#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD - esp_sleep_mmu_retention(false); +#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA + sleep_retention_do_system_retention(false); #endif #if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) sleep_flash_p4_rev3_workaround(); @@ -1160,13 +1161,11 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl if (!deep_sleep) { if (result == ESP_OK) { -#if !CONFIG_PM_SLP_IRAM_OPT && !CONFIG_IDF_TARGET_ESP32 + s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); +#if !CONFIG_PM_SLP_IRAM_OPT && !(CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32P4) #if CONFIG_SPIRAM -# if CONFIG_IDF_TARGET_ESP32P4 - cache_ll_writeback_all(CACHE_LL_LEVEL_ALL, CACHE_TYPE_DATA, CACHE_LL_ID_ALL); -# else + // TODO: PM-651 Cache_WriteBack_All(); -# endif #endif /* When the IRAM optimization for the sleep flow is disabled, all * cache contents are forcibly invalidated before exiting the sleep @@ -1174,12 +1173,6 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl * flow remains consistent, allowing the use of ccount to * dynamically calculate the sleep adjustment time. */ cache_ll_invalidate_all(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL); -#endif - s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); -#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA - if (sleep_flags & PMU_SLEEP_PD_TOP) { - sleep_retention_do_system_retention(false); - } #endif } misc_modules_wake_prepare(sleep_flags); @@ -1494,10 +1487,6 @@ esp_err_t esp_light_sleep_start(void) int sleep_time_sw_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out; int sleep_time_hw_adjustment = pmu_sleep_calculate_hw_wait_time(sleep_flags, rtc_clk_slow_src_get(), s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period); s_config.sleep_time_adjustment = sleep_time_sw_adjustment + sleep_time_hw_adjustment; -#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD - int sleep_time_sw_mmu_table_restore = (sleep_flags & PMU_SLEEP_PD_TOP) ? SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US : 0; - s_config.sleep_time_adjustment += sleep_time_sw_mmu_table_restore; -#endif #else uint32_t rtc_cntl_xtl_buf_wait_slp_cycles = rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, s_config.rtc_clk_cal_period); s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out @@ -2548,9 +2537,6 @@ FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) { top_pd_allowed &= cpu_domain_pd_allowed(); #else top_pd_allowed = false; -#endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD - top_pd_allowed &= mmu_domain_pd_allowed(); #endif top_pd_allowed &= clock_domain_pd_allowed(); top_pd_allowed &= peripheral_domain_pd_allowed(); @@ -2560,10 +2546,11 @@ FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) { #if SOC_XTAL_CLOCK_PATH_DEPENDS_ON_TOP_DOMAIN top_pd_allowed &= (s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option != ESP_PD_OPTION_ON); #endif -#if SOC_PM_TOP_PD_NOT_ALLOWED - // TODO: PM-436, Need to use efuse_hal_chip_revision() to determine whether - // the TOP domain power-down is allowed - top_pd_allowed = false; +#if CONFIG_IDF_TARGET_ESP32C5 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) { + // ESP32C5 chips lower than v1.2 are not supported to power down the TOP domain + top_pd_allowed = false; + } #endif return top_pd_allowed; diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c index 81f7707718..bd9ed24fd5 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_random.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py index c874e8f204..beca94dde8 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut diff --git a/components/esp_mm/esp_cache_msync.c b/components/esp_mm/esp_cache_msync.c index d296da1a9b..c94cb97eec 100644 --- a/components/esp_mm/esp_cache_msync.c +++ b/components/esp_mm/esp_cache_msync.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_mm/include/esp_cache.h b/components/esp_mm/include/esp_cache.h index f8efcb979c..03db92f341 100644 --- a/components/esp_mm/include/esp_cache.h +++ b/components/esp_mm/include/esp_cache.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_mm/include/esp_private/esp_cache_private.h b/components/esp_mm/include/esp_private/esp_cache_private.h index fc09ed44f1..2cd10d069c 100644 --- a/components/esp_mm/include/esp_private/esp_cache_private.h +++ b/components/esp_mm/include/esp_private/esp_cache_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index ca843fff48..6986cccff5 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -1,12 +1,14 @@ menu "Power Management" config PM_SLEEP_FUNC_IN_IRAM - bool "Place Power Management module functions in IRAM" if IDF_TARGET_ESP32C2 - default y + bool "Place Power Management module functions in IRAM" + default n select PM_SLP_IRAM_OPT if SOC_LIGHT_SLEEP_SUPPORTED select PM_RTOS_IDLE_OPT if FREERTOS_USE_TICKLESS_IDLE select ESP_PERIPH_CTRL_FUNC_IN_IRAM select ESP_REGI2C_CTRL_FUNC_IN_IRAM + select RTC_CLK_FUNC_IN_IRAM + select RTC_TIME_FUNC_IN_IRAM config PM_ENABLE diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index acf6b7852c..20e3811c2e 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -32,8 +32,6 @@ entries: sleep_cpu:sleep_enable_cpu_retention (noflash) if PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y || (ESP32P4_SELECTS_REV_LESS_V3 = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y): sleep_cpu:cpu_domain_pd_allowed (noflash) - if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y: - sleep_mmu:mmu_domain_pd_allowed (noflash) esp_clk:esp_clk_slowclk_cal_set (noflash) esp_clk:esp_clk_slowclk_cal_get (noflash) esp_clk:esp_rtc_get_time_us (noflash) diff --git a/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.limits b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.limits index 2aec98155c..b0266392d9 100644 --- a/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.limits +++ b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.limits @@ -3,8 +3,6 @@ # Limit test esp_pm auto light sleep logic with faster ticks and faster code CONFIG_FREERTOS_HZ=1000 CONFIG_COMPILER_OPTIMIZATION_PERF=y -# Minimize the automatic light sleep entry threshold -CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP=2 # Enable PM options for automatic sleeping and DFS CONFIG_PM_DFS_INIT_AUTO=y diff --git a/components/esp_psram/CMakeLists.txt b/components/esp_psram/CMakeLists.txt index 0b7f4c961e..53e5f00d23 100644 --- a/components/esp_psram/CMakeLists.txt +++ b/components/esp_psram/CMakeLists.txt @@ -15,7 +15,7 @@ if(${target} STREQUAL "esp32") list(APPEND priv_requires bootloader_support esp_driver_spi esp_driver_gpio) endif() -set(srcs) +set(srcs "system_layer/esp_psram_mspi.c") if(CONFIG_SPIRAM) list(APPEND srcs "system_layer/esp_psram.c") diff --git a/components/esp_psram/include/esp_private/esp_psram_mspi.h b/components/esp_psram/include/esp_private/esp_psram_mspi.h new file mode 100644 index 0000000000..7610d99c14 --- /dev/null +++ b/components/esp_psram/include/esp_private/esp_psram_mspi.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "sdkconfig.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_PSRAM_MSPI_MB_WORKAROUND (CONFIG_IDF_TARGET_ESP32C5 && CONFIG_ESP32C5_REV_MIN_FULL < 102) || (CONFIG_IDF_TARGET_ESP32C61 && CONFIG_ESP32C61_REV_MIN_FULL < 101) + +/** + * @brief Initialize PSRAM MSPI memory barrier + * + * @return ESP_OK on success, otherwise an error code + */ +esp_err_t esp_psram_mspi_mb_init(void); + +/** + * @brief PSRAM MSPI memory barrier + */ +void esp_psram_mspi_mb(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_psram/system_layer/esp_psram.c b/components/esp_psram/system_layer/esp_psram.c index f236e03b96..8b0251e1e7 100644 --- a/components/esp_psram/system_layer/esp_psram.c +++ b/components/esp_psram/system_layer/esp_psram.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,11 +23,13 @@ #include "hal/mmu_hal.h" #include "hal/mmu_ll.h" #include "hal/cache_ll.h" +#include "hal/efuse_hal.h" #include "soc/soc_caps.h" #include "esp_private/esp_psram_io.h" #include "esp_private/esp_psram_extram.h" #include "esp_private/esp_mmu_map_private.h" #include "esp_private/esp_psram_impl.h" +#include "esp_private/esp_psram_mspi.h" #include "esp_private/startup_internal.h" #if SOC_SPIRAM_XIP_SUPPORTED #include "esp_private/mmu_psram_flash.h" @@ -113,24 +115,35 @@ static const DRAM_ATTR char TAG[] = "esp_psram"; ESP_SYSTEM_INIT_FN(add_psram_to_heap, CORE, BIT(0), 103) { + esp_err_t ret = ESP_FAIL; + #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) #if (CONFIG_IDF_TARGET_ESP32C5 && CONFIG_ESP32C5_REV_MIN_FULL <= 100) || (CONFIG_IDF_TARGET_ESP32C61 && CONFIG_ESP32C61_REV_MIN_FULL <= 100) - ESP_EARLY_LOGW(TAG, "Due to hardware issue on ESP32-C5/C61 (Rev v1.0), PSRAM contents won't be encrypted (for flash encryption enabled case)"); - ESP_EARLY_LOGW(TAG, "Please avoid using PSRAM for security sensitive data e.g., TLS stack allocations (CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC)"); + if (efuse_hal_chip_revision() <= 100) { + ESP_EARLY_LOGW(TAG, "Due to hardware issue on ESP32-C5/C61 (Rev v1.0), PSRAM contents won't be encrypted (for flash encryption enabled case)"); + ESP_EARLY_LOGW(TAG, "Please avoid using PSRAM for security sensitive data e.g., TLS stack allocations (CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC)"); + } #endif if (esp_psram_is_initialized()) { - esp_err_t r = esp_psram_extram_add_to_heap_allocator(); - if (r != ESP_OK) { + ret = esp_psram_extram_add_to_heap_allocator(); + if (ret != ESP_OK) { ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!"); - abort(); + return ret; } #if CONFIG_SPIRAM_USE_MALLOC heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif } #endif - return ESP_OK; + + ret = esp_psram_mspi_mb_init(); + if (ret != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to initialize PSRAM MSPI memory barrier!"); + return ret; + } + + return ret; } #if CONFIG_IDF_TARGET_ESP32 @@ -422,8 +435,10 @@ esp_err_t esp_psram_init(void) #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA #if (CONFIG_IDF_TARGET_ESP32C5 && CONFIG_ESP32C5_REV_MIN_FULL <= 100) || (CONFIG_IDF_TARGET_ESP32C61 && CONFIG_ESP32C61_REV_MIN_FULL <= 100) - ESP_EARLY_LOGW(TAG, "Due to hardware issue on ESP32-C5/C61 (Rev v1.0), PSRAM contents won't be encrypted (for flash encryption enabled case)"); - ESP_EARLY_LOGW(TAG, "Please avoid using PSRAM for execution as the code/rodata shall be copied as plaintext and this could pose a security risk."); + if (efuse_hal_chip_revision() <= 100) { + ESP_EARLY_LOGW(TAG, "Due to hardware issue on ESP32-C5/C61 (Rev v1.0), PSRAM contents won't be encrypted (for flash encryption enabled case)"); + ESP_EARLY_LOGW(TAG, "Please avoid using PSRAM for execution as the code/rodata shall be copied as plaintext and this could pose a security risk."); + } #endif s_xip_psram_placement(&psram_available_size, &start_page); #endif diff --git a/components/esp_psram/system_layer/esp_psram_mspi.c b/components/esp_psram/system_layer/esp_psram_mspi.c new file mode 100644 index 0000000000..cb62d14729 --- /dev/null +++ b/components/esp_psram/system_layer/esp_psram_mspi.c @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_intr_alloc.h" +#include "esp_cache.h" +#include "esp_heap_caps.h" +#include "esp_private/esp_psram_mspi.h" + +__attribute__((unused)) static DRAM_ATTR char TAG[] = "MSPI Timing"; + +#if ESP_PSRAM_MSPI_MB_WORKAROUND +static void *s_psram_mb_dummy_cacheline; //dummy cacheline for cache memory barrier +#endif + +esp_err_t esp_psram_mspi_mb_init(void) +{ +#if ESP_PSRAM_MSPI_MB_WORKAROUND + s_psram_mb_dummy_cacheline = heap_caps_calloc(1, CONFIG_CACHE_L1_CACHE_LINE_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_CACHE_ALIGNED); + if (!s_psram_mb_dummy_cacheline) { + ESP_EARLY_LOGE(TAG, "Failed to allocate dummy cacheline for PSRAM memory barrier!"); + } +#endif + + return ESP_OK; +} + +void IRAM_ATTR esp_psram_mspi_mb(void) +{ +#if ESP_PSRAM_MSPI_MB_WORKAROUND + if (s_psram_mb_dummy_cacheline) { + uint32_t *p = (uint32_t *)s_psram_mb_dummy_cacheline; + *p = (*p + 1) % UINT32_MAX; + __attribute__((unused)) esp_err_t ret = ESP_FAIL; + ret = esp_cache_msync(s_psram_mb_dummy_cacheline, sizeof(uint32_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); //malloc is aligned, no need to writeback all + assert(ret == ESP_OK); + asm volatile("fence"); + } +#endif +} diff --git a/components/esp_psram/test_apps/psram/pytest_psram.py b/components/esp_psram/test_apps/psram/pytest_psram.py index 2cf712373d..124446d4ba 100644 --- a/components/esp_psram/test_apps/psram/pytest_psram.py +++ b/components/esp_psram/test_apps/psram/pytest_psram.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 52f93375e9..9be2ca49b7 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -322,6 +322,9 @@ else() # Regular app build rom_linker_script("coexist") rom_linker_script("net80211") rom_linker_script("pp") + if(CONFIG_ESP32C5_REV_MIN_FULL GREATER_EQUAL 102) + rom_linker_script("eco3") + endif() elseif(target STREQUAL "esp32c61") # esp32c61.rom.api.ld has been split to several lds by components. # esp32c61.rom.api.ld is still reserved to map the APIs @@ -329,9 +332,11 @@ else() # Regular app build rom_linker_script("coexist") rom_linker_script("net80211") rom_linker_script("pp") + if(CONFIG_ESP32C61_REV_MIN_FULL GREATER_EQUAL 101) + rom_linker_script("eco4") + endif() endif() - if(CONFIG_ESP_ROM_HAS_NEWLIB AND NOT target STREQUAL "esp32" AND NOT target STREQUAL "esp32s2") # ESP32 and S2 are a bit different, keep them as special cases in the target specific include section if(CONFIG_ESP32P4_REV_MIN_300) # TODO: IDF-13410 diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.eco3.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.eco3.ld new file mode 100644 index 0000000000..3f4dee36f1 --- /dev/null +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.eco3.ld @@ -0,0 +1,405 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/*************************************** + eco3 fixed + ***************************************/ + +coex_core_timer_idx_get = 0x40000aec; +coex_status_get = 0x40000b0c; +ets_delay_us = 0x4000003c; +Cache_Set_IDROM_MMU_Size = 0x400006c4; + +//ieee80211_encap_esfbuf = 0x40000b60; +//ieee80211_set_tx_desc = 0x40000b70; +//sta_input = 0x40000bd4; +//sta_rx_eapol = 0x40000bd8; +//sta_reset_beacon_timeout = 0x40000bdc; + +hal_mac_tx_set_ppdu = 0x40000c0c; +ic_mac_deinit = 0x40000c78; +ic_mac_init = 0x40000c7c; +lmacTxFrame = 0x40000cd0; +lmacDisableTransmit = 0x40000cd4; +pm_check_state = 0x40000d48; +//pm_set_beacon_filter = 0x40000d6c; +//pm_is_in_wifi_slice_threshold = 0x40000d70; +pm_keep_alive = 0x40000d78; +pm_process_tim = 0x40000da8; +//pm_tbtt_process = 0x40000dbc; +//pm_tx_data_process = 0x40000dd8; +pm_twt_process = 0x40000de8; +//pm_mac_try_enable_modem_state = 0x40000dfc; +//pm_update_next_tbtt = 0x40000e04; +pm_clear_wakeup_signal = 0x40000e0c; +pm_mac_disable_tsf_tbtt_soc_wakeup = 0x40000e10; +//pm_mac_disable_tsf_tbtt_modem_wakeup = 0x40000e14; +pm_mac_enable_tsf_tbtt_soc_wakeup = 0x40000e18; +//pm_mac_enable_tsf_tbtt_modem_wakeup = 0x40000e1c; +//pm_mac_modem_params_rt_update = 0x40000e20; +ppMapTxQueue = 0x40000e64; +//ppProcTxSecFrame = 0x40000e68; +//ppProcessTxQ = 0x40000e70; +ppRxPkt = 0x40000e8c; +ppRxProtoProc = 0x40000e90; +//ppProcessLifeTime = 0x40000ee4; +//rcGetSched = 0x40000f40; +//wDev_ProcessRxSucData = 0x40000fe0; +esp_test_tx_process_complete = 0x40001030; +pm_get_tbtt_count = 0x4000151c; +pm_enable_max_idle_timer = 0x400015b8; +//pm_beacon_offset_check = 0x400015cc; +pm_beacon_offset_get_average = 0x400015d0; +pm_beacon_offset_get_expect = 0x400015d4; +pm_beacon_offset_get_params = 0x400015d8; + +phy_rate_to_index = 0x400010e8; +phy_get_target_pwr = 0x400010ec; +phy_get_max_pwr = 0x400010f0; +phy_get_pwr_index = 0x400010f4; +phy_get_rc_dout = 0x400010f8; +phy_rc_cal = 0x400010fc; +phy_abs_temp = 0x40001100; +phy_set_chan_interp = 0x40001104; +phy_loop_clk_en = 0x40001108; +phy_get_data_sat = 0x4000110c; +phy_byte_to_word = 0x40001110; +phy_bb_bss_cbw40 = 0x40001118; +phy_set_chan_reg = 0x4000111c; +phy_i2c_master_reset = 0x40001120; +phy_chan14_mic_enable = 0x40001124; +phy_chan14_mic_cfg = 0x40001128; +phy_set_most_tpw = 0x4000112c; +phy_get_most_tpw = 0x40001130; +phy_tx_state_out = 0x40001134; +phy_ant_dft_cfg = 0x40001138; +phy_ant_wifitx_cfg = 0x4000113c; +phy_ant_wifirx_cfg = 0x40001140; +phy_ant_bttx_cfg = 0x40001144; +phy_ant_btrx_cfg = 0x40001148; +//phy_chan_dump_cfg = 0x4000114c; +phy_chan_dump_cfg_752 = 0x40001150; +phy_enable_low_rate = 0x40001154; +phy_disable_low_rate = 0x40001158; +phy_is_low_rate_enabled = 0x4000115c; +phy_dig_reg_backup = 0x40001160; +phy_chan_filt_set = 0x40001164; +phy_rx11blr_cfg = 0x40001168; +phy_set_cca = 0x4000116c; +phy_set_rx_sense = 0x40001170; +phy_freq_module_resetn = 0x40001174; +phy_freq_chan_en_sw = 0x40001178; +phy_write_chan_freq = 0x4000117c; +phy_get_freq_mem_param = 0x40001180; +phy_get_freq_mem_addr = 0x40001184; +phy_wr_freq_mem = 0x40001188; +phy_read_rf_freq_mem = 0x4000118c; +phy_freq_i2c_mem_write = 0x40001190; +phy_freq_num_get_data = 0x40001194; +phy_freq_i2c_num_addr = 0x40001198; +phy_freq_i2c_write_set = 0x4000119c; +phy_en_hw_set_freq = 0x400011a4; +phy_dis_hw_set_freq = 0x400011a8; +phy_wait_freq_set_busy = 0x400011ac; +phy_i2c_enter_critical_ = 0x400011b0; +phy_i2c_exit_critical_ = 0x400011b4; +phy_i2c_clk_sel = 0x400011b8; +phy_get_i2c_read_mask_ = 0x400011bc; +phy_get_i2c_mst0_mask = 0x400011c0; +phy_get_i2c_hostid_ = 0x400011c4; +phy_chip_i2c_readReg_org = 0x400011c8; +phy_chip_i2c_readReg = 0x400011cc; +phy_i2c_paral_set_mst0 = 0x400011d0; +phy_i2c_paral_set_read = 0x400011d4; +phy_i2c_paral_read = 0x400011d8; +phy_i2c_paral_write = 0x400011dc; +phy_i2c_paral_write_num = 0x400011e0; +phy_i2c_paral_write_mask = 0x400011e4; +phy_i2c_readReg = 0x400011e8; +phy_chip_i2c_writeReg = 0x400011ec; +phy_i2c_writeReg = 0x400011f0; +phy_i2c_readReg_Mask = 0x400011f4; +phy_set_txcap_reg = 0x400011f8; +phy_i2c_sar2_init_code = 0x400011fc; +phy_i2c_pkdet_set = 0x40001200; +phy_filter_dcap_set = 0x40001204; +phy_i2c_rc_cal_set = 0x40001208; +phy_ckgen_5g_cal = 0x4000120c; +phy_ckgen_2g_cal = 0x40001210; +phy_adc_rate_set = 0x40001214; +phy_dac_rate_set = 0x40001218; +phy_encode_i2c_master = 0x4000121c; +phy_i2c_master_fill = 0x40001220; +phy_band_reg = 0x40001224; +phy_open_fe_bb_clk = 0x40001228; +phy_get_mac_addr = 0x4000122c; +phy_set_mac_data = 0x40001230; +phy_rfcal_data_sub = 0x40001234; +phy_rf_cal_data_recovery = 0x40001238; +phy_rf_cal_data_backup = 0x4000123c; +phy_rfcal_data_check = 0x40001240; +phy_pbus_force_mode = 0x40001244; +phy_pbus_force_test = 0x4000124c; +phy_pbus_rd = 0x40001250; +phy_pbus_debugmode = 0x40001254; +phy_pbus_workmode = 0x40001258; +phy_pbus_clear_reg = 0x4000125c; +phy_pbus_set_rxgain = 0x40001260; +phy_pbus_set_dco = 0x40001264; +phy_set_loopback_gain = 0x40001268; +phy_txcal_debuge_mode_ = 0x4000126c; +phy_txcal_work_mode = 0x40001270; +phy_write_pbus_mem = 0x40001274; +phy_set_pbus_mem_2g = 0x40001278; +phy_set_pbus_mem_5g = 0x4000127c; +phy_pbus_reg_store = 0x40001280; +phy_set_pbus_mem = 0x40001284; +phy_get_rx_pbus_freq = 0x40001288; +phy_set_rx_pbus_freq = 0x4000128c; +phy_pbus_xpd_iq_path = 0x40001290; +phy_pbus_set_rftx1_5g = 0x40001294; +phy_pwdet_reg_init = 0x40001298; +phy_pwdet_sar2_init = 0x4000129c; +phy_en_pwdet = 0x400012a0; +phy_get_sar_sig_ref = 0x400012a4; +phy_pwdet_tone_start = 0x400012a8; +phy_get_tone_sar_dout = 0x400012ac; +phy_get_fm_sar_dout = 0x400012b0; +phy_txtone_linear_pwr = 0x400012b4; +phy_linear_to_db = 0x400012b8; +phy_get_power_db = 0x400012bc; +phy_meas_tone_pwr_db = 0x400012c0; +phy_pwdet_wait_idle = 0x400012c4; +phy_pkdet_vol_start = 0x400012c8; +phy_read_sar_dout = 0x400012cc; +phy_read_sar2_code = 0x400012d0; +phy_get_sar2_vol = 0x400012d4; +phy_get_pkdet_data = 0x400012d8; +phy_rx_pkdet_dc_cal = 0x400012dc; +phy_disable_agc = 0x400012e0; +phy_enable_agc = 0x400012e4; +phy_disable_cca = 0x400012e8; +phy_enable_cca = 0x400012ec; +phy_write_gain_mem = 0x400012f0; +phy_bb_bss_cbw40_dig = 0x400012f4; +phy_tx_paon_set = 0x400012f8; +phy_i2cmst_reg_init = 0x400012fc; +phy_bt_gain_offset = 0x40001300; +phy_fe_reg_init = 0x40001304; +phy_mac_enable_bb = 0x40001308; +phy_bb_wdg_cfg = 0x4000130c; +phy_fe_txrx_reset = 0x40001310; +phy_set_rx_comp_ = 0x40001314; +phy_agc_max_gain_set = 0x40001318; +phy_agc_reg_init = 0x4000131c; +phy_bb_reg_init = 0x40001320; +phy_open_i2c_xpd = 0x40001324; +phy_force_txrx_off = 0x40001328; +phy_txiq_set_reg = 0x4000132c; +phy_rxiq_set_reg = 0x40001330; +phy_rx_gain_force = 0x40001334; +phy_set_txclk_en = 0x40001338; +phy_set_rxclk_en = 0x4000133c; +phy_start_tx_tone_step = 0x40001340; +phy_stop_tx_tone = 0x40001344; +phy_bb_wdg_test_en = 0x40001348; +phy_noise_floor_auto_set = 0x4000134c; +phy_read_hw_noisefloor = 0x40001350; +phy_iq_corr_enable = 0x40001354; +phy_wifi_agc_sat_gain = 0x40001358; +phy_bbpll_cal = 0x4000135c; +phy_ant_init = 0x40001360; +phy_wifi_fbw_sel = 0x40001364; +phy_bt_filter_reg = 0x40001368; +phy_rx_sense_set = 0x4000136c; +phy_tx_state_set = 0x40001370; +phy_close_pa = 0x40001374; +phy_freq_correct = 0x40001378; +phy_set_pbus_reg = 0x4000137c; +phy_wifi_rifs_mode_en = 0x40001380; +phy_rfagc_disable = 0x40001384; +phy_pkdadc_set = 0x40001388; +phy_nrx_freq_set = 0x4000138c; +phy_fe_adc_on = 0x40001390; +phy_force_pwr_index = 0x40001394; +phy_fft_scale_force = 0x40001398; +phy_force_rx_gain = 0x4000139c; +phy_wifi_enable_set = 0x400013a0; +phy_bb_cbw_chan_cfg = 0x400013a4; +phy_vht_support = 0x400013a8; +phy_csidump_force_lltf_cfg = 0x400013ac; +phy_hemu_ru26_good_res = 0x400013b0; +phy_bb_cfo_cfg = 0x400013b4; +phy_freq_band_reg_set = 0x400013b8; +phy_set_bb_wdg = 0x400013bc; +phy_sifs_reg_init = 0x400013c0; +phy_bbtx_outfilter = 0x400013c4; +phy_bb_wdt_rst_enable = 0x400013c8; +phy_bb_wdt_int_enable = 0x400013cc; +phy_bb_wdt_timeout_clear = 0x400013d0; +phy_bb_wdt_get_status = 0x400013d4; +phy_freq_to_chan = 0x400013d8; +phy_chan_to_freq = 0x400013dc; +phy_freq_to_index = 0x400013e0; +phy_iq_est_enable = 0x400013e4; +phy_iq_est_disable = 0x400013e8; +phy_dc_iq_est = 0x400013ec; +phy_set_cal_rxdc = 0x400013f0; +phy_rxiq_get_mis = 0x400013f4; +phy_rxiq_cover_mg_mp = 0x400013f8; +phy_rfcal_rxiq = 0x400013fc; +phy_get_rfcal_rxiq_data = 0x40001400; +phy_get_dco_comp = 0x40001404; +phy_pbus_rx_dco_cal = 0x40001408; +phy_rxdc_est_min = 0x4000140c; +phy_rx_dco_cal_1step = 0x40001410; +phy_set_lb_txiq = 0x40001414; +phy_rxiq_opt = 0x40001418; +phy_bb_gain_index = 0x40001430; +phy_rfrx_gain_index = 0x40001434; +phy_gen_rx_gain_table = 0x40001438; +phy_get_rxbb_dc = 0x4000143c; +phy_wr_rx_gain_mem = 0x40001440; +phy_set_tsens_power_ = 0x40001444; +phy_get_tsens_value_ = 0x40001448; +phy_tsens_read_init = 0x4000144c; +phy_code_to_temp = 0x40001450; +phy_tsens_dac_to_index = 0x40001454; +phy_tsens_dac_cal = 0x40001458; +phy_tsens_code_read = 0x4000145c; +phy_tsens_temp_read = 0x40001460; +phy_tsens_temp_read_local = 0x40001464; +phy_temp_to_power_ = 0x40001468; +phy_bt_txdc_cal = 0x4000146c; +phy_bt_txiq_cal = 0x40001470; +phy_txdc_cal = 0x40001474; +phy_txdc_cal_pwdet = 0x40001478; +phy_txiq_get_mis_pwr = 0x4000147c; +phy_txiq_cover = 0x40001480; +phy_rfcal_txiq = 0x40001484; +phy_get_power_atten = 0x40001488; +phy_pwdet_ref_code = 0x4000148c; +phy_pwdet_code_cal = 0x40001490; +phy_rfcal_txcap = 0x40001494; +phy_txcap_setting = 0x40001498; +phy_get_cal_chan = 0x4000149c; +phy_get_chan_cal_index = 0x400014a0; +phy_get_chan_cap = 0x400014a4; +phy_freq_to_mbgain = 0x400014a8; +phy_rfcal_pwrctrl = 0x400014ac; +phy_get_pwdet_offset_ = 0x400014b0; +phy_tx_pwctrl_init_cal = 0x400014b4; +phy_tx_pwctrl_init = 0x400014b8; +phy_bt_tx_pwctrl_init = 0x400014bc; +phy_txbbgain_to_index = 0x400014c0; +phy_index_to_txbbgain = 0x400014c4; +phy_bt_get_tx_gain = 0x400014c8; +phy_dig_gain_check = 0x400014cc; +phy_wifi_get_tx_gain = 0x400014d0; +phy_wifi_11g_rate_chg = 0x400014d4; +phy_set_tx_gain_mem = 0x400014dc; +phy_get_rate_fcc_index = 0x400014e0; +phy_get_chan_target_power = 0x400014e4; +phy_get_tx_gain_value = 0x400014e8; +phy_wifi_get_target_power = 0x400014ec; +phy_wifi_get_tx_tab_ = 0x400014f0; +phy_wifi_set_tx_gain = 0x400014f4; +phy_bt_get_tx_tab_ = 0x400014f8; +phy_bt_set_tx_gain = 0x400014fc; +phy_bt_tx_gain_init = 0x40001500; + +/*************************************** + eco3 newly added + ***************************************/ + +/* Data (.data, .bss, .rodata) */ +s_offchan_tx_progress_in_ptr = 0x4085fc5c; +s_phy_get_max_pwr_new_ptr = 0x4085fc58; + +/* Functions */ +phy_get_index_pwr = 0x400015dc; +phy_get_pwr_by_rate = 0x400015e0; +phy_set_adc_rand = 0x400015e4; +phy_get_interp_data = 0x400015e8; +phy_pbus_print = 0x400015ec; +phy_internal_delay = 0x400015f0; +phy_ftm_comp = 0x400015f4; +phy_11p_set = 0x400015f8; +phy_freq_mem_backup = 0x400015fc; +phy_get_cca = 0x40001600; +phy_set_cca_cnt = 0x40001604; +phy_get_cca_cnt = 0x40001608; +phy_get_noise_floor = 0x4000160c; +phy_get_rssi = 0x40001610; +phy_rxevm_reset_mem = 0x40001614; +phy_rxevm_init_cfg = 0x40001618; +phy_freq_reg_init = 0x4000161c; +phy_freq_mem_data = 0x40001620; +phy_set_freq_sw_start = 0x40001624; +phy_freq_mem_change_5g_ = 0x40001628; +phy_i2c_bbpll_set = 0x4000162c; +phy_i2c_master_mem_txcap = 0x40001630; +phy_get_xtal_code = 0x40001634; +phy_get_dcap_degen = 0x40001638; +phy_get_vco_init = 0x4000163c; +phy_get_tcode = 0x40001640; +phy_get_tm7 = 0x40001644; +phy_get_dreg_1p1 = 0x40001648; +phy_set_freq_i2c_ = 0x4000164c; +phy_tatget_pwr_band = 0x40001650; +phy_band_i2c_set = 0x40001654; +phy_band_change = 0x40001658; +phy_close_fe_bb_clk = 0x4000165c; +phy_reg_init = 0x40001660; +phy_xpd_rf = 0x40001664; +phy_pbus_rd_addr = 0x40001668; +phy_rx_loop_cap_set = 0x4000166c; +phy_pbus_xpd_dpd_path = 0x40001670; +phy_rx_filter_mode = 0x40001674; +phy_dac_scale_set = 0x40001678; +phy_bbpll_recal = 0x4000167c; +bb_agc_reg_update = 0x40001680; +phy_bb_dcmem_clr = 0x40001684; +phy_txgain_comp_pacfg = 0x40001688; +phy_i2c_txrate_init = 0x4000168c; +phy_iq_swap_set = 0x40001690; +phy_bb_fsm_rst = 0x40001694; +phy_lltf_mask_en = 0x40001698; +phy_magtrk_scale_set = 0x4000169c; +phy_cfg_tx_magtrk = 0x400016a0; +phy_tx_magtrk_init = 0x400016a4; +phy_restart_cal = 0x400016a8; +phy_reset_ckgen = 0x400016ac; +phy_write_rfpll_sdm = 0x400016b0; +phy_rfpll_set_freq = 0x400016b4; +phy_set_rf_freq_offset = 0x400016b8; +phy_i2c_sdm_en = 0x400016bc; +phy_freq_cal_test = 0x400016c0; +phy_set_rfpll_freq = 0x400016c4; +phy_set_channel_rfpll_freq_ = 0x400016c8; +phy_read_pll_cap = 0x400016cc; +//phy_set_chan_misc = 0x400016d0; +phy_chip_set_chan_offset = 0x400016d4; +phy_chip_set_chan_ana = 0x400016d8; +phy_freq_set_reg = 0x400016dc; +phy_rfrx_rxdc_cal = 0x400016e0; +phy_linear_to_db_64bits = 0x400016e4; +phy_get_iq_est_snr = 0x400016e8; +phy_get_loop_snr = 0x400016ec; +phy_get_rx_sig_pwr = 0x400016f0; +phy_adc_rate_cal_rxdc = 0x400016f4; +phy_set_iqcal_ckgen_code = 0x400016f8; +phy_dpd_rxdc_cal = 0x400016fc; +phy_txpwr_correct = 0x40001700; +phy_txpwr_cal_track = 0x40001704; +phy_bt_track_tx_power = 0x40001708; +phy_wifi_track_tx_power = 0x4000170c; +phy_txpwr_track_slow = 0x40001710; +phy_set_tsens_pwr = 0x40001714; +phy_bt_tx_gain_set = 0x40001718; +phy_get_chan_power_offset = 0x4000171c; +phy_chan_vs_index = 0x40001720; +phy_get_txiq_dcode_offset_ = 0x40001724; +phy_get_txiq_set = 0x40001728; diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld index b83061f0c5..59cea29841 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.net80211.ld @@ -32,7 +32,7 @@ ic_ebuf_recycle_rx = 0x40000b40; ic_ebuf_recycle_tx = 0x40000b44; ic_reset_rx_ba = 0x40000b48; ic_ebuf_alloc = 0x40000b4c; -ic_reset_extra_softap_rx_ba = 0x40000b50; +//ic_reset_extra_softap_rx_ba = 0x40000b50; ieee80211_align_eb = 0x40000b54; ieee80211_ampdu_reorder = 0x40000b58; ieee80211_ampdu_start_age_timer = 0x40000b5c; @@ -68,7 +68,7 @@ wifi_is_started = 0x40000bd0; /*sta_input = 0x40000bd4;*/ //sta_rx_eapol = 0x40000bd8; //sta_reset_beacon_timeout = 0x40000bdc; -sta_get_beacon_timeout = 0x40000be0; +//sta_get_beacon_timeout = 0x40000be0; ampdu_process_multicast_address_qos_frame = 0x40000be4; /* Data (.data, .bss, .rodata) */ net80211_funcs = 0x4085ffac; diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld index 53079241dd..64e04af8d7 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.pp.ld @@ -117,7 +117,7 @@ pm_local_tsf_process = 0x40000d68; /*pm_is_in_wifi_slice_threshold = 0x40000d70;*/ pm_is_waked = 0x40000d74; /*pm_keep_alive = 0x40000d78;*/ -pm_on_beacon_rx = 0x40000d7c; +//pm_on_beacon_rx = 0x40000d7c; pm_on_data_rx = 0x40000d80; pm_on_data_tx = 0x40000d84; pm_on_tbtt = 0x40000d88; @@ -127,9 +127,9 @@ pm_on_isr_set_twt_target = 0x40000d94; pm_on_isr_twt_wake = 0x40000d98; pm_on_tsf_timer = 0x40000d9c; pm_on_twt_force_tx = 0x40000da0; -pm_parse_beacon = 0x40000da4; +//pm_parse_beacon = 0x40000da4; /*pm_process_tim = 0x40000da8;*/ -pm_rx_beacon_process = 0x40000dac; +//pm_rx_beacon_process = 0x40000dac; pm_rx_data_process = 0x40000db0; pm_sleep = 0x40000db4; pm_sleep_for = 0x40000db8; @@ -204,7 +204,7 @@ ppProcTxDone = 0x40000ec8; ppMapWaitTxq = 0x40000ecc; ppProcessWaitingQueue = 0x40000ed0; ppDisableQueue = 0x40000ed4; -ppCalVHTDeliNum = 0x40000ed8; +//ppCalVHTDeliNum = 0x40000ed8; ppCalTxVHTSMPDULength = 0x40000edc; ppCheckTxRTS = 0x40000ee0; /*ppProcessLifeTime = 0x40000ee4;*/ diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.eco4.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.eco4.ld new file mode 100644 index 0000000000..18937e41a7 --- /dev/null +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.eco4.ld @@ -0,0 +1,370 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/*************************************** + eco4 fixed + ***************************************/ + +coex_core_timer_idx_get = 0x40000a54; +coex_status_get = 0x40000a74; +ets_delay_us = 0x4000003c; + +ieee80211_encap_esfbuf = 0x40000ac8; +ieee80211_set_tx_desc = 0x40000ad8; +sta_input = 0x40000b3c; +//sta_rx_eapol = 0x40000b40; +//sta_reset_beacon_timeout = 0x40000b44; +hal_mac_tx_set_ppdu = 0x40000b74; +ic_mac_deinit = 0x40000be8; +ic_mac_init = 0x40000bec; +lmacTxFrame = 0x40000c40; +lmacDisableTransmit = 0x40000c44; +pm_check_state = 0x40000cb4; +pm_set_beacon_filter = 0x40000cd8; +//pm_is_in_wifi_slice_threshold = 0x40000cdc; +pm_keep_alive = 0x40000ce4; +pm_process_tim = 0x40000d14; +pm_tbtt_process = 0x40000d28; +pm_tx_data_process = 0x40000d44; +pm_twt_process = 0x40000d54; +pm_mac_try_enable_modem_state = 0x40000d68; +//pm_update_next_tbtt = 0x40000d70; +pm_clear_wakeup_signal = 0x40000d78; +pm_mac_disable_tsf_tbtt_soc_wakeup = 0x40000d7c; +pm_mac_disable_tsf_tbtt_modem_wakeup = 0x40000d80; +pm_mac_enable_tsf_tbtt_soc_wakeup = 0x40000d84; +pm_mac_enable_tsf_tbtt_modem_wakeup = 0x40000d88; +//pm_mac_modem_params_rt_update = 0x40000d8c; +pm_coex_pwr_update = 0x40000d9c; +ppMapTxQueue = 0x40000ddc; +ppProcTxSecFrame = 0x40000de0; +ppProcessTxQ = 0x40000de8; +ppRxPkt = 0x40000e04; +ppRxProtoProc = 0x40000e08; +//ppProcessLifeTime = 0x40000e54; +rcGetSched = 0x40000eb4; +//wDev_ProcessRxSucData = 0x40000f54; +pm_get_tbtt_count = 0x400014c8; +pm_beacon_offset_check = 0x40001564; +pm_beacon_offset_get_average = 0x40001568; +pm_beacon_offset_get_expect = 0x4000156c; +pm_beacon_offset_get_params = 0x40001570; +pm_enable_max_idle_timer = 0x40001578; + +phy_get_rc_dout = 0x40001058; +phy_rc_cal = 0x4000105c; +phy_abs_temp = 0x40001060; +phy_set_chan_cal_interp = 0x40001064; +phy_loopback_mode_en = 0x40001068; +phy_get_data_sat = 0x4000106c; +phy_byte_to_word = 0x40001070; +phy_bb_bss_cbw40 = 0x40001074; +phy_set_chan_reg = 0x40001078; +phy_i2c_master_reset = 0x4000107c; +phy_chan14_mic_enable = 0x40001080; +phy_chan14_mic_cfg = 0x40001084; +phy_freq_module_resetn = 0x40001088; +phy_freq_chan_en_sw = 0x4000108c; +phy_write_chan_freq = 0x40001090; +phy_get_freq_mem_param = 0x40001094; +phy_get_freq_mem_addr = 0x40001098; +phy_wr_rf_freq_mem = 0x4000109c; +phy_read_rf_freq_mem = 0x400010a0; +phy_freq_i2c_mem_write = 0x400010a4; +phy_freq_reg_init = 0x400010a8; +phy_freq_num_get_data = 0x400010ac; +phy_freq_i2c_num_addr = 0x400010b0; +phy_freq_i2c_write_set = 0x400010b4; +phy_pll_dac_mem_update = 0x400010b8; +phy_pll_cap_mem_update = 0x400010bc; +phy_en_hw_set_freq = 0x400010d4; +phy_dis_hw_set_freq = 0x400010d8; +phy_wait_freq_set_busy = 0x400010dc; +phy_set_chan_freq_sw_start = 0x400010e0; +phy_wait_i2c_sdm_stable = 0x400010e4; +phy_reg_init = 0x400010e8; +phy_xpd_rf = 0x400010ec; +phy_get_mac_addr = 0x400010f4; +phy_set_mac_data = 0x400010f8; +phy_rfcal_data_sub = 0x400010fc; +phy_rf_cal_data_recovery = 0x40001100; +phy_rf_cal_data_backup = 0x40001104; +phy_rfcal_data_check = 0x40001108; +phy_pwdet_reg_init = 0x4000110c; +phy_pwdet_sar2_init = 0x40001110; +phy_en_pwdet = 0x40001114; +phy_get_sar_sig_ref = 0x40001118; +phy_pwdet_tone_start = 0x4000111c; +phy_get_tone_sar_dout = 0x40001120; +phy_get_fm_sar_dout = 0x40001124; +phy_txtone_linear_pwr = 0x40001128; +phy_linear_to_db = 0x4000112c; +phy_get_power_db = 0x40001130; +phy_meas_tone_pwr_db = 0x40001134; +phy_pwdet_wait_idle = 0x40001138; +phy_pkdet_vol_start = 0x4000113c; +phy_read_sar_dout = 0x40001140; +phy_read_sar2_code = 0x40001144; +phy_get_sar2_vol = 0x40001148; +phy_get_pll_vol = 0x4000114c; +phy_tx_pwctrl_bg_init = 0x40001150; +phy_set_most_tpw = 0x40001154; +phy_get_most_tpw = 0x40001158; +phy_tx_state_out = 0x4000115c; +phy_ant_dft_cfg = 0x40001160; +phy_ant_wifitx_cfg = 0x40001164; +phy_ant_wifirx_cfg = 0x40001168; +phy_ant_bttx_cfg = 0x4000116c; +phy_ant_btrx_cfg = 0x40001170; +//phy_chan_dump_cfg = 0x40001174; +phy_enable_low_rate = 0x40001178; +phy_disable_low_rate = 0x4000117c; +phy_is_low_rate_enabled = 0x40001180; +phy_dig_reg_backup = 0x40001184; +phy_chan_filt_set = 0x40001188; +phy_rx11blr_cfg = 0x4000118c; +phy_set_cca = 0x40001190; +phy_set_rx_sense = 0x40001194; +phy_rx_gain_force = 0x40001198; +phy_mhz2ieee = 0x4000119c; +phy_chan_to_freq = 0x400011a0; +phy_restart_cal = 0x400011a4; +phy_write_rfpll_sdm = 0x400011a8; +phy_wait_rfpll_cal_end = 0x400011ac; +phy_rfpll_set_freq = 0x400011b0; +phy_set_rf_freq_offset = 0x400011b4; +phy_set_rfpll_freq = 0x400011b8; +phy_set_channel_rfpll_freq = 0x400011bc; +phy_rfpll_cap_correct = 0x400011c0; +phy_rfpll_cap_init_cal = 0x400011c4; +phy_set_freq = 0x400011c8; +phy_write_pll_cap = 0x400011cc; +phy_read_pll_cap = 0x400011d0; +phy_chip_set_chan_misc = 0x400011d4; +phy_freq_set_reg = 0x400011d8; +phy_rfpll_chgp_cal = 0x400011dc; +phy_gen_rx_gain_table = 0x400011e0; +phy_get_rxbb_dc = 0x400011e4; +phy_wr_rx_gain_mem = 0x400011e8; +phy_rfpll_cap_track = 0x400011ec; +phy_txpwr_correct = 0x400011f4; +phy_txpwr_cal_track = 0x400011f8; +phy_bt_track_tx_power = 0x400011fc; +phy_wifi_track_tx_power = 0x40001200; +phy_bt_txdc_cal = 0x40001204; +phy_bt_txiq_cal = 0x40001208; +phy_txdc_cal_pwdet = 0x4000120c; +phy_txdc_cal = 0x40001210; +phy_txiq_get_mis_pwr = 0x40001214; +phy_txiq_cover = 0x40001218; +phy_rfcal_txiq = 0x4000121c; +phy_get_power_atten = 0x40001220; +phy_pwdet_ref_code = 0x40001224; +phy_pwdet_code_cal = 0x40001228; +phy_rfcal_txcap = 0x4000122c; +phy_rfcal_pwrctrl = 0x40001234; +phy_tx_pwctrl_init_cal = 0x40001238; +phy_i2c_enter_critical_ = 0x40001244; +phy_i2c_exit_critical_ = 0x40001248; +phy_i2c_clk_sel = 0x4000124c; +phy_get_i2c_read_mask_ = 0x40001250; +phy_get_i2c_mst0_mask = 0x40001254; +phy_get_i2c_hostid_ = 0x40001258; +phy_chip_i2c_readReg_org = 0x4000125c; +phy_chip_i2c_readReg = 0x40001260; +phy_i2c_paral_set_mst0 = 0x40001264; +phy_i2c_paral_set_read = 0x40001268; +phy_i2c_paral_read = 0x4000126c; +phy_i2c_paral_write = 0x40001270; +phy_i2c_paral_write_num = 0x40001274; +phy_i2c_paral_write_mask = 0x40001278; +phy_i2c_readReg = 0x4000127c; +phy_chip_i2c_writeReg = 0x40001280; +phy_i2c_writeReg = 0x40001284; +phy_i2c_readReg_Mask = 0x40001288; +phy_i2c_writeReg_Mask = 0x4000128c; +phy_set_txcap_reg = 0x40001290; +phy_i2c_sar2_init_code = 0x40001294; +phy_filter_dcap_set = 0x4000129c; +phy_i2c_rc_cal_set = 0x400012ac; +phy_i2c_bbpll_set = 0x400012b0; +phy_adc_rate_set = 0x400012b4; +phy_dac_rate_set = 0x400012b8; +phy_encode_i2c_master = 0x400012bc; +phy_i2c_master_fill = 0x400012c0; +phy_i2c_master_mem_txcap = 0x400012c4; +phy_pbus_force_mode = 0x400012d0; +phy_pbus_rd_addr = 0x400012d4; +phy_pbus_rd_shift = 0x400012d8; +phy_pbus_force_test = 0x400012dc; +phy_pbus_rd = 0x400012e0; +phy_pbus_debugmode = 0x400012e4; +phy_pbus_workmode = 0x400012e8; +phy_pbus_set_rxgain = 0x400012ec; +phy_pbus_xpd_rx_off = 0x400012f0; +phy_pbus_xpd_rx_on = 0x400012f4; +phy_pbus_xpd_tx_off = 0x400012f8; +phy_pbus_xpd_tx_on = 0x400012fc; +phy_pbus_set_dco = 0x40001300; +phy_set_loopback_gain = 0x40001304; +phy_txcal_debuge_mode_ = 0x40001308; +phy_txcal_work_mode = 0x4000130c; +phy_pbus_clear_reg = 0x40001310; +phy_save_pbus_reg = 0x40001314; +phy_write_pbus_mem = 0x40001318; +phy_set_pbus_mem = 0x4000131c; +phy_disable_agc = 0x40001320; +phy_enable_agc = 0x40001324; +phy_disable_cca = 0x40001328; +phy_enable_cca = 0x4000132c; +phy_write_gain_mem = 0x40001330; +phy_bb_bss_cbw40_dig = 0x40001334; +phy_mac_tx_chan_offset = 0x40001338; +phy_rx_11b_opt = 0x4000133c; +phy_tx_paon_set = 0x40001340; +phy_i2cmst_reg_init = 0x40001344; +phy_bt_gain_offset = 0x40001348; +phy_fe_reg_init = 0x4000134c; +phy_mac_enable_bb = 0x40001350; +phy_bb_wdg_cfg = 0x40001354; +phy_fe_txrx_reset = 0x40001358; +phy_set_rx_comp_ = 0x4000135c; +phy_agc_reg_init = 0x40001360; +phy_btbb_wifi_bb_cfg2 = 0x40001364; +phy_bb_reg_init = 0x40001368; +phy_open_i2c_xpd = 0x4000136c; +phy_force_txrx_off = 0x40001370; +phy_txiq_set_reg = 0x40001374; +phy_rxiq_set_reg = 0x40001378; +phy_set_txclk_en = 0x4000137c; +phy_set_rxclk_en = 0x40001380; +phy_start_tx_tone_step = 0x40001384; +phy_stop_tx_tone = 0x40001388; +phy_bb_wdg_test_en = 0x4000138c; +phy_noise_floor_auto_set = 0x40001390; +phy_read_hw_noisefloor = 0x40001394; +phy_iq_corr_enable = 0x40001398; +phy_wifi_agc_sat_gain = 0x4000139c; +phy_bbpll_cal = 0x400013a0; +phy_ant_init = 0x400013a4; +phy_wifi_fbw_sel = 0x400013a8; +phy_bt_filter_reg = 0x400013ac; +phy_rx_sense_set = 0x400013b0; +phy_tx_state_set = 0x400013b4; +phy_close_pa = 0x400013b8; +phy_freq_correct = 0x400013bc; +phy_set_pbus_reg = 0x400013c0; +phy_wifi_rifs_mode_en = 0x400013c4; +phy_nrx_freq_set = 0x400013c8; +phy_fe_adc_on = 0x400013cc; +phy_force_pwr_index = 0x400013d0; +phy_fft_scale_force = 0x400013d4; +phy_force_rx_gain = 0x400013d8; +phy_wifi_enable_set = 0x400013dc; +phy_bb_wdt_rst_enable = 0x400013e0; +phy_bb_wdt_int_enable = 0x400013e4; +phy_bb_wdt_timeout_clear = 0x400013e8; +phy_bb_wdt_get_status = 0x400013ec; +phy_iq_est_enable = 0x400013f0; +phy_iq_est_disable = 0x400013f4; +phy_dc_iq_est = 0x400013f8; +phy_set_cal_rxdc = 0x400013fc; +phy_rxiq_get_mis = 0x40001400; +phy_rxiq_cover_mg_mp = 0x40001404; +phy_rfcal_rxiq = 0x40001408; +phy_get_rfcal_rxiq_data = 0x4000140c; +phy_get_dco_comp = 0x40001410; +phy_pbus_rx_dco_cal = 0x40001414; +phy_rxdc_est_min = 0x40001418; +phy_pbus_rx_dco_cal_1step = 0x4000141c; +phy_get_iq_value = 0x40001420; +phy_set_lb_txiq = 0x40001424; +phy_set_rx_gain_cal_iq = 0x40001428; +phy_set_rx_gain_cal_dc = 0x4000142c; +phy_spur_reg_write_one_tone = 0x40001430; +phy_spur_cal = 0x40001434; +phy_spur_coef_cfg = 0x40001438; +phy_bb_gain_index = 0x4000143c; +phy_rfrx_gain_index = 0x40001440; +phy_set_tsens_power_ = 0x40001444; +phy_set_tsens_range_ = 0x40001448; +phy_get_tsens_value_ = 0x4000144c; +phy_tsens_read_init = 0x40001450; +phy_code_to_temp = 0x40001454; +phy_tsens_dac_to_index = 0x40001458; +phy_tsens_dac_cal = 0x4000145c; +phy_tsens_code_read = 0x40001460; +phy_tsens_temp_read = 0x40001464; +phy_tsens_temp_read_local = 0x40001468; +phy_temp_to_power = 0x4000146c; +phy_txbbgain_to_index = 0x40001470; +phy_index_to_txbbgain = 0x40001474; +phy_bt_index_to_bb = 0x40001478; +phy_bt_bb_to_index = 0x4000147c; +phy_bt_get_tx_gain = 0x40001480; +phy_dig_gain_check = 0x40001484; +phy_wifi_get_tx_gain = 0x40001488; +phy_wifi_11g_rate_chg = 0x4000148c; +phy_set_tx_gain_mem = 0x40001490; +phy_get_rate_fcc_index = 0x40001494; +phy_get_chan_target_power = 0x40001498; +phy_get_tx_gain_value = 0x4000149c; +phy_wifi_get_target_power = 0x400014a0; +phy_wifi_get_tx_tab_ = 0x400014a4; +phy_wifi_set_tx_gain = 0x400014a8; +phy_bt_get_tx_tab_ = 0x400014ac; +phy_bt_set_tx_gain = 0x400014b0; +phy_rate_to_index = 0x400014b8; +phy_get_target_pwr = 0x400014bc; +phy_get_max_pwr = 0x400014c0; +phy_get_pwr_index = 0x400014c4; +phy_chip_set_chan_ana = 0x400014d4; +phy_get_romfuncs = 0x400014d8; + +/*************************************** + eco4 newly added + ***************************************/ + +/* Data (.data, .bss, .rodata) */ +s_offchan_tx_progress_in_ptr = 0x4084fc5c; + + +/* Functions */ +phy_bb_agc_reg_update = 0x4000157c; +phy_bb_cbw_chan_cfg = 0x40001580; +phy_bb_cfo_cfg = 0x40001584; +phy_bb_dcmem_clr = 0x40001588; +phy_bbpll_recal = 0x4000158c; +phy_bbtx_outfilter = 0x40001590; +phy_csidump_force_lltf_cfg = 0x40001594; +phy_dac_scale_set = 0x40001598; +phy_dcode_cal_init = 0x4000159c; +phy_fe_reg_update = 0x400015a0; +phy_freq_band_reg_set = 0x400015a4; +phy_get_cca = 0x400015a8; +phy_get_cca_cnt = 0x400015ac; +phy_get_dreg1p6 = 0x400015b0; +phy_get_noise_floor = 0x400015b4; +phy_get_oc_dr1 = 0x400015b8; +phy_get_rssi = 0x400015bc; +phy_get_rx_sig_pwr = 0x400015c0; +phy_get_txiq_set = 0x400015c4; +phy_get_xtal_duty = 0x400015c8; +phy_hemu_ru26_good_res = 0x400015cc; +phy_i2c_txrate_init = 0x400015d0; +phy_lltf_mask_en = 0x400015d4; +phy_open_fe_bb_clk = 0x400015d8; +phy_reset_ckgen = 0x400015dc; +phy_rx_filter_mode = 0x400015e0; +phy_set_bb_wdg = 0x400015e4; +phy_set_cca_cnt = 0x400015e8; +phy_set_channel_dcode = 0x400015ec; +phy_set_ext_dcode = 0x400015f0; +phy_set_freq_i2c_ = 0x400015f4; +phy_sifs_reg_init = 0x400015f8; +phy_txgain_comp_pacfg = 0x400015fc; +phy_txpwr_track_slow = 0x40001600; +phy_vht_support = 0x40001604; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld index 4abb61d6e5..90100d3705 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.net80211.ld @@ -28,7 +28,7 @@ ic_ebuf_recycle_rx = 0x40000aa8; ic_ebuf_recycle_tx = 0x40000aac; ic_reset_rx_ba = 0x40000ab0; ic_ebuf_alloc = 0x40000ab4; -ic_reset_extra_softap_rx_ba = 0x40000ab8; +//ic_reset_extra_softap_rx_ba = 0x40000ab8; ieee80211_align_eb = 0x40000abc; ieee80211_ampdu_reorder = 0x40000ac0; ieee80211_ampdu_start_age_timer = 0x40000ac4; @@ -64,7 +64,7 @@ wifi_is_started = 0x40000b38; /*sta_input = 0x40000b3c;*/ //sta_rx_eapol = 0x40000b40; //sta_reset_beacon_timeout = 0x40000b44; -sta_get_beacon_timeout = 0x40000b48; +//sta_get_beacon_timeout = 0x40000b48; ampdu_process_multicast_address_qos_frame = 0x40000b4c; /* Data (.data, .bss, .rodata) */ net80211_funcs = 0x4084ffac; diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index c6649ba3a6..f293976428 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -205,7 +205,8 @@ SECTIONS */ .dram0.dummy (NOLOAD): { - . = ORIGIN(dram0_0_seg) + MAX(_iram_end - _diram_i_start, 0); + /* MAX() uses unsigned long arithmetic. Add offset to prevent underflow when _iram_end < _diram_i_start */ + . = ORIGIN(dram0_0_seg) + MAX(_iram_end - _diram_i_start + (_diram_i_start - ORIGIN(iram0_0_seg)), (_diram_i_start - ORIGIN(iram0_0_seg))) - (_diram_i_start - ORIGIN(iram0_0_seg)); } > dram0_0_seg .dram0.data : diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 5e1b1c308c..aa667391b5 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -87,7 +87,6 @@ SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/p SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c on BIT(0) SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c on BIT(0) SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) -SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c on BIT(0) # app_trace has to be initialized before systemview SECONDARY: 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index 54b8442b3d..1097c23fc6 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -323,7 +323,7 @@ static void test_psram_accessible_after_lightsleep(void) esp_light_sleep_start(); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !SOC_PM_TOP_PD_NOT_ALLOWED +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP); TEST_ESP_OK(sleep_cpu_configure(false)); #endif diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c index 03129592a5..c8dbbc15a1 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -64,19 +64,11 @@ TEST_CASE("Task WDT task timeout after peripheral powerdown lightsleep", "[task_ TEST_ESP_OK(sleep_cpu_configure(true)); esp_sleep_context_t sleep_ctx; esp_sleep_set_sleep_context(&sleep_ctx); -#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD - /* There is a bug that PD TOP will reset mmu table, so we add mmu table retention during sleep, - and it will increase time overhead before entering sleep */ - esp_sleep_enable_timer_wakeup(100 * 1000); -#else esp_sleep_enable_timer_wakeup(10 * 1000); -#endif esp_light_sleep_start(); -#if !SOC_PM_TOP_PD_NOT_ALLOWED TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP); -#endif TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); esp_sleep_set_sleep_context(NULL); diff --git a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py index 3d0d92f227..ecae9e65f7 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py +++ b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py @@ -1,16 +1,17 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @idf_parametrize( 'config,target', [ - ('default', 'supported_targets'), - ('pd_vddsdio', 'supported_targets'), + *(('default', target) for target in soc_filtered_targets('IDF_TARGET not in ["esp32c5"]')), + *(('pd_vddsdio', target) for target in soc_filtered_targets('IDF_TARGET not in ["esp32c5"]')), ('psram', 'esp32'), ('psram', 'esp32p4'), ('psram', 'esp32s2'), @@ -25,6 +26,35 @@ def test_esp_system(dut: Dut) -> None: dut.run_all_single_board_cases(timeout=60) +@pytest.mark.generic +@idf_parametrize( + 'config', + [ + 'pd_vddsdio', + 'psram', + ], + indirect=['config'], +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_esp_system_esp32c5(dut: Dut) -> None: + dut.run_all_single_board_cases(timeout=60) + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@idf_parametrize( + 'config', + [ + 'default', + 'psram_with_pd_top', + ], + indirect=['config'], +) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_esp_system_esp32c5_eco3(dut: Dut) -> None: + dut.run_all_single_board_cases(timeout=60) + + @pytest.mark.generic @idf_parametrize('config', ['default'], indirect=['config']) @idf_parametrize('target', ['supported_targets'], indirect=['target']) diff --git a/components/esp_wifi/CMakeLists.txt b/components/esp_wifi/CMakeLists.txt index 2cd6ec22e2..e20f4cd9e0 100644 --- a/components/esp_wifi/CMakeLists.txt +++ b/components/esp_wifi/CMakeLists.txt @@ -63,7 +63,7 @@ idf_component_register(SRCS "${srcs}" PRIV_REQUIRES esptool_py esp_pm esp_timer nvs_flash wpa_supplicant hal lwip esp_coex PRIV_INCLUDE_DIRS ../wpa_supplicant/src/ ../wpa_supplicant/esp_supplicant/src/ - wifi_apps/roaming_app/include + wifi_apps/roaming_app/include wifi_apps/roaming_app/src LDFRAGMENTS "${ldfragments}") if(CONFIG_ESP_WIFI_ENABLED OR CONFIG_ESP_HOST_WIFI_ENABLED) diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 01d52d9e69..156aed2cb6 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 01d52d9e69032c486015dc28b08c3bf6aaf348a9 +Subproject commit 156aed2cb6e6c9987dc2e7402fee907158cdf885 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index d1c298b2ff..0461280d5a 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -198,10 +198,6 @@ static esp_err_t wifi_deinit_internal(void) esp_supplicant_deinit(); -#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP - roam_deinit_app(); -#endif - #if CONFIG_ESP_WIFI_SLP_SAMPLE_BEACON_FEATURE wifi_beacon_offset_config_t offset_config = WIFI_BEACON_OFFSET_CONFIG_DEFAULT(false); esp_wifi_beacon_offset_configure(&offset_config); @@ -471,10 +467,6 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) goto _deinit; } -#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP - roam_init_app(); -#endif - } else { goto _deinit; } @@ -717,6 +709,24 @@ void nan_ndp_resp_timeout_process(void *p) } #endif /* CONFIG_ESP_WIFI_NAN_ENABLE */ +#if CONFIG_IDF_TARGET_ESP32C5 +#if CONFIG_ESP32C5_REV_MIN_FULL <= 100 +void esp32c5_eco3_rom_ptr_init(void) +{ + /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */ +} +#endif +#endif + +#if CONFIG_IDF_TARGET_ESP32C61 +#if CONFIG_ESP32C61_REV_MIN_FULL <= 100 +void esp32c61_eco4_rom_ptr_init(void) +{ + /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */ +} +#endif +#endif + #if CONFIG_IDF_TARGET_ESP32C2 #if CONFIG_ESP32C2_REV_MIN_FULL < 200 void esp32c2_eco4_rom_ptr_init(void) diff --git a/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h b/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h index 6ed20ce949..28ccb7a79e 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h +++ b/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h @@ -16,9 +16,11 @@ struct roam_config { int8_t low_rssi_threshold; uint8_t rssi_threshold_reduction_offset; bool scan_monitor; +#if CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR uint8_t scan_interval; int8_t scan_rssi_threshold; uint8_t scan_rssi_diff; +#endif bool legacy_roam_enabled; uint8_t btm_retry_cnt; bool btm_roaming_enabled; @@ -37,6 +39,10 @@ void roam_sta_disconnected(void *disconn); esp_err_t roam_get_config_params(struct roam_config *config); esp_err_t roam_set_config_params(struct roam_config *config); +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP +void esp_wifi_roaming_set_current_bssid(const uint8_t *bssid); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming b/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming index 22f641377d..57bc23649a 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming +++ b/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming @@ -73,7 +73,7 @@ menu "Roaming Methods" config ESP_WIFI_ROAMING_NETWORK_ASSISTED_ROAM bool "Support Network Assisted roaming using 802.11v" depends on ESP_WIFI_WNM_SUPPORT - default n + default y help Roaming between APs using network assisted Roaming. This involves BSS Transition Management mechanisms outlined in 802.11v. @@ -139,13 +139,7 @@ menu "Scan Configuration" Duration for which the results from the most recent scans can be used by the roaming app for determining the roaming candidates. - config ESP_WIFI_ROAMING_MAX_CANDIDATES - int "Max Candidates in the network" - default 3 - range 3 20 - help - Max candidates that can be considered while scanning as a part of the - network at one time. + endmenu #"Scan Configuration" @@ -160,7 +154,7 @@ config ESP_WIFI_ROAMING_BACKOFF_TIME config ESP_WIFI_ROAMING_PERIODIC_RRM_MONITORING bool "Send periodic neighbor report request to AP for internal list updation" depends on ESP_WIFI_RRM_SUPPORT - default y + default n help This option will enable station to keep sending RRM neighbor list request to AP and update its internal list. @@ -182,3 +176,50 @@ config ESP_WIFI_ROAMING_RRM_MONITOR_THRESHOLD range -99 0 help The RSSI threshold beyond which we start sending periodic neighbor report requests. + +menu "Blacklist Configuration" + config ESP_WIFI_ROAMING_BSSID_BLACKLIST + bool "Enable BSSID blacklisting" + default n + help + Enable this to blacklist BSSIDs. + + config ESP_WIFI_ROAMING_AUTO_BLACKLISTING + bool "Enable automatic BSSID blacklisting" + depends on ESP_WIFI_ROAMING_BSSID_BLACKLIST + help + Enable this to automatically blacklist BSSIDs after multiple failed connection attempts. + + config ESP_WIFI_ROAMING_MAX_CONN_FAILURES + int "Maximum connection failures" + depends on ESP_WIFI_ROAMING_AUTO_BLACKLISTING + range 1 10 + default 3 + help + Maximum number of connection failures before a BSSID is blacklisted. + + config ESP_WIFI_ROAMING_BLACKLIST_TIMEOUT + int "Blacklist timeout (in seconds)" + depends on ESP_WIFI_ROAMING_BSSID_BLACKLIST + range 10 3600 + default 300 + help + Time in seconds for which a BSSID remains in the blacklist. + This applies to both automatically and manually blacklisted BSSIDs. + + config ESP_WIFI_ROAMING_MAX_CANDIDATES + int "Maximum number of roaming candidates" + range 1 10 + default 5 + help + Maximum number of roaming candidates to consider. This also defines the size of the blacklist. + + config ESP_WIFI_ROAMING_PREVENT_DOWNGRADE + bool "Prevent security downgrade when roaming" + default n + help + If the currently connected AP sends a "transition disable" bit, + this option will make the roaming logic ignore less secure APs. + This helps prevent security downgrades when roaming in a mixed + security environment (e.g., WPA2/WPA3). +endmenu # "Blacklist Configuration" diff --git a/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h b/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h index 9ca515e6af..29d3effc5b 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h +++ b/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,12 +22,18 @@ extern "C" { #define ROAMING_BACKOFF_TIME CONFIG_ESP_WIFI_ROAMING_BACKOFF_TIME /* Low RSSI based roaming configuration */ +#ifndef CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_ROAMING +#define CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_ROAMING 0 +#endif #define LOW_RSSI_ROAMING_ENABLED CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_ROAMING #if LOW_RSSI_ROAMING_ENABLED #define ROAMING_LOW_RSSI_THRESHOLD CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_THRESHOLD #define RSSI_THRESHOLD_REDUCTION_OFFSET CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_OFFSET #endif /*LOW_RSSI_ROAMING_ENABLED*/ +#ifndef CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR +#define CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR 0 +#endif /* Periodic Scan based Roaming configuration */ #define PERIODIC_SCAN_MONITORING CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR #if PERIODIC_SCAN_MONITORING @@ -134,6 +140,16 @@ struct roaming_app { #endif #if PERIODIC_SCAN_MONITORING bool periodic_scan_active; +#endif +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + struct blacklist_entry { + uint8_t bssid[ETH_ALEN]; +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + uint8_t failures; +#endif + struct timeval timestamp; + } bssid_blacklist[CONFIG_ESP_WIFI_ROAMING_MAX_CANDIDATES]; + uint8_t bssid_blacklist_count; #endif bool allow_reconnect; }; diff --git a/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c b/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c index 20dcc08366..c7b84d5c0f 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c +++ b/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c @@ -28,22 +28,17 @@ #include "utils/eloop.h" #include "rom/ets_sys.h" #include "common/ieee802_11_defs.h" -static struct roaming_app g_roaming_app; +#include "common/wpa_common.h" +#include "esp_wpas_glue.h" + +struct roaming_app g_roaming_app; typedef void (* scan_done_cb_t)(void *arg, ETS_STATUS status); extern int esp_wifi_promiscuous_scan_start(wifi_scan_config_t *config, scan_done_cb_t cb); -static void *scan_results_lock = NULL; -#define ROAM_SCAN_RESULTS_LOCK() os_mutex_lock(scan_results_lock) -#define ROAM_SCAN_RESULTS_UNLOCK() os_mutex_unlock(scan_results_lock) - -#if PERIODIC_RRM_MONITORING -static void *neighbor_list_lock = NULL; -#define ROAM_NEIGHBOR_LIST_LOCK() os_mutex_lock(neighbor_list_lock) -#define ROAM_NEIGHBOR_LIST_UNLOCK() os_mutex_unlock(neighbor_list_lock) -#endif /*PERIODIC_RRM_MONITORING*/ static int wifi_post_roam_event(struct cand_bss *bss); static void determine_best_ap(int8_t rssi_threshold); +static bool is_bssid_blacklisted(const uint8_t *bssid); #if PERIODIC_RRM_MONITORING static void roaming_app_periodic_rrm_internal_handler(void *data, void *ctx); #endif @@ -53,6 +48,13 @@ static void roaming_app_periodic_scan_internal_handler(void *data, void *ctx); static const char *ROAMING_TAG = "ROAM"; +void esp_wifi_roaming_set_current_bssid(const uint8_t *bssid) +{ + if (bssid) { + memcpy(g_roaming_app.current_bss.ap.bssid, bssid, ETH_ALEN); + } +} + static inline long time_diff_sec(struct timeval *a, struct timeval *b) { return (a->tv_sec - b->tv_sec); @@ -139,12 +141,6 @@ static void init_periodic_rrm_event(void) ESP_LOGI(ROAMING_TAG, "RRM monitor is disabled in config"); return; } - if (!neighbor_list_lock) { - neighbor_list_lock = os_recursive_mutex_create(); - if (!neighbor_list_lock) { - ESP_LOGE(ROAMING_TAG, "%s: failed to create roaming neighbor list lock", __func__); - } - } ESP_LOGV(ROAMING_TAG, "Initialised Periodic RRM Monitoring event!"); g_roaming_app.periodic_rrm_active = true; if (eloop_register_timeout(g_roaming_app.config.rrm_monitor_time, 0, roaming_app_periodic_rrm_internal_handler, NULL, NULL)) { @@ -179,23 +175,77 @@ static void roaming_app_disconnected_event_handler(void *ctx, void *data) #endif /*PERIODIC_SCAN_MONITORING*/ wifi_event_sta_disconnected_t *disconn = data; - ESP_LOGD(ROAMING_TAG, "station got disconnected reason=%d", disconn->reason); +#define RSSI_INVALID -128 + g_roaming_app.current_bss.ap.rssi = RSSI_INVALID; +#undef RSSI_INVALID + + ESP_LOGD(ROAMING_TAG, "station got disconnected reason=%d, rssi =%d", disconn->reason, disconn->rssi); +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + if (disconn->reason == WIFI_REASON_CONNECTION_FAIL || disconn->reason == WIFI_REASON_AUTH_FAIL) { + bool found = false; + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN) == 0) { + g_roaming_app.bssid_blacklist[i].failures++; + gettimeofday(&g_roaming_app.bssid_blacklist[i].timestamp, NULL); + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " connection failures: %d", MAC2STR(g_roaming_app.current_bss.ap.bssid), g_roaming_app.bssid_blacklist[i].failures); + if (g_roaming_app.bssid_blacklist[i].failures >= CONFIG_ESP_WIFI_ROAMING_MAX_CONN_FAILURES) { + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " blacklisted", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + /* The BSSID is now blacklisted. The logic later in this function + * will check the blacklist and trigger a scan for a new AP + * instead of trying to reconnect to this one. */ + } + found = true; + break; + } + } + if (!found) { + if (g_roaming_app.bssid_blacklist_count < CONFIG_ESP_WIFI_ROAMING_MAX_CANDIDATES) { + memcpy(g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN); + g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].failures = 1; + gettimeofday(&g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].timestamp, NULL); + g_roaming_app.bssid_blacklist_count++; + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " added to blacklist tracking", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + } else { + int oldest_idx = 0; + for (int i = 1; i < g_roaming_app.bssid_blacklist_count; i++) { + if (g_roaming_app.bssid_blacklist[i].timestamp.tv_sec < g_roaming_app.bssid_blacklist[oldest_idx].timestamp.tv_sec) { + oldest_idx = i; + } + } + ESP_LOGD(ROAMING_TAG, "Blacklist is full. Replacing oldest entry for " MACSTR, MAC2STR(g_roaming_app.bssid_blacklist[oldest_idx].bssid)); + memcpy(g_roaming_app.bssid_blacklist[oldest_idx].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN); + g_roaming_app.bssid_blacklist[oldest_idx].failures = 1; + gettimeofday(&g_roaming_app.bssid_blacklist[oldest_idx].timestamp, NULL); + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " added to blacklist tracking", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + } + } + } +#endif if (disconn->reason == WIFI_REASON_ROAMING) { ESP_LOGD(ROAMING_TAG, "station roaming, do nothing"); } else if (g_roaming_app.allow_reconnect == false) { ESP_LOGD(ROAMING_TAG, "station initiated disconnect, do nothing"); } else { +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + if (is_bssid_blacklisted(g_roaming_app.current_bss.ap.bssid)) { + ESP_LOGD(ROAMING_TAG, "AP " MACSTR " is blacklisted, finding another AP", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + determine_best_ap(0); + } else { +#endif #if LEGACY_ROAM_ENABLED - /* - * Resetting the Bssid param as it is possible that a previous force - * roam has set config to connect to a specific bssid and now further - * roaming attempts using BTM could lead to a spiral of connecting to - * the previous AP */ - if (g_roaming_app.force_roam_ongoing) { - legacy_roam_clear_bssid_flag(); - } + /* + * Resetting the Bssid param as it is possible that a previous force + * roam has set config to connect to a specific bssid and now further + * roaming attempts using BTM could lead to a spiral of connecting to + * the previous AP */ + if (g_roaming_app.force_roam_ongoing) { + legacy_roam_clear_bssid_flag(); + } #endif /*LEGACY_ROAM_ENABLED*/ - esp_wifi_connect(); + esp_wifi_connect(); +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + } +#endif } os_free(disconn); } @@ -357,26 +407,27 @@ cleanup: } return buf; } -static void roaming_app_neighbor_report_recv_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) + +static void roaming_app_neighbor_report_recv_internal_handler(void *ctx, void *data) { + wifi_event_neighbor_report_t *neighbor_report_event = data; if (!g_roaming_app.rrm_request_active) { ESP_LOGV(ROAMING_TAG, "Not the response for our Neighbor Report Request"); - return; + goto cleanup; } g_roaming_app.rrm_request_active = false; - if (!event_data) { + if (!neighbor_report_event) { ESP_LOGE(ROAMING_TAG, "No data received for neighbor report"); - return; + goto cleanup; } - wifi_event_neighbor_report_t *neighbor_report_event = (wifi_event_neighbor_report_t*)event_data; ESP_LOGD(ROAMING_TAG, "Received cb for Neighbor Report Request"); uint8_t *pos = (uint8_t *)neighbor_report_event->report; if (!pos) { ESP_LOGE(ROAMING_TAG, "Neighbor report is empty"); - return; + goto cleanup; } uint8_t report_len = neighbor_report_event->report_len; @@ -384,22 +435,42 @@ static void roaming_app_neighbor_report_recv_handler(void* arg, esp_event_base_t ESP_LOGD(ROAMING_TAG, "rrm: neighbor report len=%d", report_len); ESP_LOG_BUFFER_HEXDUMP(ROAMING_TAG, pos, report_len, ESP_LOG_DEBUG); - ROAM_NEIGHBOR_LIST_LOCK(); if (g_roaming_app.btm_neighbor_list) { os_free(g_roaming_app.btm_neighbor_list); g_roaming_app.btm_neighbor_list = NULL; } /* create neighbor list */ g_roaming_app.btm_neighbor_list = get_btm_neighbor_list(pos + 1, report_len - 1); - ROAM_NEIGHBOR_LIST_UNLOCK(); +cleanup: + if (neighbor_report_event) { + os_free(neighbor_report_event); + } +} + +static void roaming_app_neighbor_report_recv_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + wifi_event_neighbor_report_t *event = (wifi_event_neighbor_report_t*)event_data; + if (!event) { + return; + } + wifi_event_neighbor_report_t *event_copy = os_malloc(sizeof(wifi_event_neighbor_report_t) + event->report_len); + if (!event_copy) { + ESP_LOGE(ROAMING_TAG, "Failed to allocate memory for neighbor report event"); + return; + } + memcpy(event_copy, event, sizeof(wifi_event_neighbor_report_t) + event->report_len); + + if (eloop_register_timeout(0, 0, roaming_app_neighbor_report_recv_internal_handler, NULL, event_copy) != 0) { + os_free(event_copy); + } } #endif /*PERIODIC_RRM_MONITORING*/ #if LOW_RSSI_ROAMING_ENABLED -static void roaming_app_rssi_low_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +static void roaming_app_rssi_low_internal_handler(void *ctx, void *data) { - wifi_event_bss_rssi_low_t *event = event_data; + wifi_event_bss_rssi_low_t *event = data; ESP_LOGI(ROAMING_TAG, "%s:bss rssi is=%ld", __func__, event->rssi); roaming_app_get_ap_info(&g_roaming_app.current_bss.ap); @@ -408,25 +479,34 @@ static void roaming_app_rssi_low_handler(void* arg, esp_event_base_t event_base, ESP_LOGD(ROAMING_TAG, "Resetting RSSI Threshold to %d", g_roaming_app.current_low_rssi_threshold); esp_wifi_set_rssi_threshold(g_roaming_app.current_low_rssi_threshold); + os_free(event); +} + +static void roaming_app_rssi_low_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + wifi_event_bss_rssi_low_t *event = event_data; + if (!event) { + return; + } + wifi_event_bss_rssi_low_t *event_copy = os_malloc(sizeof(wifi_event_bss_rssi_low_t)); + if (!event_copy) { + ESP_LOGE(ROAMING_TAG, "Failed to allocate memory for rssi low event"); + return; + } + memcpy(event_copy, event, sizeof(wifi_event_bss_rssi_low_t)); + + if (eloop_register_timeout(0, 0, roaming_app_rssi_low_internal_handler, NULL, event_copy) != 0) { + os_free(event_copy); + } } #endif #if NETWORK_ASSISTED_ROAMING_ENABLED static void trigger_network_assisted_roam(void) { -#if PERIODIC_RRM_MONITORING - if (g_roaming_app.current_bss.rrm_support) { - ROAM_NEIGHBOR_LIST_LOCK(); - } -#endif /*PERIODIC_RRM_MONITORING*/ if (esp_wnm_send_bss_transition_mgmt_query(REASON_RSSI, g_roaming_app.btm_neighbor_list, 1) < 0) { ESP_LOGD(ROAMING_TAG, "failed to send btm query"); } -#if PERIODIC_RRM_MONITORING - if (g_roaming_app.current_bss.rrm_support) { - ROAM_NEIGHBOR_LIST_UNLOCK(); - } -#endif /*PERIODIC_RRM_MONITORING*/ ESP_LOGD(ROAMING_TAG, "Sent BTM Query"); gettimeofday(&g_roaming_app.last_roamed_time, NULL); #if LEGACY_ROAM_ENABLED @@ -444,6 +524,7 @@ static void trigger_legacy_roam(struct cand_bss *bss) wifi_cfg.sta.bssid_set = true; os_memcpy(wifi_cfg.sta.bssid, bss->bssid, ETH_ALEN); esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC); + esp_wifi_roaming_set_current_bssid(bss->bssid); esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); esp_wifi_connect(); ESP_LOGI(ROAMING_TAG, "Disconnecting and connecting to "MACSTR" on account of better rssi",MAC2STR(bss->bssid)); @@ -458,7 +539,7 @@ void roaming_app_trigger_roam(struct cand_bss *bss) gettimeofday(&now, NULL); ESP_LOGD(ROAMING_TAG,"Processing trigger roaming request."); if (time_diff_sec(&now, &g_roaming_app.last_roamed_time) < g_roaming_app.config.backoff_time ) { - ESP_LOGD(ROAMING_TAG,"Ignoring request as time difference to last request is %ld",time_diff_sec(&now, &g_roaming_app.last_roamed_time)); + ESP_LOGD(ROAMING_TAG,"Ignoring request as time difference to last request is %ld",time_diff_sec(&now, &g_roaming_app.last_roamed_time)); goto free_bss; } #if NETWORK_ASSISTED_ROAMING_ENABLED @@ -492,7 +573,6 @@ void roaming_app_trigger_roam_internal_handler(void *ctx, void *data) } else { roaming_app_trigger_roam((struct cand_bss *)data); } - } static int wifi_post_roam_event(struct cand_bss *bss) @@ -529,7 +609,6 @@ void print_ap_records(struct scanned_ap_info *ap_info) } - #if PERIODIC_RRM_MONITORING static void periodic_rrm_request(struct timeval *now) { @@ -546,6 +625,31 @@ static void periodic_rrm_request(struct timeval *now) static bool candidate_security_match(wifi_ap_record_t candidate) { +#if CONFIG_ESP_WIFI_ROAMING_PREVENT_DOWNGRADE + u8 transition_disable = wpa_supplicant_get_transition_disable(); + if (transition_disable & TRANSITION_DISABLE_WPA3_PERSONAL) { + if (candidate.authmode == WIFI_AUTH_WPA2_PSK) { + return false; + } + } + if (transition_disable & TRANSITION_DISABLE_ENHANCED_OPEN) { + if (candidate.authmode == WIFI_AUTH_OPEN) { + return false; + } + } + if (transition_disable & TRANSITION_DISABLE_WPA3_ENTERPRISE) { + if (candidate.authmode == WIFI_AUTH_WPA2_ENTERPRISE) { + return false; + } + } +#if TODO // application doesn't have a way to know SAE-PK enabled AP atm + if (transition_disable & TRANSITION_DISABLE_SAE_PK) { + if (candidate.authmode == WIFI_AUTH_WPA3_PSK) { + return false; + } + } +#endif +#endif wifi_auth_mode_t curr_auth = g_roaming_app.current_bss.ap.authmode; wifi_auth_mode_t cand_auth = candidate.authmode; ESP_LOGV(ROAMING_TAG, "Cand authmode : %d, Current Authmode : %d", cand_auth, curr_auth); @@ -556,9 +660,6 @@ static bool candidate_security_match(wifi_ap_record_t candidate) wifi_config_t wifi_cfg = {0}; esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); if (wifi_cfg.sta.owe_enabled && OWE_COMPATIBLE(curr_auth, cand_auth)) { - /* - * OWE <--> Open allowed if threshold is Open - */ if (wifi_cfg.sta.threshold.authmode == WIFI_AUTH_OPEN) { ESP_LOGV(ROAMING_TAG, "transition between OWE and open permitted"); return true; @@ -568,7 +669,7 @@ static bool candidate_security_match(wifi_ap_record_t candidate) } } else if (wifi_cfg.sta.threshold.authmode > cand_auth) { /* If the authmode of the candidate AP is less than our threshold, it - * will fail during connection*/ + * will fail during connection */ ESP_LOGV(ROAMING_TAG, "Authmode threshold failure %d -> %d", wifi_cfg.sta.threshold.authmode, cand_auth); return false; } else if (PSK_COMPATIBLE(curr_auth, cand_auth)) { @@ -581,11 +682,45 @@ static bool candidate_security_match(wifi_ap_record_t candidate) return false; } -static bool candidate_profile_match(wifi_ap_record_t candidate) +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST +static void remove_expired_blacklist_entries(void) { - return candidate_security_match(candidate); + struct timeval now; + gettimeofday(&now, NULL); + int j = 0; + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (time_diff_sec(&now, &g_roaming_app.bssid_blacklist[i].timestamp) <= CONFIG_ESP_WIFI_ROAMING_BLACKLIST_TIMEOUT) { + if (i != j) { + g_roaming_app.bssid_blacklist[j] = g_roaming_app.bssid_blacklist[i]; + } + j++; + } else { + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " removed from blacklist due to timeout", MAC2STR(g_roaming_app.bssid_blacklist[i].bssid)); + } + } + g_roaming_app.bssid_blacklist_count = j; } -/* Remember to always call this function with the ROAM_SCAN_RESULTS_LOCK */ +#endif + +static bool is_bssid_blacklisted(const uint8_t *bssid) +{ +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + remove_expired_blacklist_entries(); + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, bssid, ETH_ALEN) == 0) { +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + if (g_roaming_app.bssid_blacklist[i].failures >= CONFIG_ESP_WIFI_ROAMING_MAX_CONN_FAILURES) { + return true; + } +#else + return true; +#endif + } + } +#endif + return false; +} + static void parse_scan_results_and_roam(void) { int8_t rssi_threshold = g_roaming_app.current_rssi_threshold; @@ -594,16 +729,18 @@ static void parse_scan_results_and_roam(void) int8_t rssi_diff = 0; uint8_t i; int8_t best_ap_index = -1; - wifi_ap_record_t ap_info; - roaming_app_get_ap_info(&ap_info); for (i = 0; i < g_roaming_app.scanned_aps.current_count; i++) { - rssi_diff = g_roaming_app.scanned_aps.ap_records[i].rssi - ap_info.rssi; + if (is_bssid_blacklisted(g_roaming_app.scanned_aps.ap_records[i].bssid)) { + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " is blacklisted, skipping", MAC2STR(g_roaming_app.scanned_aps.ap_records[i].bssid)); + continue; + } + rssi_diff = g_roaming_app.scanned_aps.ap_records[i].rssi - g_roaming_app.current_bss.ap.rssi; ESP_LOGD(ROAMING_TAG, "The difference between ("MACSTR", "MACSTR") with rssi (%d,%d) is : %d while the threshold is %d and the best rssi diff yet is %d, thecand_auth is %d", - MAC2STR(g_roaming_app.scanned_aps.ap_records[i].bssid),MAC2STR(ap_info.bssid), - g_roaming_app.scanned_aps.ap_records[i].rssi, ap_info.rssi, + MAC2STR(g_roaming_app.scanned_aps.ap_records[i].bssid),MAC2STR(g_roaming_app.current_bss.ap.bssid), + g_roaming_app.scanned_aps.ap_records[i].rssi, g_roaming_app.current_bss.ap.rssi, rssi_diff, rssi_threshold, best_rssi_diff, g_roaming_app.scanned_aps.ap_records[i].authmode); - if ((memcmp(g_roaming_app.scanned_aps.ap_records[i].bssid, ap_info.bssid, ETH_ALEN) != 0) && - candidate_profile_match(g_roaming_app.scanned_aps.ap_records[i]) && rssi_diff > best_rssi_diff ) { + if ((memcmp(g_roaming_app.scanned_aps.ap_records[i].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN) != 0) && + candidate_security_match(g_roaming_app.scanned_aps.ap_records[i]) && rssi_diff > best_rssi_diff ) { best_rssi_diff = rssi_diff; best_ap_index = i; } @@ -632,44 +769,41 @@ static void parse_scan_results_and_roam(void) static void scan_done_event_handler(void *arg, ETS_STATUS status) { if (status == ETS_OK) { - ROAM_SCAN_RESULTS_LOCK(); ESP_LOGD(ROAMING_TAG, "Scan Done properly"); g_roaming_app.scanned_aps.current_count = MAX_CANDIDATE_COUNT; esp_wifi_scan_get_ap_records(&g_roaming_app.scanned_aps.current_count, g_roaming_app.scanned_aps.ap_records); print_ap_records(&g_roaming_app.scanned_aps); parse_scan_results_and_roam(); - ROAM_SCAN_RESULTS_UNLOCK(); } else { ESP_LOGD(ROAMING_TAG, "Scan Done with error %d ", status); } - ROAM_SCAN_RESULTS_LOCK(); g_roaming_app.scan_ongoing = false; - ROAM_SCAN_RESULTS_UNLOCK(); } -static void conduct_scan(void) +static bool conduct_scan(void) { - /* Update scan time in global structure */ gettimeofday(&g_roaming_app.scanned_aps.time, NULL); - /* Issue scan */ os_memset(&g_roaming_app.scanned_aps, 0, sizeof(struct scanned_ap_info)); + /* Issue scan */ if (esp_wifi_promiscuous_scan_start(&g_roaming_app.config.scan_config, scan_done_event_handler) < 0) { ESP_LOGE(ROAMING_TAG, "failed to issue scan"); - return; + return false; } ESP_LOGI(ROAMING_TAG, "Issued Scan"); + return true; } static void determine_best_ap(int8_t rssi_threshold) { struct timeval now; gettimeofday(&now, NULL); - ROAM_SCAN_RESULTS_LOCK(); /* If the scan results are recent enough or a scan is already ongoing we should not trigger a new scan */ if (!g_roaming_app.scan_ongoing) { g_roaming_app.scan_ongoing = true; g_roaming_app.current_rssi_threshold = rssi_threshold; if (time_diff_sec(&now,&g_roaming_app.scanned_aps.time) > SCAN_RESULTS_USABILITY_WINDOW) { - conduct_scan(); + if (!conduct_scan()) { + g_roaming_app.scan_ongoing = false; + } } else { parse_scan_results_and_roam(); g_roaming_app.scan_ongoing = false; @@ -677,7 +811,6 @@ static void determine_best_ap(int8_t rssi_threshold) } else if(rssi_threshold < g_roaming_app.current_rssi_threshold) { g_roaming_app.current_rssi_threshold = rssi_threshold; } - ROAM_SCAN_RESULTS_UNLOCK(); } #if PERIODIC_SCAN_MONITORING static void periodic_scan_roam(struct timeval *now) @@ -698,6 +831,7 @@ static void periodic_scan_roam(struct timeval *now) roaming_app_get_ap_info(&g_roaming_app.current_bss.ap); ESP_LOGD(ROAMING_TAG, "Connected AP's RSSI=%d", g_roaming_app.current_bss.ap.rssi); if (g_roaming_app.current_bss.ap.rssi > g_roaming_app.config.scan_rssi_threshold) { + ESP_LOGD(ROAMING_TAG, "Not going for scan, Scan RSSI threshold=%d", g_roaming_app.config.scan_rssi_threshold); return; } @@ -780,6 +914,7 @@ static int8_t parse_scan_chan_list(void) { int8_t ret = 0; char *scan_chan_string = NULL; + char *scan_chan_string_p = NULL; if (validate_scan_chan_list(SCAN_PREFERRED_CHAN_LIST) == false) { ESP_LOGE(ROAMING_TAG, "scan chan list validation failed."); ret = -1; @@ -793,22 +928,27 @@ static int8_t parse_scan_chan_list(void) } strlcpy(scan_chan_string, SCAN_PREFERRED_CHAN_LIST, strlen(SCAN_PREFERRED_CHAN_LIST) + 1); char* token; - token = strsep(&scan_chan_string, ","); + scan_chan_string_p = scan_chan_string; + token = strsep(&scan_chan_string_p, ","); g_roaming_app.config.scan_config.channel_bitmap.ghz_2_channels = 0; + g_roaming_app.config.scan_config.channel_bitmap.ghz_5_channels = 0; while (token != NULL) { uint8_t channel = atoi(token); /* Check if the number is within the required range */ if (channel >= 1 && channel <= 14) { - /* Check if the number is already present in the array */ g_roaming_app.config.scan_config.channel_bitmap.ghz_2_channels |= (1 << channel); +#if CONFIG_SOC_WIFI_SUPPORT_5G + } else if (channel >= 36 && channel <= 177) { + g_roaming_app.config.scan_config.channel_bitmap.ghz_5_channels |= CHANNEL_TO_BIT(channel); +#endif } else { ESP_LOGE(ROAMING_TAG, "Channel out of range: %d", channel); ret = -1; goto cleanup; } - token = strsep(&scan_chan_string, ","); + token = strsep(&scan_chan_string_p, ","); } cleanup: @@ -818,7 +958,6 @@ cleanup: return ret; } - static esp_err_t init_config_params(void) { g_roaming_app.config.backoff_time = ROAMING_BACKOFF_TIME; @@ -828,9 +967,11 @@ static esp_err_t init_config_params(void) g_roaming_app.config.rssi_threshold_reduction_offset = RSSI_THRESHOLD_REDUCTION_OFFSET; g_roaming_app.config.scan_monitor = PERIODIC_SCAN_MONITORING; +#if PERIODIC_SCAN_MONITORING g_roaming_app.config.scan_interval = SCAN_MONITOR_INTERVAL; g_roaming_app.config.scan_rssi_threshold = SCAN_MONITOR_RSSI_THRESHOLD; g_roaming_app.config.scan_rssi_diff = SCAN_ROAM_RSSI_DIFF; +#endif /* PERIODIC_SCAN_MONITORING */ g_roaming_app.config.legacy_roam_enabled = LEGACY_ROAM_ENABLED; g_roaming_app.config.btm_retry_cnt = BSS_TM_RETRY_COUNT; @@ -846,9 +987,11 @@ static esp_err_t init_config_params(void) g_roaming_app.config.backoff_time, g_roaming_app.config.low_rssi_roam_trigger, g_roaming_app.config.low_rssi_threshold, g_roaming_app.config.rssi_threshold_reduction_offset); +#if PERIODIC_SCAN_MONITORING ESP_LOGD(ROAMING_TAG, "scan_monitor=%d scan_interval=%d scan_rssi_threshold=%d scan_rssi_diff=%d", g_roaming_app.config.scan_monitor, g_roaming_app.config.scan_interval, g_roaming_app.config.scan_rssi_threshold, g_roaming_app.config.scan_rssi_diff); +#endif /* PERIODIC_SCAN_MONITORING */ ESP_LOGD(ROAMING_TAG, "legacy_roam_enabled=%d, btm_retry_cnt=%d btm_roaming_enabled=%d", g_roaming_app.config.legacy_roam_enabled, @@ -864,14 +1007,6 @@ static esp_err_t init_config_params(void) static esp_err_t init_scan_config(void) { - if (!scan_results_lock) { - scan_results_lock = os_recursive_mutex_create(); - if (!scan_results_lock) { - ESP_LOGE(ROAMING_TAG, "%s: failed to create scan results lock", __func__); - return ESP_FAIL; - } - } - if (strcmp(DEFAULT_PREFERRED_SCAN_CHAN_LIST, SCAN_PREFERRED_CHAN_LIST)) { ESP_ERROR_CHECK(parse_scan_chan_list()); } @@ -895,6 +1030,7 @@ void roam_init_app(void) ESP_LOGE(ROAMING_TAG, "No roaming method enabled. Roaming app cannot be initialized"); return; #endif + memset(&g_roaming_app, 0, sizeof(g_roaming_app)); #if LOW_RSSI_ROAMING_ENABLED ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, &roaming_app_rssi_low_handler, NULL)); @@ -926,23 +1062,107 @@ void roam_deinit_app(void) #if PERIODIC_SCAN_MONITORING g_roaming_app.periodic_scan_active = false; + eloop_cancel_timeout(roaming_app_periodic_scan_internal_handler, NULL, NULL); #endif /*PERIODIC_SCAN_MONITORING*/ #if PERIODIC_RRM_MONITORING ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_NEIGHBOR_REP, &roaming_app_neighbor_report_recv_handler)); /* Disabling the periodic scan and RRM events */ g_roaming_app.periodic_rrm_active = false; - if (neighbor_list_lock) { - os_mutex_delete(neighbor_list_lock); - neighbor_list_lock = NULL; + eloop_cancel_timeout(roaming_app_periodic_rrm_internal_handler, NULL, NULL); + if (g_roaming_app.btm_neighbor_list) { + os_free(g_roaming_app.btm_neighbor_list); + g_roaming_app.btm_neighbor_list = NULL; } #endif /*PERIODIC_RRM_MONITORING*/ - if (scan_results_lock) { - os_mutex_delete(scan_results_lock); - scan_results_lock = NULL; - } } +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST +static void roaming_app_blacklist_add_handler(void *ctx, void *data) +{ + uint8_t *bssid = data; + if (g_roaming_app.bssid_blacklist_count >= CONFIG_ESP_WIFI_ROAMING_MAX_CANDIDATES) { + ESP_LOGE(ROAMING_TAG, "Blacklist is full"); + os_free(bssid); + return; + } + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, bssid, ETH_ALEN) == 0) { + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " already in blacklist", MAC2STR(bssid)); + os_free(bssid); + return; // Already blacklisted + } + } + memcpy(g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].bssid, bssid, ETH_ALEN); +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].failures = CONFIG_ESP_WIFI_ROAMING_MAX_CONN_FAILURES; +#endif + gettimeofday(&g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].timestamp, NULL); + g_roaming_app.bssid_blacklist_count++; + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " added to blacklist", MAC2STR(bssid)); + os_free(bssid); +} + +esp_err_t esp_wifi_blacklist_add(const uint8_t *bssid) +{ + if (!bssid) { + return ESP_ERR_INVALID_ARG; + } + uint8_t *bssid_copy = os_malloc(ETH_ALEN); + if (!bssid_copy) { + return ESP_ERR_NO_MEM; + } + memcpy(bssid_copy, bssid, ETH_ALEN); + if (eloop_register_timeout(0, 0, roaming_app_blacklist_add_handler, NULL, bssid_copy) != 0) { + os_free(bssid_copy); + return ESP_FAIL; + } + return ESP_OK; +} + +static void roaming_app_blacklist_remove_handler(void *ctx, void *data) +{ + uint8_t *bssid = data; + int found_index = -1; + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, bssid, ETH_ALEN) == 0) { + found_index = i; + break; + } + } + + if (found_index != -1) { + // Shift elements to fill the gap + int remaining_entries = g_roaming_app.bssid_blacklist_count - found_index - 1; + if (remaining_entries > 0) { + memmove(&g_roaming_app.bssid_blacklist[found_index], &g_roaming_app.bssid_blacklist[found_index + 1], remaining_entries * sizeof(struct blacklist_entry)); + } + g_roaming_app.bssid_blacklist_count--; + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " removed from blacklist", MAC2STR(bssid)); + } else { + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " not found in blacklist", MAC2STR(bssid)); + } + os_free(bssid); +} + +esp_err_t esp_wifi_blacklist_remove(const uint8_t *bssid) +{ + if (!bssid) { + return ESP_ERR_INVALID_ARG; + } + uint8_t *bssid_copy = os_malloc(ETH_ALEN); + if (!bssid_copy) { + return ESP_ERR_NO_MEM; + } + memcpy(bssid_copy, bssid, ETH_ALEN); + if (eloop_register_timeout(0, 0, roaming_app_blacklist_remove_handler, NULL, bssid_copy) != 0) { + os_free(bssid_copy); + return ESP_FAIL; + } + return ESP_OK; +} +#endif + /* No need for this to be done in pptask ctx */ esp_err_t roam_get_config_params(struct roam_config *config) { @@ -962,9 +1182,11 @@ static int update_config_params(void *data) g_roaming_app.config.backoff_time, g_roaming_app.config.low_rssi_roam_trigger, g_roaming_app.config.low_rssi_threshold, g_roaming_app.config.rssi_threshold_reduction_offset); +#if PERIODIC_SCAN_MONITORING ESP_LOGI(ROAMING_TAG, "scan_monitor=%d scan_interval=%d scan_rssi_threshold=%d scan_rssi_diff=%d", g_roaming_app.config.scan_monitor, g_roaming_app.config.scan_interval, g_roaming_app.config.scan_rssi_threshold, g_roaming_app.config.scan_rssi_diff); +#endif ESP_LOGI(ROAMING_TAG, "legacy_roam_enabled=%d, btm_retry_cnt=%d btm_roaming_enabled=%d", g_roaming_app.config.legacy_roam_enabled, diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 1836dce9db..994e147cab 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -337,6 +337,7 @@ menu "FreeRTOS" # Todo: Rename to CONFIG_FREERTOS_EXPECTED_IDLE_TIME_BEFORE_SLEEP (IDF-4986) int "configEXPECTED_IDLE_TIME_BEFORE_SLEEP" depends on FREERTOS_USE_TICKLESS_IDLE + default 8 if !PM_SLP_IRAM_OPT && (FREERTOS_HZ > 200) default 3 range 2 4294967295 # Minimal value is 2 because of a check in FreeRTOS.h (search configEXPECTED_IDLE_TIME_BEFORE_SLEEP) diff --git a/components/freertos/test_apps/freertos/misc/test_idf_additions.c b/components/freertos/test_apps/freertos/misc/test_idf_additions.c index 5c5c3d69ad..99e67eb97b 100644 --- a/components/freertos/test_apps/freertos/misc/test_idf_additions.c +++ b/components/freertos/test_apps/freertos/misc/test_idf_additions.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -282,7 +282,7 @@ Expected: --------------------------------------------------------------------------------------------------------------------- */ #define TEST_DELAY_MS 200 -static uint32_t tick_hook_count[portNUM_PROCESSORS]; +static volatile uint32_t tick_hook_count[portNUM_PROCESSORS]; static void IRAM_ATTR tick_hook(void) { @@ -296,10 +296,21 @@ static void suspend_task(void *arg) /* Fetch the current core ID */ BaseType_t xCoreID = portGET_CORE_ID(); + /* Warm up the cache by running the scheduler suspension/resumption once. + * This reduces the execution time variance caused by cache misses during + * the actual test on targets like the esp32p4. + */ + vTaskSuspendAll(); + xTaskResumeAll(); + vTaskDelay(pdMS_TO_TICKS(10)); + /* Register tick hook */ - memset(tick_hook_count, 0, sizeof(tick_hook_count)); + tick_hook_count[xCoreID] = 0; esp_register_freertos_tick_hook_for_cpu(tick_hook, xCoreID); + /* Read the tick hook count before suspending */ + uint32_t initial_count = tick_hook_count[xCoreID]; + /* Suspend scheduler */ vTaskSuspendAll(); @@ -312,30 +323,39 @@ static void suspend_task(void *arg) /* Delay for a further TEST_DELAY_MS milliseconds after scheduler resumption */ vTaskDelay(pdMS_TO_TICKS(TEST_DELAY_MS)); + /* Read the final tick hook count */ + uint32_t final_count = tick_hook_count[xCoreID]; + /* De-register tick hook */ esp_deregister_freertos_tick_hook_for_cpu(tick_hook, xCoreID); /* Verify that the tick hook callback count equals the scheduler suspension time + the delay time. * We add a variation of 2 ticks to account for delays encountered during test setup and teardown. */ - printf("Core%d tick_hook_count = %"PRIu32"\n", xCoreID, tick_hook_count[xCoreID]); - TEST_ASSERT_INT_WITHIN(portTICK_PERIOD_MS * 2, TEST_DELAY_MS * 2, tick_hook_count[xCoreID]); + printf("Core%d initial_count = %"PRIu32"\n", xCoreID, initial_count); + printf("Core%d final_count = %"PRIu32"\n", xCoreID, final_count); + TEST_ASSERT_INT_WITHIN(portTICK_PERIOD_MS * 2, TEST_DELAY_MS * 2, final_count - initial_count); /* Signal main task of test completion */ xTaskNotifyGive(main_task_hdl); - /* Cleanup */ - vTaskDelete(NULL); + vTaskSuspend(NULL); } TEST_CASE("IDF additions: IDF tick hooks during scheduler suspension", "[freertos]") { /* Run test for each core */ + TaskHandle_t suspend_task_handle[portNUM_PROCESSORS]; for (int x = 0; x < portNUM_PROCESSORS; x++) { - xTaskCreatePinnedToCore(&suspend_task, "suspend_task", 8192, (void *)xTaskGetCurrentTaskHandle(), UNITY_FREERTOS_PRIORITY, NULL, x); + xTaskCreatePinnedToCore(&suspend_task, "suspend_task", 8192, (void *)xTaskGetCurrentTaskHandle(), UNITY_FREERTOS_PRIORITY, &suspend_task_handle[x], x); /* Wait for test completion */ ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + /* Cleanup */ + vTaskSuspend(suspend_task_handle[x]); + vTaskDelay(pdMS_TO_TICKS(10)); + vTaskDelete(suspend_task_handle[x]); } } diff --git a/components/hal/esp32/include/hal/spi_ll.h b/components/hal/esp32/include/hal/spi_ll.h index b685cf11a7..5e7b137612 100644 --- a/components/hal/esp32/include/hal/spi_ll.h +++ b/components/hal/esp32/include/hal/spi_ll.h @@ -1172,6 +1172,19 @@ static inline void spi_dma_ll_rx_enable_burst_desc(spi_dma_dev_t *dma_in, uint32 dma_in->dma_conf.indscr_burst_en = enable; } +/** + * Get the DMA RX alignment requirements + * + * @param dma_dev Beginning address of the DMA peripheral registers. + * @param internal_size The internal memory alignment requirements. + * @param external_size The external memory alignment requirements. + */ +static inline void spi_dma_ll_get_rx_alignment_require(spi_dma_dev_t *dma_dev, uint32_t *internal_size, uint32_t *external_size) +{ + *internal_size = 4; // esp32 needs 4 bytes alignment on hardware design + *external_size = UINT32_MAX; // dma of esp32 spi don't support external memory +} + /** * Reset TX DMA which transmits the data from RAM to a peripheral. * diff --git a/components/hal/esp32c2/include/hal/gdma_ll.h b/components/hal/esp32c2/include/hal/gdma_ll.h index ee877d5b3e..ff327126de 100644 --- a/components/hal/esp32c2/include/hal/gdma_ll.h +++ b/components/hal/esp32c2/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_PAIRS_PER_GROUP 1 // Number of GDMA pairs in each AHB group #define GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT 1 // TX and RX channel in the same pair will share the same interrupt source number +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x01 // pair 0 is M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32c3/include/hal/gdma_ll.h b/components/hal/esp32c3/include/hal/gdma_ll.h index f7b3147e4d..511d692613 100644 --- a/components/hal/esp32c3/include/hal/gdma_ll.h +++ b/components/hal/esp32c3/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group #define GDMA_LL_AHB_TX_RX_SHARE_INTERRUPT 1 // TX and RX channel in the same pair will share the same interrupt source number +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32c5/include/hal/ahb_dma_ll.h b/components/hal/esp32c5/include/hal/ahb_dma_ll.h index 787edf0ec5..4ea87aef8c 100644 --- a/components/hal/esp32c5/include/hal/ahb_dma_ll.h +++ b/components/hal/esp32c5/include/hal/ahb_dma_ll.h @@ -48,6 +48,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][3][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32c5/include/hal/spi_ll.h b/components/hal/esp32c5/include/hal/spi_ll.h index 538ea77ac0..897e979494 100644 --- a/components/hal/esp32c5/include/hal/spi_ll.h +++ b/components/hal/esp32c5/include/hal/spi_ll.h @@ -54,6 +54,8 @@ typedef spi_dev_t spi_dma_dev_t; // Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done + SPI_LL_INTR_IN_FULL = BIT(4), ///< DMA in_full error happened + SPI_LL_INTR_OUT_EMPTY = BIT(5), ///< DMA out_empty error happened SPI_LL_INTR_RDBUF = BIT(6), ///< Has received RDBUF command. Only available in slave HD. SPI_LL_INTR_WRBUF = BIT(7), ///< Has received WRBUF command. Only available in slave HD. SPI_LL_INTR_RDDMA = BIT(8), ///< Has received RDDMA command. Only available in slave HD. @@ -1097,16 +1099,18 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) //helper macros to generate code for each interrupts #define FOR_EACH_ITEM(op, list) do { list(op) } while(0) #define INTR_LIST(item) \ - item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done_int_ena, dma_int_raw.trans_done_int_raw, dma_int_clr.trans_done_int_clr, dma_int_set.trans_done_int_set) \ - item(SPI_LL_INTR_RDBUF, dma_int_ena.slv_rd_buf_done_int_ena, dma_int_raw.slv_rd_buf_done_int_raw, dma_int_clr.slv_rd_buf_done_int_clr, dma_int_set.slv_rd_buf_done_int_set) \ - item(SPI_LL_INTR_WRBUF, dma_int_ena.slv_wr_buf_done_int_ena, dma_int_raw.slv_wr_buf_done_int_raw, dma_int_clr.slv_wr_buf_done_int_clr, dma_int_set.slv_wr_buf_done_int_set) \ - item(SPI_LL_INTR_RDDMA, dma_int_ena.slv_rd_dma_done_int_ena, dma_int_raw.slv_rd_dma_done_int_raw, dma_int_clr.slv_rd_dma_done_int_clr, dma_int_set.slv_rd_dma_done_int_set) \ - item(SPI_LL_INTR_WRDMA, dma_int_ena.slv_wr_dma_done_int_ena, dma_int_raw.slv_wr_dma_done_int_raw, dma_int_clr.slv_wr_dma_done_int_clr, dma_int_set.slv_wr_dma_done_int_set) \ - item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done_int_ena, dma_int_raw.dma_seg_trans_done_int_raw, dma_int_clr.dma_seg_trans_done_int_clr, dma_int_set.dma_seg_trans_done_int_set) \ - item(SPI_LL_INTR_CMD7, dma_int_ena.slv_cmd7_int_ena, dma_int_raw.slv_cmd7_int_raw, dma_int_clr.slv_cmd7_int_clr, dma_int_set.slv_cmd7_int_set) \ - item(SPI_LL_INTR_CMD8, dma_int_ena.slv_cmd8_int_ena, dma_int_raw.slv_cmd8_int_raw, dma_int_clr.slv_cmd8_int_clr, dma_int_set.slv_cmd8_int_set) \ - item(SPI_LL_INTR_CMD9, dma_int_ena.slv_cmd9_int_ena, dma_int_raw.slv_cmd9_int_raw, dma_int_clr.slv_cmd9_int_clr, dma_int_set.slv_cmd9_int_set) \ - item(SPI_LL_INTR_CMDA, dma_int_ena.slv_cmda_int_ena, dma_int_raw.slv_cmda_int_raw, dma_int_clr.slv_cmda_int_clr, dma_int_set.slv_cmda_int_set) + item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done_int_ena, dma_int_raw.trans_done_int_raw, dma_int_clr.trans_done_int_clr, dma_int_set.trans_done_int_set) \ + item(SPI_LL_INTR_IN_FULL, dma_int_ena.dma_infifo_full_err_int_ena, dma_int_raw.dma_infifo_full_err_int_raw, dma_int_clr.dma_infifo_full_err_int_clr, dma_int_set.dma_infifo_full_err_int_set) \ + item(SPI_LL_INTR_OUT_EMPTY, dma_int_ena.dma_outfifo_empty_err_int_ena, dma_int_raw.dma_outfifo_empty_err_int_raw, dma_int_clr.dma_outfifo_empty_err_int_clr, dma_int_set.dma_outfifo_empty_err_int_set) \ + item(SPI_LL_INTR_RDBUF, dma_int_ena.slv_rd_buf_done_int_ena, dma_int_raw.slv_rd_buf_done_int_raw, dma_int_clr.slv_rd_buf_done_int_clr, dma_int_set.slv_rd_buf_done_int_set) \ + item(SPI_LL_INTR_WRBUF, dma_int_ena.slv_wr_buf_done_int_ena, dma_int_raw.slv_wr_buf_done_int_raw, dma_int_clr.slv_wr_buf_done_int_clr, dma_int_set.slv_wr_buf_done_int_set) \ + item(SPI_LL_INTR_RDDMA, dma_int_ena.slv_rd_dma_done_int_ena, dma_int_raw.slv_rd_dma_done_int_raw, dma_int_clr.slv_rd_dma_done_int_clr, dma_int_set.slv_rd_dma_done_int_set) \ + item(SPI_LL_INTR_WRDMA, dma_int_ena.slv_wr_dma_done_int_ena, dma_int_raw.slv_wr_dma_done_int_raw, dma_int_clr.slv_wr_dma_done_int_clr, dma_int_set.slv_wr_dma_done_int_set) \ + item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done_int_ena, dma_int_raw.dma_seg_trans_done_int_raw, dma_int_clr.dma_seg_trans_done_int_clr, dma_int_set.dma_seg_trans_done_int_set) \ + item(SPI_LL_INTR_CMD7, dma_int_ena.slv_cmd7_int_ena, dma_int_raw.slv_cmd7_int_raw, dma_int_clr.slv_cmd7_int_clr, dma_int_set.slv_cmd7_int_set) \ + item(SPI_LL_INTR_CMD8, dma_int_ena.slv_cmd8_int_ena, dma_int_raw.slv_cmd8_int_raw, dma_int_clr.slv_cmd8_int_clr, dma_int_set.slv_cmd8_int_set) \ + item(SPI_LL_INTR_CMD9, dma_int_ena.slv_cmd9_int_ena, dma_int_raw.slv_cmd9_int_raw, dma_int_clr.slv_cmd9_int_clr, dma_int_set.slv_cmd9_int_set) \ + item(SPI_LL_INTR_CMDA, dma_int_ena.slv_cmda_int_ena, dma_int_raw.slv_cmda_int_raw, dma_int_clr.slv_cmda_int_clr, dma_int_set.slv_cmda_int_set) static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) diff --git a/components/hal/esp32c6/include/hal/gdma_ll.h b/components/hal/esp32c6/include/hal/gdma_ll.h index 5a1d8d2417..62f4dea119 100644 --- a/components/hal/esp32c6/include/hal/gdma_ll.h +++ b/components/hal/esp32c6/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32c61/include/hal/ahb_dma_ll.h b/components/hal/esp32c61/include/hal/ahb_dma_ll.h index d2f5f95bfb..67a789970a 100644 --- a/components/hal/esp32c61/include/hal/ahb_dma_ll.h +++ b/components/hal/esp32c61/include/hal/ahb_dma_ll.h @@ -48,6 +48,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 2 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x03 // pair 0,1 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][2][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32c61/include/hal/spi_ll.h b/components/hal/esp32c61/include/hal/spi_ll.h index 4c8bf5edb2..6a6918a63f 100644 --- a/components/hal/esp32c61/include/hal/spi_ll.h +++ b/components/hal/esp32c61/include/hal/spi_ll.h @@ -54,6 +54,8 @@ typedef spi_dev_t spi_dma_dev_t; // Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done + SPI_LL_INTR_IN_FULL = BIT(4), ///< DMA in_full error happened + SPI_LL_INTR_OUT_EMPTY = BIT(5), ///< DMA out_empty error happened SPI_LL_INTR_RDBUF = BIT(6), ///< Has received RDBUF command. Only available in slave HD. SPI_LL_INTR_WRBUF = BIT(7), ///< Has received WRBUF command. Only available in slave HD. SPI_LL_INTR_RDDMA = BIT(8), ///< Has received RDDMA command. Only available in slave HD. @@ -1099,16 +1101,18 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) //helper macros to generate code for each interrupts #define FOR_EACH_ITEM(op, list) do { list(op) } while(0) #define INTR_LIST(item) \ - item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done, dma_int_raw.trans_done, dma_int_clr.trans_done, dma_int_set.trans_done) \ - item(SPI_LL_INTR_RDBUF, dma_int_ena.slv_rd_buf_done, dma_int_raw.slv_rd_buf_done, dma_int_clr.slv_rd_buf_done, dma_int_set.slv_rd_buf_done) \ - item(SPI_LL_INTR_WRBUF, dma_int_ena.slv_wr_buf_done, dma_int_raw.slv_wr_buf_done, dma_int_clr.slv_wr_buf_done, dma_int_set.slv_wr_buf_done) \ - item(SPI_LL_INTR_RDDMA, dma_int_ena.slv_rd_dma_done, dma_int_raw.slv_rd_dma_done, dma_int_clr.slv_rd_dma_done, dma_int_set.slv_rd_dma_done) \ - item(SPI_LL_INTR_WRDMA, dma_int_ena.slv_wr_dma_done, dma_int_raw.slv_wr_dma_done, dma_int_clr.slv_wr_dma_done, dma_int_set.slv_wr_dma_done) \ - item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done, dma_int_raw.dma_seg_trans_done, dma_int_clr.dma_seg_trans_done, dma_int_set.dma_seg_trans_done) \ - item(SPI_LL_INTR_CMD7, dma_int_ena.slv_cmd7, dma_int_raw.slv_cmd7, dma_int_clr.slv_cmd7, dma_int_set.slv_cmd7) \ - item(SPI_LL_INTR_CMD8, dma_int_ena.slv_cmd8, dma_int_raw.slv_cmd8, dma_int_clr.slv_cmd8, dma_int_set.slv_cmd8) \ - item(SPI_LL_INTR_CMD9, dma_int_ena.slv_cmd9, dma_int_raw.slv_cmd9, dma_int_clr.slv_cmd9, dma_int_set.slv_cmd9) \ - item(SPI_LL_INTR_CMDA, dma_int_ena.slv_cmda, dma_int_raw.slv_cmda, dma_int_clr.slv_cmda, dma_int_set.slv_cmda) + item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done, dma_int_raw.trans_done, dma_int_clr.trans_done, dma_int_set.trans_done) \ + item(SPI_LL_INTR_IN_FULL, dma_int_ena.dma_infifo_full_err, dma_int_raw.dma_infifo_full_err, dma_int_clr.dma_infifo_full_err, dma_int_set.dma_infifo_full_err) \ + item(SPI_LL_INTR_OUT_EMPTY, dma_int_ena.dma_outfifo_empty_err, dma_int_raw.dma_outfifo_empty_err, dma_int_clr.dma_outfifo_empty_err, dma_int_set.dma_outfifo_empty_err) \ + item(SPI_LL_INTR_RDBUF, dma_int_ena.slv_rd_buf_done, dma_int_raw.slv_rd_buf_done, dma_int_clr.slv_rd_buf_done, dma_int_set.slv_rd_buf_done) \ + item(SPI_LL_INTR_WRBUF, dma_int_ena.slv_wr_buf_done, dma_int_raw.slv_wr_buf_done, dma_int_clr.slv_wr_buf_done, dma_int_set.slv_wr_buf_done) \ + item(SPI_LL_INTR_RDDMA, dma_int_ena.slv_rd_dma_done, dma_int_raw.slv_rd_dma_done, dma_int_clr.slv_rd_dma_done, dma_int_set.slv_rd_dma_done) \ + item(SPI_LL_INTR_WRDMA, dma_int_ena.slv_wr_dma_done, dma_int_raw.slv_wr_dma_done, dma_int_clr.slv_wr_dma_done, dma_int_set.slv_wr_dma_done) \ + item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done, dma_int_raw.dma_seg_trans_done, dma_int_clr.dma_seg_trans_done, dma_int_set.dma_seg_trans_done) \ + item(SPI_LL_INTR_CMD7, dma_int_ena.slv_cmd7, dma_int_raw.slv_cmd7, dma_int_clr.slv_cmd7, dma_int_set.slv_cmd7) \ + item(SPI_LL_INTR_CMD8, dma_int_ena.slv_cmd8, dma_int_raw.slv_cmd8, dma_int_clr.slv_cmd8, dma_int_set.slv_cmd8) \ + item(SPI_LL_INTR_CMD9, dma_int_ena.slv_cmd9, dma_int_raw.slv_cmd9, dma_int_clr.slv_cmd9, dma_int_set.slv_cmd9) \ + item(SPI_LL_INTR_CMDA, dma_int_ena.slv_cmda, dma_int_raw.slv_cmda, dma_int_clr.slv_cmda, dma_int_set.slv_cmda) static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) diff --git a/components/hal/esp32h2/include/hal/gdma_ll.h b/components/hal/esp32h2/include/hal/gdma_ll.h index 5a1d8d2417..62f4dea119 100644 --- a/components/hal/esp32h2/include/hal/gdma_ll.h +++ b/components/hal/esp32h2/include/hal/gdma_ll.h @@ -47,6 +47,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 3 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 diff --git a/components/hal/esp32h21/include/hal/gdma_ll.h b/components/hal/esp32h21/include/hal/gdma_ll.h index bf145e4778..4d0f42c613 100644 --- a/components/hal/esp32h21/include/hal/gdma_ll.h +++ b/components/hal/esp32h21/include/hal/gdma_ll.h @@ -50,6 +50,8 @@ extern "C" { #define GDMA_LL_AHB_DESC_ALIGNMENT 4 #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][3][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32h4/include/hal/ahb_dma_ll.h b/components/hal/esp32h4/include/hal/ahb_dma_ll.h index facd2dab5a..addac62de0 100644 --- a/components/hal/esp32h4/include/hal/ahb_dma_ll.h +++ b/components/hal/esp32h4/include/hal/ahb_dma_ll.h @@ -48,6 +48,8 @@ extern "C" { #define GDMA_LL_AHB_NUM_GROUPS 1 // Number of AHB GDMA groups #define GDMA_LL_AHB_PAIRS_PER_GROUP 5 // Number of GDMA pairs in each AHB group +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[1][5][GDMA_ETM_EVENT_MAX]){{{ \ [GDMA_ETM_EVENT_EOF] = GDMA_EVT_OUT_EOF_CH0, \ diff --git a/components/hal/esp32p4/include/hal/gdma_ll.h b/components/hal/esp32p4/include/hal/gdma_ll.h index 3f1410a1a6..6316a33f94 100644 --- a/components/hal/esp32p4/include/hal/gdma_ll.h +++ b/components/hal/esp32p4/include/hal/gdma_ll.h @@ -54,6 +54,14 @@ #define GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE 1 // AHB GDMA supports adjustable burst size #endif +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x06 // only pair 1,2 are M2M capable +#else +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable +#endif + +#define GDMA_LL_AXI_M2M_CAPABLE_PAIR_MASK 0x07 // pair 0,1,2 are M2M capable + #define GDMA_LL_TX_ETM_EVENT_TABLE(group, chan, event) \ (uint32_t[2][GDMA_ETM_EVENT_MAX]){ \ { \ diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index d5abfc435d..aa21ed0ebc 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1723,6 +1723,23 @@ static inline uint32_t isp_ll_awb_get_accumulated_b_value(isp_dev_t *hw) } #if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +/** + * @brief Set AWB subwindow range + * + * @param[in] hw Hardware instance address + * @param[in] top_left_x Top left pixel x axis value + * @param[in] top_left_y Top left pixel y axis value + * @param[in] sub_window_xsize Subwindow x size (minimum 4) + * @param[in] sub_window_ysize Subwindow y size (minimum 4) + */ +static inline void isp_ll_awb_set_subwindow_range(isp_dev_t *hw, uint32_t top_left_x, uint32_t top_left_y, uint32_t sub_window_xsize, uint32_t sub_window_ysize) +{ + hw->awb_bx.awb_x_start = top_left_x; + hw->awb_bx.awb_x_bsize = sub_window_xsize; + hw->awb_by.awb_y_start = top_left_y; + hw->awb_by.awb_y_bsize = sub_window_ysize; +} + /** * @brief Enable AWB white balance gain * @@ -1758,6 +1775,11 @@ static inline void isp_ll_awb_set_wb_gain(isp_dev_t *hw, isp_wbg_gain_t gain) hw->wbg_coef_b.wbg_b = gain.gain_b; } #else +static inline void isp_ll_awb_set_subwindow_range(isp_dev_t *hw, uint32_t top_left_x, uint32_t top_left_y, uint32_t sub_window_xsize, uint32_t sub_window_ysize) +{ + // for compatibility +} + static inline void isp_ll_awb_enable_wb_gain(isp_dev_t *hw, bool enable) { //for compatibility @@ -1877,21 +1899,27 @@ static inline void isp_ll_shadow_set_mode(isp_dev_t *hw, isp_ll_shadow_mode_t mo /** * @brief Update BLC shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.blc_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.blc_update = 1; + } else { + if (hw->shadow_reg_ctrl.blc_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.blc_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.blc_update = 1; + } return true; } @@ -1899,21 +1927,27 @@ static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw) /** * @brief Update DPC shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.dpc_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.dpc_update = 1; + } else { + if (hw->shadow_reg_ctrl.dpc_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.dpc_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.dpc_update = 1; + } return true; } @@ -1921,21 +1955,27 @@ static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw) /** * @brief Update BF shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.bf_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.bf_update = 1; + } else { + if (hw->shadow_reg_ctrl.bf_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.bf_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.bf_update = 1; + } return true; } @@ -1943,21 +1983,27 @@ static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw) /** * @brief Update WBG shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.wbg_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.wbg_update = 1; + } else { + if (hw->shadow_reg_ctrl.wbg_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.wbg_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.wbg_update = 1; + } return true; } @@ -1965,21 +2011,27 @@ static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) /** * @brief Update CCM shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.ccm_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.ccm_update = 1; + } else { + if (hw->shadow_reg_ctrl.ccm_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.ccm_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.ccm_update = 1; + } return true; } @@ -1987,21 +2039,27 @@ static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) /** * @brief Update Sharpen shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.sharp_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.sharp_update = 1; + } else { + if (hw->shadow_reg_ctrl.sharp_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.sharp_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.sharp_update = 1; + } return true; } @@ -2009,21 +2067,27 @@ static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw) /** * @brief Update Color shadow register * - * @param[in] hw Hardware instance address + * @param[in] hw Hardware instance address + * @param[in] force_update Force update * @return * - True if update is successful, False otherwise */ -static inline bool isp_ll_shadow_update_color(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_color(isp_dev_t *hw, bool force_update) { //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); - if (hw->shadow_reg_ctrl.color_update == 1) { - return false; - } + if (force_update) { + //don't care shadow register + hw->shadow_reg_ctrl.color_update = 1; + } else { + if (hw->shadow_reg_ctrl.color_update == 1) { + return false; + } - //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC - hw->shadow_reg_ctrl.color_update = 1; + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.color_update = 1; + } return true; } @@ -2034,43 +2098,43 @@ static inline void isp_ll_shadow_set_mode(isp_dev_t *hw, isp_ll_shadow_mode_t mo //for compatibility } -static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw, bool force_update) { //for compatibility return true; } -static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw, bool force_update) { //for compatibility return true; } -static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw, bool force_update) { //for compatibility return true; } -static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw, bool force_update) { //for compatibility return true; } -static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw, bool force_update) { //for compatibility return true; } -static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw, bool force_update) { //for compatibility return true; } -static inline bool isp_ll_shadow_update_color(isp_dev_t *hw) +static inline bool isp_ll_shadow_update_color(isp_dev_t *hw, bool force_update) { //for compatibility return true; diff --git a/components/hal/esp32p4/include/hal/spi_ll.h b/components/hal/esp32p4/include/hal/spi_ll.h index 04a895d421..d5f335087e 100644 --- a/components/hal/esp32p4/include/hal/spi_ll.h +++ b/components/hal/esp32p4/include/hal/spi_ll.h @@ -56,6 +56,8 @@ typedef spi_dev_t spi_dma_dev_t; // Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done + SPI_LL_INTR_IN_FULL = BIT(4), ///< DMA in_full error happened + SPI_LL_INTR_OUT_EMPTY = BIT(5), ///< DMA out_empty error happened SPI_LL_INTR_RDBUF = BIT(6), ///< Has received RDBUF command. Only available in slave HD. SPI_LL_INTR_WRBUF = BIT(7), ///< Has received WRBUF command. Only available in slave HD. SPI_LL_INTR_RDDMA = BIT(8), ///< Has received RDDMA command. Only available in slave HD. @@ -1155,16 +1157,18 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) //helper macros to generate code for each interrupts #define FOR_EACH_ITEM(op, list) do { list(op) } while(0) #define INTR_LIST(item) \ - item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done_int, dma_int_raw.trans_done_int, dma_int_clr.trans_done_int, dma_int_set.trans_done_int) \ - item(SPI_LL_INTR_RDBUF, dma_int_ena.slv_rd_buf_done_int, dma_int_raw.slv_rd_buf_done_int, dma_int_clr.slv_rd_buf_done_int, dma_int_set.slv_rd_buf_done_int) \ - item(SPI_LL_INTR_WRBUF, dma_int_ena.slv_wr_buf_done_int, dma_int_raw.slv_wr_buf_done_int, dma_int_clr.slv_wr_buf_done_int, dma_int_set.slv_wr_buf_done_int) \ - item(SPI_LL_INTR_RDDMA, dma_int_ena.slv_rd_dma_done_int, dma_int_raw.slv_rd_dma_done_int, dma_int_clr.slv_rd_dma_done_int, dma_int_set.slv_rd_dma_done_int) \ - item(SPI_LL_INTR_WRDMA, dma_int_ena.slv_wr_dma_done_int, dma_int_raw.slv_wr_dma_done_int, dma_int_clr.slv_wr_dma_done_int, dma_int_set.slv_wr_dma_done_int) \ - item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done_int, dma_int_raw.dma_seg_trans_done_int, dma_int_clr.dma_seg_trans_done_int, dma_int_set.dma_seg_trans_done_int) \ - item(SPI_LL_INTR_CMD7, dma_int_ena.slv_cmd7_int, dma_int_raw.slv_cmd7_int, dma_int_clr.slv_cmd7_int, dma_int_set.slv_cmd7_int) \ - item(SPI_LL_INTR_CMD8, dma_int_ena.slv_cmd8_int, dma_int_raw.slv_cmd8_int, dma_int_clr.slv_cmd8_int, dma_int_set.slv_cmd8_int) \ - item(SPI_LL_INTR_CMD9, dma_int_ena.slv_cmd9_int, dma_int_raw.slv_cmd9_int, dma_int_clr.slv_cmd9_int, dma_int_set.slv_cmd9_int) \ - item(SPI_LL_INTR_CMDA, dma_int_ena.slv_cmda_int, dma_int_raw.slv_cmda_int, dma_int_clr.slv_cmda_int, dma_int_set.slv_cmda_int) + item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done_int, dma_int_raw.trans_done_int, dma_int_clr.trans_done_int, dma_int_set.trans_done_int) \ + item(SPI_LL_INTR_IN_FULL, dma_int_ena.dma_infifo_full_err_int, dma_int_raw.dma_infifo_full_err_int, dma_int_clr.dma_infifo_full_err_int, dma_int_set.dma_infifo_full_err_int) \ + item(SPI_LL_INTR_OUT_EMPTY, dma_int_ena.dma_outfifo_empty_err_int, dma_int_raw.dma_outfifo_empty_err_int, dma_int_clr.dma_outfifo_empty_err_int, dma_int_set.dma_outfifo_empty_err_int) \ + item(SPI_LL_INTR_RDBUF, dma_int_ena.slv_rd_buf_done_int, dma_int_raw.slv_rd_buf_done_int, dma_int_clr.slv_rd_buf_done_int, dma_int_set.slv_rd_buf_done_int) \ + item(SPI_LL_INTR_WRBUF, dma_int_ena.slv_wr_buf_done_int, dma_int_raw.slv_wr_buf_done_int, dma_int_clr.slv_wr_buf_done_int, dma_int_set.slv_wr_buf_done_int) \ + item(SPI_LL_INTR_RDDMA, dma_int_ena.slv_rd_dma_done_int, dma_int_raw.slv_rd_dma_done_int, dma_int_clr.slv_rd_dma_done_int, dma_int_set.slv_rd_dma_done_int) \ + item(SPI_LL_INTR_WRDMA, dma_int_ena.slv_wr_dma_done_int, dma_int_raw.slv_wr_dma_done_int, dma_int_clr.slv_wr_dma_done_int, dma_int_set.slv_wr_dma_done_int) \ + item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done_int, dma_int_raw.dma_seg_trans_done_int, dma_int_clr.dma_seg_trans_done_int, dma_int_set.dma_seg_trans_done_int) \ + item(SPI_LL_INTR_CMD7, dma_int_ena.slv_cmd7_int, dma_int_raw.slv_cmd7_int, dma_int_clr.slv_cmd7_int, dma_int_set.slv_cmd7_int) \ + item(SPI_LL_INTR_CMD8, dma_int_ena.slv_cmd8_int, dma_int_raw.slv_cmd8_int, dma_int_clr.slv_cmd8_int, dma_int_set.slv_cmd8_int) \ + item(SPI_LL_INTR_CMD9, dma_int_ena.slv_cmd9_int, dma_int_raw.slv_cmd9_int, dma_int_clr.slv_cmd9_int, dma_int_set.slv_cmd9_int) \ + item(SPI_LL_INTR_CMDA, dma_int_ena.slv_cmda_int, dma_int_raw.slv_cmda_int, dma_int_clr.slv_cmda_int, dma_int_set.slv_cmda_int) static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index 68f0834f79..b55bb8c046 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -1364,6 +1364,20 @@ static inline uint32_t spi_dma_ll_get_in_suc_eof_desc_addr(spi_dma_dev_t *dma_in return dma_in->dma_in_suc_eof_des_addr; } +/** + * Get the DMA RX alignment requirements + * + * @param dma_dev Beginning address of the DMA peripheral registers. + * @param internal_size The internal memory alignment requirements. + * @param external_size The external memory alignment requirements. + */ +static inline void spi_dma_ll_get_rx_alignment_require(spi_dma_dev_t *dma_dev, uint32_t *internal_size, uint32_t *external_size) +{ + *internal_size = 4; + // SPI2 supports external memory, SPI3 does not + *external_size = (dma_dev == &GPSPI2) ? 16 << dma_dev->dma_conf.ext_mem_bk_size : UINT32_MAX; +} + //---------------------------------------------------TX-------------------------------------------------// /** * Reset TX DMA which transmits the data from RAM to a peripheral. diff --git a/components/hal/esp32s3/include/hal/gdma_ll.h b/components/hal/esp32s3/include/hal/gdma_ll.h index d69c74fd1e..58cc22253c 100644 --- a/components/hal/esp32s3/include/hal/gdma_ll.h +++ b/components/hal/esp32s3/include/hal/gdma_ll.h @@ -66,6 +66,8 @@ extern "C" { #define GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT 1 #define GDMA_LL_MAX_BURST_SIZE_PSRAM 64 // PSRAM controller doesn't support burst access with size > 64 bytes +#define GDMA_LL_AHB_M2M_CAPABLE_PAIR_MASK 0x1F // pair 0,1,2,3,4 are M2M capable + ///////////////////////////////////// Common ///////////////////////////////////////// /** diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index c3db5cbd26..a318f40a86 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -56,6 +56,8 @@ typedef spi_dev_t spi_dma_dev_t; // Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done + SPI_LL_INTR_IN_FULL = BIT(4), ///< DMA in_full error happened + SPI_LL_INTR_OUT_EMPTY = BIT(5), ///< DMA out_empty error happened SPI_LL_INTR_RDBUF = BIT(6), ///< Has received RDBUF command. Only available in slave HD. SPI_LL_INTR_WRBUF = BIT(7), ///< Has received WRBUF command. Only available in slave HD. SPI_LL_INTR_RDDMA = BIT(8), ///< Has received RDDMA command. Only available in slave HD. @@ -1107,6 +1109,8 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) #define FOR_EACH_ITEM(op, list) do { list(op) } while(0) #define INTR_LIST(item) \ item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done, dma_int_raw.trans_done, dma_int_clr.trans_done, dma_int_set.trans_done_int_set) \ + item(SPI_LL_INTR_IN_FULL, dma_int_ena.infifo_full_err, dma_int_raw.infifo_full_err, dma_int_clr.infifo_full_err, dma_int_set.infifo_full_err_int_set) \ + item(SPI_LL_INTR_OUT_EMPTY, dma_int_ena.outfifo_empty_err, dma_int_raw.outfifo_empty_err, dma_int_clr.outfifo_empty_err, dma_int_set.outfifo_empty_err_int_set) \ item(SPI_LL_INTR_RDBUF, dma_int_ena.rd_buf_done, dma_int_raw.rd_buf_done, dma_int_clr.rd_buf_done, dma_int_set.rd_buf_done_int_set) \ item(SPI_LL_INTR_WRBUF, dma_int_ena.wr_buf_done, dma_int_raw.wr_buf_done, dma_int_clr.wr_buf_done, dma_int_set.wr_buf_done_int_set) \ item(SPI_LL_INTR_RDDMA, dma_int_ena.rd_dma_done, dma_int_raw.rd_dma_done, dma_int_clr.rd_dma_done, dma_int_set.rd_dma_done_int_set) \ diff --git a/components/hal/include/hal/isp_hal.h b/components/hal/include/hal/isp_hal.h index a8eb6b502d..952c43445c 100644 --- a/components/hal/include/hal/isp_hal.h +++ b/components/hal/include/hal/isp_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -132,6 +132,17 @@ void isp_hal_ae_window_config(isp_hal_context_t *hal, const isp_window_t *window */ bool isp_hal_awb_set_window_range(isp_hal_context_t *hal, const isp_window_t *win); +/** + * @brief Set the subwindow range of the AWB + * + * @param[in] hal Context of the HAL layer + * @param[in] win Pointer to the subwindow of the AWB + * @return + * - true Set success + * - false Invalid arg + */ +bool isp_hal_awb_set_subwindow_range(isp_hal_context_t *hal, const isp_window_t *win); + /** * @brief Set the luminance range of the white patch * diff --git a/components/hal/include/hal/spi_hal.h b/components/hal/include/hal/spi_hal.h index c9d2e136e8..3dacc434c8 100644 --- a/components/hal/include/hal/spi_hal.h +++ b/components/hal/include/hal/spi_hal.h @@ -240,6 +240,23 @@ void spi_hal_user_start(const spi_hal_context_t *hal); */ bool spi_hal_usr_is_done(const spi_hal_context_t *hal); +/** + * Get SPI interrupt bits status by mask + * + * @param hal Context of the HAL layer. + * @param mask Mask of the interrupt bits to check. + * @return True if the masked interrupts are set, false otherwise. + */ +bool spi_hal_get_intr_mask(spi_hal_context_t *hal, uint32_t mask); + +/** + * Clear SPI interrupt bits by mask + * + * @param hal Context of the HAL layer. + * @param mask Mask of the interrupt bits to clear. + */ +void spi_hal_clear_intr_mask(spi_hal_context_t *hal, uint32_t mask); + /** * Setup transaction operations, write tx buffer to HW registers * @@ -342,16 +359,6 @@ void spi_hal_sct_deinit(spi_hal_context_t *hal); */ void spi_hal_sct_set_conf_bits_len(spi_hal_context_t *hal, uint32_t conf_len); -/** - * Clear SPI interrupt bits by mask - */ -void spi_hal_clear_intr_mask(spi_hal_context_t *hal, uint32_t mask); - -/** - * Get SPI interrupt bits status by mask - */ -bool spi_hal_get_intr_mask(spi_hal_context_t *hal, uint32_t mask); - /** * Set conf_bitslen base to HW for sct, only supported on s2. */ diff --git a/components/hal/isp_hal.c b/components/hal/isp_hal.c index 6dc1cad264..592f83b3ff 100644 --- a/components/hal/isp_hal.c +++ b/components/hal/isp_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -66,6 +66,24 @@ bool isp_hal_awb_set_window_range(isp_hal_context_t *hal, const isp_window_t *wi return true; } +bool isp_hal_awb_set_subwindow_range(isp_hal_context_t *hal, const isp_window_t *win) +{ + if (win->top_left.x > win->btm_right.x || + win->top_left.y > win->btm_right.y || + win->btm_right.x > ISP_LL_AWB_WINDOW_MAX_RANGE || + win->btm_right.y > ISP_LL_AWB_WINDOW_MAX_RANGE) { + return false; + } + isp_ll_awb_set_subwindow_range( + hal->hw, + win->top_left.x, + win->top_left.y, + (win->btm_right.x - win->top_left.x) / SOC_ISP_AWB_WINDOW_X_NUMS, + (win->btm_right.y - win->top_left.y) / SOC_ISP_AWB_WINDOW_Y_NUMS + ); + return true; +} + bool isp_hal_awb_set_luminance_range(isp_hal_context_t *hal, uint32_t lum_min, uint32_t lum_max) { if (lum_min > lum_max || lum_max > ISP_LL_AWB_LUM_MAX_RANGE) { diff --git a/components/hal/spi_hal_iram.c b/components/hal/spi_hal_iram.c index 1b38660a58..35d6ecd4f9 100644 --- a/components/hal/spi_hal_iram.c +++ b/components/hal/spi_hal_iram.c @@ -235,6 +235,16 @@ bool spi_hal_usr_is_done(const spi_hal_context_t *hal) return spi_ll_usr_is_done(hal->hw); } +#if SOC_SPI_SUPPORT_SLAVE_HD_VER2 +bool spi_hal_get_intr_mask(spi_hal_context_t *hal, uint32_t mask) { + return spi_ll_get_intr(hal->hw, mask); +} + +void spi_hal_clear_intr_mask(spi_hal_context_t *hal, uint32_t mask) { + spi_ll_clear_intr(hal->hw, mask); +} +#endif + void spi_hal_push_tx_buffer(const spi_hal_context_t *hal, const spi_hal_trans_config_t *hal_trans) { if (hal_trans->send_buffer) { @@ -256,15 +266,7 @@ void spi_hal_fetch_result(const spi_hal_context_t *hal) #if SOC_SPI_SCT_SUPPORTED /*------------------------------------------------------------------------------ * Segmented-Configure-Transfer - *----------------------------------------------------------------------------*/ -void spi_hal_clear_intr_mask(spi_hal_context_t *hal, uint32_t mask) { - spi_ll_clear_intr(hal->hw, mask); -} - -bool spi_hal_get_intr_mask(spi_hal_context_t *hal, uint32_t mask) { - return spi_ll_get_intr(hal->hw, mask); -} - +*----------------------------------------------------------------------------*/ void spi_hal_sct_set_conf_bits_len(spi_hal_context_t *hal, uint32_t conf_len) { spi_ll_set_conf_phase_bits_len(hal->hw, conf_len); } diff --git a/components/nvs_flash/src/nvs_pagemanager.cpp b/components/nvs_flash/src/nvs_pagemanager.cpp index c5e3a17c69..e46e58b946 100644 --- a/components/nvs_flash/src/nvs_pagemanager.cpp +++ b/components/nvs_flash/src/nvs_pagemanager.cpp @@ -163,22 +163,25 @@ esp_err_t PageManager::requestNewPage() return ESP_ERR_NVS_NOT_ENOUGH_SPACE; } - esp_err_t err = activatePage(); + Page* erasedPage = maxUnusedItemsPageIt; + +#ifndef NDEBUG + size_t usedEntries = erasedPage->getUsedEntryCount(); +#endif + esp_err_t err = erasedPage->markFreeing(); + if (err != ESP_OK) { + return err; + } + + // Activating a new page first when markFreeing is done. The data recovery from power loss will be + // driven by the existence of the (transitional) FREEING state of a page. + err = activatePage(); if (err != ESP_OK) { return err; } Page* newPage = &mPageList.back(); - Page* erasedPage = maxUnusedItemsPageIt; - -#ifndef NDEBUG - size_t usedEntries = erasedPage->getUsedEntryCount(); -#endif - err = erasedPage->markFreeing(); - if (err != ESP_OK) { - return err; - } err = erasedPage->copyItems(*newPage); if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { return err; diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index c024a9ab02..00e4c382b5 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -779,6 +779,10 @@ config SOC_WIFI_FTM_SUPPORT bool default y +config SOC_WIFI_TXOP_SUPPORT + bool + default y + config SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW bool default y diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 6bd72b906f..f0e7f245c7 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -345,6 +345,7 @@ /*------------------------------------ WI-FI CAPS ------------------------------------*/ #define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ #define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ +#define SOC_WIFI_TXOP_SUPPORT (1) /*!< Support TXOP */ #define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */ #define SOC_WIFI_PHY_NEEDS_USB_WORKAROUND (1) /*!< SoC has WiFi and USB PHYs interference, needs a workaround */ diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 17e001cf11..076c7e1069 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -1139,6 +1139,10 @@ config SOC_WIFI_WAPI_SUPPORT bool default y +config SOC_WIFI_TXOP_SUPPORT + bool + default y + config SOC_WIFI_CSI_SUPPORT bool default y diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 7f7de46c61..c624192fdb 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -473,6 +473,7 @@ #define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ #define SOC_WIFI_GCMP_SUPPORT (1) /*!< Support GCMP(GCMP128 and GCMP256) */ #define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ +#define SOC_WIFI_TXOP_SUPPORT (1) /*!< Support TXOP */ #define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ #define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ #define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */ diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index ccf75e989d..47d23baf0b 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1727,10 +1727,6 @@ config SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN bool default y -config SOC_PM_TOP_PD_NOT_ALLOWED - bool - default y - config SOC_PM_PAU_LINK_NUM int default 5 @@ -1827,6 +1823,10 @@ config SOC_WIFI_WAPI_SUPPORT bool default y +config SOC_WIFI_TXOP_SUPPORT + bool + default y + config SOC_WIFI_CSI_SUPPORT bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index bb696ebb35..581831d1ce 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -664,7 +664,6 @@ #define SOC_PM_CPU_RETENTION_BY_SW (1) #define SOC_PM_MODEM_RETENTION_BY_REGDMA (1) #define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1) -#define SOC_PM_TOP_PD_NOT_ALLOWED (1) #define SOC_PM_PAU_LINK_NUM (5) #define SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE (1) @@ -701,6 +700,7 @@ #define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ #define SOC_WIFI_GCMP_SUPPORT (1) /*!< Support GCMP(GCMP128 and GCMP256) */ #define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ +#define SOC_WIFI_TXOP_SUPPORT (1) /*!< Support TXOP */ #define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ #define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ #define SOC_WIFI_HE_SUPPORT (1) /*!< Support Wi-Fi 6 */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 6e0a205e53..36c2bf2e26 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1591,6 +1591,10 @@ config SOC_WIFI_WAPI_SUPPORT bool default y +config SOC_WIFI_TXOP_SUPPORT + bool + default y + config SOC_WIFI_CSI_SUPPORT bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 1a3b8cb9cd..f0179b93a1 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -619,6 +619,7 @@ #define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ #define SOC_WIFI_GCMP_SUPPORT (1) /*!< Support GCMP(GCMP128 and GCMP256) */ #define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ +#define SOC_WIFI_TXOP_SUPPORT (1) /*!< Support TXOP */ #define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ #define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ #define SOC_WIFI_HE_SUPPORT (1) /*!< Support Wi-Fi 6 */ diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index a1a51f3dd2..542b058f90 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -1299,6 +1299,10 @@ config SOC_WIFI_WAPI_SUPPORT bool default y +config SOC_WIFI_TXOP_SUPPORT + bool + default y + config SOC_WIFI_CSI_SUPPORT bool default y diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 3ab56bcfc1..145d5d1168 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -518,6 +518,7 @@ #define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ #define SOC_WIFI_GCMP_SUPPORT (1) /*!< Support GCMP(GCMP128 and GCMP256) */ #define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ +#define SOC_WIFI_TXOP_SUPPORT (1) /*!< Support TXOP */ #define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ #define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ #define SOC_WIFI_HE_SUPPORT (1) /*!< Support Wi-Fi 6 */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 7c92228f8b..a2cf8b0233 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -1491,6 +1491,10 @@ config SOC_WIFI_WAPI_SUPPORT bool default y +config SOC_WIFI_TXOP_SUPPORT + bool + default y + config SOC_WIFI_CSI_SUPPORT bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 689435d105..8a393413b2 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -585,6 +585,7 @@ #define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ #define SOC_WIFI_GCMP_SUPPORT (1) /*!< Support GCMP(GCMP128 and GCMP256) */ #define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ +#define SOC_WIFI_TXOP_SUPPORT (1) /*!< Support TXOP */ #define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ #define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ #define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */ diff --git a/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py b/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py index 423e01c440..bd4087e03c 100644 --- a/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py +++ b/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py @@ -54,8 +54,8 @@ def test_esp_flash_multi(dut: Dut) -> None: @pytest.mark.parametrize( 'config, baud', [ - ('esp32c2_xtal26m', '74880'), - ('esp32c2_xtal26m_rom', '74880'), + ('c2_xtal26m', '74880'), + ('c2_xtal26m_rom', '74880'), ], indirect=True, ) diff --git a/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py b/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py index 09d1bda04d..624898ccae 100644 --- a/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py +++ b/components/spi_flash/test_apps/flash_suspend/pytest_flash_auto_suspend.py @@ -10,7 +10,6 @@ from pytest_embedded_idf.utils import idf_parametrize 'config', [ 'release', - 'i2c_isr_flash', 'text_in_flash_when_suspend', ], indirect=True, diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index cafc14a27b..4039ab4345 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -245,6 +245,7 @@ idf_component_register(SRCS "${srcs}" "${esp_srcs}" "${tls_src}" "${roaming_src} INCLUDE_DIRS include port/include esp_supplicant/include PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src src/crypto ../esp_wifi/wifi_apps/roaming_app/include + ../esp_wifi/wifi_apps/roaming_app/src LDFRAGMENTS ${linker_fragments} PRIV_REQUIRES mbedtls esp_timer esp_wifi) diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c index 6328136a91..61f8840729 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c @@ -252,31 +252,6 @@ cleanup: return res; } -int crypto_bignum_to_string(const struct crypto_bignum *a, - u8 *buf, size_t buflen, size_t padlen) -{ - int num_bytes, offset; - size_t outlen; - - if (padlen > buflen) { - return -1; - } - - num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a); - - if (padlen > (size_t) num_bytes) { - offset = padlen - num_bytes; - } else { - offset = 0; - } - - os_memset(buf, 0, offset); - mbedtls_mpi_write_string((mbedtls_mpi *) a, 16, (char *)(buf + offset), - mbedtls_mpi_size((mbedtls_mpi *)a), &outlen); - - return outlen; -} - int crypto_bignum_addmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index 04a9a9a27a..239aacc971 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -24,6 +24,7 @@ #include "rsn_supp/wpa.h" #include "esp_private/wifi.h" #include "esp_wifi_types_generic.h" +#include "esp_roaming.h" /* Utility Functions */ esp_err_t esp_supplicant_str_to_mac(const char *str, uint8_t dest[6]) @@ -168,6 +169,9 @@ static int handle_assoc_frame(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 channel) { if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (len < 6) { /* Cap info + status code */ + return -1; + } if (gWpaSm.ft_protocol) { if (wpa_ft_validate_reassoc_resp(&gWpaSm, frame + 6, len - 6, sender)) { wpa_sm_set_ft_params(&gWpaSm, NULL, 0); @@ -660,6 +664,9 @@ void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, config->sta.channel = bss->channel; /* supplicant connect will only be called in case of bss transition(roaming) */ esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC); +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP + esp_wifi_roaming_set_current_bssid(bss->bssid); +#endif esp_wifi_set_config(WIFI_IF_STA, config); os_free(config); esp_wifi_connect(); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c index bd8e11a44f..ad59b8a913 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c @@ -264,7 +264,7 @@ static void gas_query_timeout(void *eloop_data, void *user_ctx) { struct dpp_authentication *auth = user_ctx; - if (!auth || !auth->auth_success) { + if (!s_dpp_ctx.dpp_auth || !s_dpp_ctx.dpp_auth->auth_success || (s_dpp_ctx.dpp_auth != auth)) { wpa_printf(MSG_INFO, "DPP-GAS: Auth %p state not correct", auth); return; } @@ -408,6 +408,10 @@ static esp_err_t esp_dpp_rx_peer_disc_resp(struct action_rx_param *rx_param) return ESP_ERR_INVALID_ARG; } + if (rx_param->vendor_data_len < 2) { + wpa_printf(MSG_INFO, "DPP: Too short vendor specific data"); + return ESP_FAIL; + } size_t len = rx_param->vendor_data_len - 2; buf = rx_param->action_frm->u.public_action.v.pa_vendor_spec.vendor_data; @@ -542,28 +546,38 @@ static esp_err_t gas_query_resp_rx(struct action_rx_param *rx_param) { struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; uint8_t *pos = rx_param->action_frm->u.public_action.v.pa_gas_resp.data; - uint8_t *resp = &pos[10]; + uint8_t *resp = &pos[10]; /* first byte of DPP attributes */ + size_t vendor_len = rx_param->vendor_data_len; int i, res; - if (pos[1] == WLAN_EID_VENDOR_SPECIFIC && pos[2] == 5 && - WPA_GET_BE24(&pos[3]) == OUI_WFA && pos[6] == 0x1a && pos[7] == 1 && auth) { + /* Basic structural checks on the Advertisement Protocol payload */ + if (!(pos[1] == WLAN_EID_VENDOR_SPECIFIC && pos[2] == 5 && + WPA_GET_BE24(&pos[3]) == OUI_WFA && pos[6] == 0x1a && pos[7] == 1 && auth)) { + wpa_hexdump(MSG_INFO, "DPP: Failed, Configuration Response adv_proto", pos, 8); + return ESP_OK; + } - eloop_cancel_timeout(gas_query_timeout, NULL, auth); - if (dpp_conf_resp_rx(auth, resp, rx_param->vendor_data_len - 2) < 0) { - wpa_printf(MSG_INFO, "DPP: Configuration attempt failed"); + /* DPP attribute length = vendor_data_len - 2, caller validated vendor_data_len + * (we skip the 2-byte length field and pass only the attributes). */ + size_t dpp_data_len = vendor_len - 2; + + eloop_cancel_timeout(gas_query_timeout, NULL, auth); + + if (dpp_conf_resp_rx(auth, resp, dpp_data_len) < 0) { + wpa_printf(MSG_INFO, "DPP: Configuration attempt failed"); + goto fail; + } + + for (i = 0; i < auth->num_conf_obj; i++) { + res = esp_dpp_handle_config_obj(auth, &auth->conf_obj[i]); + if (res < 0) { + wpa_printf(MSG_INFO, "DPP: Configuration parsing failed"); goto fail; } - - for (i = 0; i < auth->num_conf_obj; i++) { - res = esp_dpp_handle_config_obj(auth, &auth->conf_obj[i]); - if (res < 0) { - wpa_printf(MSG_INFO, "DPP: Configuration parsing failed"); - goto fail; - } - } } return ESP_OK; + fail: return ESP_FAIL; } @@ -853,11 +867,17 @@ static char *esp_dpp_parse_chan_list(const char *chan_list) } char *uri_ptr = uri_channels; + size_t current_offset = 0; // Use an offset to track current position params->num_chan = 0; /* Append " chan=" at the beginning of the URI */ - strcpy(uri_ptr, " chan="); - uri_ptr += strlen(" chan="); + int written = os_snprintf(uri_ptr + current_offset, max_uri_len - current_offset, " chan="); + if (written < 0 || written >= max_uri_len - current_offset) { // Check for error or truncation + wpa_printf(MSG_ERROR, "DPP: URI buffer too small for initial string"); + os_free(uri_channels); + return NULL; + } + current_offset += written; while (*chan_list && params->num_chan < ESP_DPP_MAX_CHAN_COUNT) { int channel = 0; @@ -892,16 +912,23 @@ static char *esp_dpp_parse_chan_list(const char *chan_list) /* Add the valid channel to the list */ params->chan_list[params->num_chan++] = channel; - /* Check if there's space left in uri_channels buffer */ - size_t remaining_space = max_uri_len - (uri_ptr - uri_channels); - if (remaining_space <= 8) { // Oper class + "/" + channel + "," + null terminator - wpa_printf(MSG_ERROR, "DPP: Not enough space in URI buffer"); + // Calculate space needed for current channel string (e.g., "81/1,") + int needed_for_channel = os_snprintf(NULL, 0, "%d/%d,", oper_class, channel); + + if (current_offset + needed_for_channel + 1 > max_uri_len) { // +1 for null terminator + wpa_printf(MSG_ERROR, "DPP: Not enough space in URI buffer for channel %d", channel); os_free(uri_channels); return NULL; } /* Append the operating class and channel to the URI */ - uri_ptr += sprintf(uri_ptr, "%d/%d,", oper_class, channel); + written = os_snprintf(uri_ptr + current_offset, max_uri_len - current_offset, "%d/%d,", oper_class, channel); + if (written < 0 || written >= max_uri_len - current_offset) { // Check for error or truncation + wpa_printf(MSG_ERROR, "DPP: Error writing channel %d to URI buffer", channel); + os_free(uri_channels); + return NULL; + } + current_offset += written; /* Skip any delimiters (comma or space) */ while (*chan_list == ',' || *chan_list == ' ') { @@ -916,8 +943,8 @@ static char *esp_dpp_parse_chan_list(const char *chan_list) } /* Replace the last comma with a space if there was content added */ - if (uri_ptr > uri_channels && *(uri_ptr - 1) == ',') { - *(uri_ptr - 1) = ' '; + if (current_offset > strlen(" chan=") && uri_ptr[current_offset - 1] == ',') { + uri_ptr[current_offset - 1] = ' '; } return uri_channels; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index da162f0ee5..d1d107a3fe 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -199,7 +199,8 @@ void *hostap_init(void) } #endif /* CONFIG_SAE */ - os_memcpy(hapd->conf->ssid.wpa_passphrase, esp_wifi_ap_get_prof_password_internal(), strlen((char *)esp_wifi_ap_get_prof_password_internal())); + os_snprintf(hapd->conf->ssid.wpa_passphrase, WIFI_PASSWORD_LEN_MAX, + "%s", esp_wifi_ap_get_prof_password_internal()); hapd->conf->ssid.wpa_passphrase[WIFI_PASSWORD_LEN_MAX - 1] = '\0'; hapd->conf->max_num_sta = esp_wifi_ap_get_max_sta_conn(); auth_conf->transition_disable = esp_wifi_ap_get_transition_disable_internal(); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index c9b09881ee..21a7c4e379 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -333,8 +333,16 @@ static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status) wpa_printf(MSG_ERROR, "Invalid SAE anti-clogging token container header"); return ESP_FAIL; } + if (len < 5) { + wpa_printf(MSG_ERROR, "Invalid SAE anti-clogging token length"); + return ESP_FAIL; + } g_sae_token = wpabuf_alloc_copy(buf + 5, len - 5); } else { + if (len < 2) { + wpa_printf(MSG_ERROR, "Invalid SAE anti-clogging token length"); + return ESP_FAIL; + } g_sae_token = wpabuf_alloc_copy(buf + 2, len - 2); } return ESP_OK; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index 2490a4003a..b0333289ad 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -31,6 +31,7 @@ #include "esp_eap_client.h" #include "esp_common_i.h" #include "esp_owe_i.h" +#include "esp_roaming.h" #include "esp_wps.h" #include "esp_wps_i.h" @@ -140,6 +141,9 @@ bool wpa_attach(void) ret = (esp_wifi_register_eapol_txdonecb_internal(eapol_txcb) == ESP_OK); } esp_set_scan_ie(); +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP + roam_init_app(); +#endif return ret; } @@ -192,6 +196,9 @@ void wpa_ap_get_peer_spp_msg(void *sm_data, bool *spp_cap, bool *spp_req) bool wpa_deattach(void) { struct wpa_sm *sm = &gWpaSm; +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP + roam_deinit_app(); +#endif esp_wpa3_free_sae_data(); #ifdef CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT if (sm->wpa_sm_eap_disable) { diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c index 948f271397..42cbbe92d8 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c @@ -189,4 +189,9 @@ void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code) { /*check if need clear internal state and data value*/ } + +u8 wpa_supplicant_get_transition_disable(void) +{ + return wpa_sm_get_transition_disable(&gWpaSm); +} #endif diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h index 48ff0a6379..1a1d57993b 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,8 @@ #ifndef WPAS_GLUE_H #define WPAS_GLUE_H +#include "rsn_supp/wpa_i.h" + u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos); @@ -35,4 +37,6 @@ void wpa_supplicant_transition_disable(struct wpa_sm *sm, u8 bitmap); int hostapd_send_eapol(const u8 *source, const u8 *sta_addr, const u8 *data, size_t data_len); + +u8 wpa_supplicant_get_transition_disable(void); #endif /* WPAS_GLUE_H */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c index 186571237a..26413edc29 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c @@ -389,8 +389,8 @@ static int wps_enrollee_process_msg_frag(struct wpabuf **buf, int tot_len, u8 *f identifier = sm->current_identifier; if (*buf == NULL) { - if (0 == (flag & WPS_MSG_FLAG_LEN) || tot_len < frag_len) { - wpa_printf(MSG_ERROR, "WPS: %s: Invalid fragment flag: 0x%02x", __FUNCTION__, flag); + if (frag_len < 0 || tot_len < frag_len) { + wpa_printf(MSG_ERROR, "WPS: Invalid first fragment length"); return ESP_FAIL; } @@ -405,9 +405,17 @@ static int wps_enrollee_process_msg_frag(struct wpabuf **buf, int tot_len, u8 *f if (flag & WPS_MSG_FLAG_LEN) { wpa_printf(MSG_ERROR, "WPS: %s: Invalid fragment flag: 0x%02x", __func__, flag); + wpabuf_free(*buf); + *buf = NULL; return ESP_FAIL; } + if (frag_len < 0 || wpabuf_len(*buf) + frag_len > tot_len) { + wpa_printf(MSG_ERROR, "WPS: Invalid subsequent fragment length"); + wpabuf_free(*buf); + *buf = NULL; + return ESP_FAIL; + } wpabuf_put_data(*buf, frag_data, frag_len); if (flag & WPS_MSG_FLAG_MORE) { @@ -445,6 +453,10 @@ static int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) return ESP_FAIL; } + if (len < (int)(sizeof(struct eap_expand) + 1)) { + wpa_printf(MSG_ERROR, "WPS: Truncated EAP-Expanded header"); + return ESP_FAIL; + } expd = (struct eap_expand *) ubuf; wpa_printf(MSG_DEBUG, "WPS: Processing WSC message (len=%d, total_len=%d)", len, tlen); @@ -463,7 +475,11 @@ static int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) flag = *(u8 *)(ubuf + sizeof(struct eap_expand)); if (flag & WPS_MSG_FLAG_LEN) { - tbuf = ubuf + sizeof(struct eap_expand) + 1 + 2;//two bytes total length + if (len < (int)(sizeof(struct eap_expand) + 1 + 2)) { + wpa_printf(MSG_ERROR, "WPS: Missing total length field"); + return ESP_FAIL; + } + tbuf = ubuf + sizeof(struct eap_expand) + 1 + 2; // includes 2-byte total length frag_len = len - (sizeof(struct eap_expand) + 1 + 2); be_tot_len = *(u16 *)(ubuf + sizeof(struct eap_expand) + 1); tlen = ((be_tot_len & 0xff) << 8) | ((be_tot_len >> 8) & 0xff); @@ -473,6 +489,15 @@ static int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) tlen = frag_len; } + if (frag_len < 0 || tlen < 0 || ((flag & WPS_MSG_FLAG_LEN) && tlen < frag_len)) { + wpa_printf(MSG_ERROR, "WPS: Invalid fragment sizes"); + if (wps_buf) { + wpabuf_free(wps_buf); + wps_buf = NULL; + } + return ESP_FAIL; + } + if (tlen > 50000) { wpa_printf(MSG_ERROR, "WPS: Invalid EAP-WSC message length"); return ESP_FAIL; diff --git a/components/wpa_supplicant/src/ap/sta_info.c b/components/wpa_supplicant/src/ap/sta_info.c index 0894486373..28daefb547 100644 --- a/components/wpa_supplicant/src/ap/sta_info.c +++ b/components/wpa_supplicant/src/ap/sta_info.c @@ -173,15 +173,14 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) /* initialize STA info data */ os_memcpy(sta->addr, addr, ETH_ALEN); sta->next = hapd->sta_list; - hapd->sta_list = sta; - hapd->num_sta++; - ap_sta_hash_add(hapd, sta); #ifdef CONFIG_SAE sta->sae_commit_processing = false; sta->remove_pending = false; sta->lock = os_semphr_create(1, 1); #endif /* CONFIG_SAE */ - + hapd->sta_list = sta; + hapd->num_sta++; + ap_sta_hash_add(hapd, sta); return sta; } diff --git a/components/wpa_supplicant/src/crypto/crypto.h b/components/wpa_supplicant/src/crypto/crypto.h index 7946e6be16..b65b00809b 100644 --- a/components/wpa_supplicant/src/crypto/crypto.h +++ b/components/wpa_supplicant/src/crypto/crypto.h @@ -1141,17 +1141,6 @@ void crypto_free_buffer(unsigned char *buf); */ int crypto_ec_get_priv_key_der(struct crypto_ec_key *key, unsigned char **key_data, int *key_len); -/** - * crypto_bignum_to_string: get big number in ascii format - * @a: big number - * @buf: buffer in which number will written to - * @buflen: buffer length - * @padlen: padding length - * Return : 0 if success - */ -int crypto_bignum_to_string(const struct crypto_bignum *a, - u8 *buf, size_t buflen, size_t padlen); - struct crypto_ecdh; void crypto_ecdh_deinit(struct crypto_ecdh *ecdh); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 75fe1f5094..4dfcd00a41 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -1340,6 +1340,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (ie.transition_disable) { wpa_supplicant_transition_disable(sm, ie.transition_disable[0]); + sm->transition_disable = ie.transition_disable[0]; } if (sm->key_install && sm->key_info & WPA_KEY_INFO_INSTALL && sm->use_ext_key_id) { @@ -1357,6 +1358,11 @@ failed: wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); } +u8 wpa_sm_get_transition_disable(struct wpa_sm *sm) +{ + return sm->transition_disable; +} + static int wpa_supplicant_activate_ptk(struct wpa_sm *sm) { int keylen; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index b31aeb1e1a..909073e610 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -9,6 +9,8 @@ #ifndef WPA_I_H #define WPA_I_H +#include "common/defs.h" + extern struct wpa_sm gWpaSm; #define DEFAULT_EAPOL_VERSION 1 @@ -86,6 +88,7 @@ struct wpa_sm { struct wpa_gtk_data gd; //used for calllback save param u16 key_info; //used for txcallback param u16 txcb_flags; + u8 transition_disable; bool ap_notify_completed_rsne; wifi_pmf_config_t pmf_cfg; u8 eapol1_count; @@ -208,6 +211,8 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); +u8 wpa_sm_get_transition_disable(struct wpa_sm *sm); + int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk); #endif /* WPA_I_H */ diff --git a/docs/conf_common.py b/docs/conf_common.py index 7637498e78..5278e0c685 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -34,6 +34,7 @@ BLE_DOCS = [ 'api-guides/ble/ble-feature-support-status.rst', 'api-guides/ble/host-feature-support-status.rst', 'api-guides/ble/ble-qualification.rst', + 'api-guides/ble/ble-multiconnection-guide.rst', 'api-guides/ble/get-started/ble-introduction.rst', 'api-guides/ble/get-started/ble-device-discovery.rst', 'api-guides/ble/get-started/ble-connection.rst', diff --git a/docs/docs_not_updated/esp32c5.txt b/docs/docs_not_updated/esp32c5.txt index 8f54062766..16b8b961f3 100644 --- a/docs/docs_not_updated/esp32c5.txt +++ b/docs/docs_not_updated/esp32c5.txt @@ -1,5 +1,3 @@ -api-guides/low-power-mode.rst -api-guides/deep-sleep-stub.rst api-guides/inc/external-ram-esp32-notes.rst api-reference/storage/vfs.rst api-reference/storage/spiffs.rst diff --git a/docs/en/api-guides/ble/ble-multiconnection-guide.rst b/docs/en/api-guides/ble/ble-multiconnection-guide.rst new file mode 100644 index 0000000000..38f0c1cb43 --- /dev/null +++ b/docs/en/api-guides/ble/ble-multiconnection-guide.rst @@ -0,0 +1,63 @@ +Multi-Connection Guide +========================================== + +:link_to_translation:`zh_CN:[中文]` + +Introduction +-------------- + +The following table provides an overview of the maximum number of concurrent connections supported for each ESP Bluetooth LE Host. In multi-connection scenarios, connection parameters must be configured appropriately. In general, as the number of connections increases, the connection interval should be increased accordingly. For detailed parameter configuration recommendations and SDK configuration details, please refer to the corresponding example code in the following table. + +In this document, the maximum number of connections refers to the maximum number of simultaneous active connections that the device can maintain, whether operating as a central or peripheral. + +.. table:: Maximum Concurrent Connections by ESP Bluetooth LE Host + + +---------------+-----------------------------+------------------------------+---------------------+ + | Host | Max Connections | SDKconfig | Example | + +===============+=============================+==============================+=====================+ + | | | |bluedroid_enable_config| | | + | ESP-Bluedroid | |max_bluedroid_connections| | | |bluedroid_example| | + | | | |bluedroid_connection_num| | | + +---------------+-----------------------------+------------------------------+---------------------+ + | ESP-NimBLE | |max_nimble_connections| | |nimble_connection_num| | |nimble_example| | + +---------------+-----------------------------+------------------------------+---------------------+ + + +Note +---- + +1. The ability to support multiple connections highly depends on the application’s overall memory usage. It is recommended to disable unnecessary features to optimize multi-connection performance. + +2. When the device operates in the peripheral role, connection stability and overall performance will be influenced by the central device and the negotiated connection parameters. + +.. only:: not esp32 and not esp32c3 and not esp32s3 and not esp32c2 + + 3. Due to the relatively higher memory usage of ESP-Bluedroid, it supports fewer concurrent connections compared to ESP-Nimble. + + 4. If your application requires more simultaneous connections than the values listed above, please contact our `customer support team `__ for further assistance. + +.. |bluedroid_enable_config| replace:: :ref:`BT_MULTI_CONNECTION_ENBALE ` +.. |bluedroid_connection_num| replace:: :ref:`BT_ACL_CONNECTIONS ` +.. |bluedroid_example| replace:: :example:`multi_conn ` +.. |nimble_connection_num| replace:: :ref:`BT_NIMBLE_MAX_CONNECTIONS ` +.. |nimble_example| replace:: :example:`multi_conn` + +.. only:: esp32 or esp32c3 or esp32s3 + + .. |max_bluedroid_connections| replace:: 9 + .. |max_nimble_connections| replace:: 9 + +.. only:: esp32c2 + + .. |max_bluedroid_connections| replace:: 2 + .. |max_nimble_connections| replace:: 2 + +.. only:: esp32h2 + + .. |max_bluedroid_connections| replace:: 15 + .. |max_nimble_connections| replace:: 70 + +.. only:: esp32c6 or esp32c5 or esp32c61 + + .. |max_bluedroid_connections| replace:: 50 + .. |max_nimble_connections| replace:: 70 diff --git a/docs/en/api-guides/ble/index.rst b/docs/en/api-guides/ble/index.rst index e9deeee59f..1663f253f9 100644 --- a/docs/en/api-guides/ble/index.rst +++ b/docs/en/api-guides/ble/index.rst @@ -14,6 +14,7 @@ Overview ble-feature-support-status ble-qualification Low Power Mode Introduction <../low-power-mode/low-power-mode-ble> + ble-multiconnection-guide *************** Get Started diff --git a/docs/en/api-guides/low-power-mode/low-power-mode-soc.rst b/docs/en/api-guides/low-power-mode/low-power-mode-soc.rst index 792d7bdabd..56a3f86b8d 100644 --- a/docs/en/api-guides/low-power-mode/low-power-mode-soc.rst +++ b/docs/en/api-guides/low-power-mode/low-power-mode-soc.rst @@ -218,10 +218,10 @@ Recommended Configuration - 1000 * - ``max_freq_mhz`` - - 160 + - The maximum CPU frequency supported by {IDF_TARGET_NAME} * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - false @@ -288,6 +288,14 @@ This section introduces the recommended configuration and configuration steps fo Due to the shared power pins between flash and PSRAM, cutting power to PSRAM would result in data loss. Therefore, to ensure light sleep does not disrupt program execution, enabling this option requires that the system does not utilize PSRAM. +.. only:: SOC_PM_SUPPORT_TOP_PD + + - Power down Digital Peripheral modules and all child power domains under the TOP power domain in light sleep (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH`) + +.. only:: SOC_PM_SUPPORT_RTC_PERIPH_PD + + - Power down the RTC digital peripheral module. Automatically powered down the RTC digital peripherals during system sleep is the default system power management policy. Users can call `esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)` to enable the RTC digital peripheral module while in sleep mode. + .. only:: esp32c2 - To reduce the on-chip RAM usage of the Power Management module (:ref:CONFIG_PM_SLEEP_FUNC_IN_IRAM), the options in the table below are used to control whether individual components of the Power Management module enable or disable on-chip RAM optimization when :ref:CONFIG_PM_SLEEP_FUNC_IN_IRAM is disabled. @@ -335,7 +343,7 @@ Configuration Steps: Recommended Configuration +++++++++++++++++++++++++++++ -.. only:: esp32c3 or esp32s3 +.. only:: esp32c6 or esp32c5 .. list-table:: :header-rows: 1 @@ -374,20 +382,125 @@ Recommended Configuration * - Power down CPU (:ref:`CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP`) - ON -.. only:: SOC_PM_SUPPORT_TAGMEM_PD + * - Power down flash in light sleep (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH`) + - OFF + + * - ``max_freq_mhz`` + - The maximum CPU frequency supported by {IDF_TARGET_NAME} + + * - ``min_freq_mhz`` + - {CONFIG_XTAL_FREQ} + + * - ``light_sleep_enable`` + - true + + .. note:: + Configurations not mentioned in the above table are set to default. + +.. only:: esp32s3 + + .. list-table:: + :header-rows: 1 + :widths: 30 15 + + * - Configuration Name + - Configuration Status + + * - Enable power management component (:ref:`CONFIG_PM_ENABLE`) + - ON + + * - Enable RTOS Tickless IDLE mode (:ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE`) + - ON + + * - RTOS Tick rate (Hz) (:ref:`CONFIG_FREERTOS_HZ`) + - 1000 + + * - Minimum IDLE Tick count before entering sleep mode (:ref:`CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP`) + - 3 + + * - Put light sleep related codes in IRAM (:ref:`CONFIG_PM_SLP_IRAM_OPT`) + - OFF + + * - Put RTOS IDLE related codes in IRAM (:ref:`CONFIG_PM_RTOS_IDLE_OPT`) + - OFF + + * - RTC slow clock source (:ref:`CONFIG_RTC_CLK_SRC`) + - Internal 150 kHz OSC + + * - Disable all GPIO when chip at sleep (:ref:`CONFIG_PM_SLP_DISABLE_GPIO`) + - ON + + * - Power down MAC and baseband (:ref:`CONFIG_ESP_PHY_MAC_BB_PD`) + - ON + + * - Power down CPU (:ref:`CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP`) + - ON * - Power down I/D-cache tag memory (:ref:`CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP`) - ON - * - Power down flash in light sleep (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH`) - OFF * - ``max_freq_mhz`` - - 160 + - The maximum CPU frequency supported by {IDF_TARGET_NAME} * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} + + * - ``light_sleep_enable`` + - true + + .. note:: + Configurations not mentioned in the above table are set to default. + +.. only:: esp32c3 + + .. list-table:: + :header-rows: 1 + :widths: 30 15 + + * - Configuration Name + - Configuration Status + + * - Enable power management component (:ref:`CONFIG_PM_ENABLE`) + - ON + + * - Enable RTOS Tickless IDLE mode (:ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE`) + - ON + + * - RTOS Tick rate (Hz) (:ref:`CONFIG_FREERTOS_HZ`) + - 1000 + + * - Minimum IDLE Tick count before entering sleep mode (:ref:`CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP`) + - 3 + + * - Put light sleep related codes in IRAM (:ref:`CONFIG_PM_SLP_IRAM_OPT`) + - OFF + + * - Put RTOS IDLE related codes in IRAM (:ref:`CONFIG_PM_RTOS_IDLE_OPT`) + - OFF + + * - RTC slow clock source (:ref:`CONFIG_RTC_CLK_SRC`) + - Internal 150 kHz OSC + + * - Disable all GPIO when chip at sleep (:ref:`CONFIG_PM_SLP_DISABLE_GPIO`) + - ON + + * - Power down MAC and baseband (:ref:`CONFIG_ESP_PHY_MAC_BB_PD`) + - ON + + * - Power down CPU (:ref:`CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP`) + - ON + + * - Power down flash in light sleep (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH`) + - OFF + + * - ``max_freq_mhz`` + - The maximum CPU frequency supported by {IDF_TARGET_NAME} + + * - ``min_freq_mhz`` + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - true @@ -432,7 +545,7 @@ Recommended Configuration - 160 * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - true @@ -480,7 +593,7 @@ Recommended Configuration - 120 * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - true diff --git a/docs/en/api-guides/low-power-mode/low-power-mode-wifi.rst b/docs/en/api-guides/low-power-mode/low-power-mode-wifi.rst index c09170b364..7ab7eecadf 100644 --- a/docs/en/api-guides/low-power-mode/low-power-mode-wifi.rst +++ b/docs/en/api-guides/low-power-mode/low-power-mode-wifi.rst @@ -5,9 +5,9 @@ Introduction to Low Power Mode in Wi-Fi Scenarios After the previous introduction to low power mode from a systemic perspective, this section delves into low power mode in Wi-Fi scenarios. Due to the complexity of Wi-Fi scenarios, basic principles of Wi-Fi power saving will be introduced before specific low power mode. This section is focused on station mode. -.. todo - add sleep-current/esp32c5_summary.inc and sleep-current/esp32c61_summary.inc +.. todo - add sleep-current/esp32c61_summary.inc -.. only:: not esp32c5 and not esp32c61 +.. only:: not esp32c61 Choosing Low Power Mode in Wi-Fi Scenarios --------------------------------------------- @@ -355,17 +355,17 @@ Modem-sleep Mode Configuration - 1000 * - ``max_freq_mhz`` - - 160 + - The maximum CPU frequency supported by {IDF_TARGET_NAME} * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - false - .. todo - add sleep-current/esp32c5_modem_sleep.inc sleep-current/esp32c61_modem_sleep.inc + .. todo - add sleep-current/esp32c61_modem_sleep.inc - .. only:: not esp32c5 and not esp32c61 + .. only:: not esp32c61 - Configuration Performance @@ -377,9 +377,9 @@ Auto Light-sleep Mode + Wi-Fi Scenario Configuration Auto Light-sleep mode in Wi-Fi scenarios does not require wake-up source configuration compared with a pure system. But the remaining part of configuration is basically the same in the two operation scenarios. Therefore, detailed introduction of configurable options, configuration steps, and recommended configurations can be found in the previous section :ref:`Deep-sleep Mode`, with the Wi-Fi-related configurations set to default. -.. todo - add sleep-current/esp32c5_light_sleep.inc and leep-current/esp32c61_light_sleep.inc +.. todo - add eep-current/esp32c61_light_sleep.inc -.. only:: not esp32c5 and not esp32c61 +.. only:: not esp32c61 - Configuration Performance @@ -415,3 +415,11 @@ Deep-sleep mode configuration in Wi-Fi scenarios is essentially the same as in a .. only:: esp32c2 Average current approximately 4.9 μA + + .. only:: esp32c6 + + Average current approximately 6.7 μA + + .. only:: esp32c5 + + Average current approximately 10.0 μA diff --git a/docs/en/api-guides/sleep-current/esp32c5_light_sleep.inc b/docs/en/api-guides/sleep-current/esp32c5_light_sleep.inc new file mode 100644 index 0000000000..5577f33535 --- /dev/null +++ b/docs/en/api-guides/sleep-current/esp32c5_light_sleep.inc @@ -0,0 +1,27 @@ +.. list-table:: + :header-rows: 1 + :widths: 20 10 20 20 20 + + * - CPU frequency + - DTIM + - Average current (mA) + - Max current (mA) + - Min current (mA) + + * - 240 MHz + - 1 + - 1.342 + - 80.375 + - 0.218 + + * - 240 MHz + - 3 + - 0.651 + - 81.179 + - 0.219 + + * - 240 MHz + - 10 + - 0.398 + - 80.518 + - 0.217 diff --git a/docs/en/api-guides/sleep-current/esp32c5_modem_sleep.inc b/docs/en/api-guides/sleep-current/esp32c5_modem_sleep.inc new file mode 100644 index 0000000000..b0e551ce6c --- /dev/null +++ b/docs/en/api-guides/sleep-current/esp32c5_modem_sleep.inc @@ -0,0 +1,107 @@ +.. list-table:: + :header-rows: 1 + :widths: 20 10 10 20 24 20 20 + + * - CPU frequency + - DFS + - DTIM + - Wi-Fi Band + - Average current (mA) + - Max current (mA) + - Min current (mA) + + * - 240 MHz + - ON + - 1 + - 2.4 GHz + - 24.766 + - 88.836 + - 23.139 + + * - 240 MHz + - OFF + - 1 + - 2.4 GHz + - 32.394 + - 97.378 + - 30.776 + + * - 240 MHz + - ON + - 3 + - 2.4 GHz + - 24.19 + - 89.176 + - 23.229 + + * - 240 MHz + - OFF + - 3 + - 2.4 GHz + - 31.618 + - 97.439 + - 30.778 + + * - 240 MHz + - ON + - 10 + - 2.4 GHz + - 23.998 + - 88.524 + - 23.252 + + * - 240 MHz + - OFF + - 10 + - 2.4 GHz + - 31.281 + - 98.254 + - 30.788 + + * - 240 MHz + - ON + - 1 + - 5 GHz + - 25.467 + - 114.746 + - 24.387 + + * - 240 MHz + - OFF + - 1 + - 5 GHz + - 32.329 + - 117.077 + - 31.948 + + * - 240 MHz + - ON + - 3 + - 5 GHz + - 25.208 + - 112.746 + - 24.421 + + * - 240 MHz + - OFF + - 3 + - 5 GHz + - 32.088 + - 117.227 + - 31.948 + + * - 240 MHz + - ON + - 10 + - 5 GHz + - 25.151 + - 114.438 + - 24.432 + + * - 160 MHz + - OFF + - 10 + - 5 GHz + - 32.011 + - 119.908 + - 31.955 diff --git a/docs/en/api-guides/sleep-current/esp32c5_summary.inc b/docs/en/api-guides/sleep-current/esp32c5_summary.inc new file mode 100644 index 0000000000..4df10c0851 --- /dev/null +++ b/docs/en/api-guides/sleep-current/esp32c5_summary.inc @@ -0,0 +1,87 @@ +.. list-table:: + :header-rows: 1 + :widths: 20 20 30 20 20 + + * - Item + - Modem-sleep + - Modem-sleep+DFS + - Auto Light-sleep + - Deep-sleep + + * - Sleep + - Automatic + - Automatic + - Automatic + - Manual + + * - Wake-up + - Automatic + - Automatic + - Automatic + - Configure Wake-up Source + + * - Wi-Fi Connection + - Maintain + - Maintain + - Maintain + - Disconnect + + * - CPU + - On + - On/Throttled + - Paused + - Off + + * - System Clock + - On + - On + - Off + - Off + + * - Peripherals + - On + - On + - On + - Off + + * - DTIM1 (2.4 GHz) + - 32.394 mA + - 24.766 mA + - 1.342 mA + - / + + * - DTIM1 (5 GHz) + - 32.329 mA + - 25.467 mA + - 1.514 mA + - / + + * - DTIM3 (2.4 GHz) + - 31.618 mA + - 24.19 mA + - 0.651 mA + - / + + * - DTIM3 (5 GHz) + - 32.088 mA + - 25.208 mA + - 0.764 mA + - / + + * - DTIM10 (2.4 GHz) + - 31.281 mA + - 23.998 mA + - 0.398 mA + - / + + * - DTIM10 (5 GHz) + - 32.011 mA + - 25.151 mA + - 0.451 mA + - / + + * - Average Current + - / + - / + - / + - 10.0 μA diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index d3e759e3e9..b76ac861ab 100644 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -2925,11 +2925,11 @@ Wi-Fi AMSDU Wi-Fi Fragment ------------------------- -.. only:: esp32 or esp32s2 +.. only:: not SOC_WIFI_TXOP_SUPPORT supports Wi-Fi receiving fragment, but does not support Wi-Fi transmitting fragment. -.. only:: esp32c3 or esp32s3 or esp32c5 or esp32c6 +.. only:: SOC_WIFI_TXOP_SUPPORT {IDF_TARGET_NAME} supports Wi-Fi receiving and transmitting fragment. diff --git a/docs/en/api-reference/bluetooth/esp_a2dp.rst b/docs/en/api-reference/bluetooth/esp_a2dp.rst index efed7e5e58..8e1105e258 100644 --- a/docs/en/api-reference/bluetooth/esp_a2dp.rst +++ b/docs/en/api-reference/bluetooth/esp_a2dp.rst @@ -1,10 +1,15 @@ Bluetooth® A2DP API =================== +Overview +-------- + +A2DP (Advanced Audio Distribution Profile) enables high-quality audio streaming from one device to another over Bluetooth. It is primarily used for streaming audio from source devices such as smartphones, computers, and media players to sink devices such as Bluetooth speakers, headphones, and car audio systems. Users can use the A2DP APIs to transmit or receive audio streams. + Application Examples -------------------- -- :example:`bluetooth/bluedroid/classic_bt/a2dp_sink` demonstrates how to implement an audio sink device using the Advanced Audio Distribution Profile (A2DP) to receive audio streams. This example also shows how to use AVRCP for media information notifications and I2S for audio stream output. +- :example:`bluetooth/bluedroid/classic_bt/a2dp_sink_stream` demonstrates how to implement an audio sink device using the Advanced Audio Distribution Profile (A2DP) to receive audio streams. This example also shows how to use I2S for audio stream output. - :example:`bluetooth/bluedroid/classic_bt/a2dp_source` demonstrates how to use A2DP APIs to transmit audio streams. diff --git a/docs/en/api-reference/bluetooth/esp_avrc.rst b/docs/en/api-reference/bluetooth/esp_avrc.rst index 10ad910382..4816e91b27 100644 --- a/docs/en/api-reference/bluetooth/esp_avrc.rst +++ b/docs/en/api-reference/bluetooth/esp_avrc.rst @@ -1,10 +1,19 @@ -Bluetooth® AVRCP APIs -===================== +Bluetooth® AVRCP API +==================== Overview -------- -Bluetooth AVRCP reference APIs. +AVRCP (Audio/Video Remote Control Profile) enables remote control of audio and video devices over Bluetooth, allowing users to manage playback (play, pause, next/previous track), adjust volume, and retrieve media metadata. + +Application Examples +-------------------- + +- :example:`bluetooth/bluedroid/classic_bt/avrcp_absolute_volume` demonstrates how to implement Audio/Video Remote Control Profile to control absolute volume. + +- :example:`bluetooth/bluedroid/classic_bt/avrcp_ct_metadata` demonstrates how to implement Audio/Video Remote Control Profile to get metadata. + +- :example:`bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art` demonstrates how to implement Audio/Video Remote Control Profile to get and display cover art image. API Reference ------------- diff --git a/docs/en/api-reference/bluetooth/esp_gap_bt.rst b/docs/en/api-reference/bluetooth/esp_gap_bt.rst index 7206eb7496..76fe246b4b 100644 --- a/docs/en/api-reference/bluetooth/esp_gap_bt.rst +++ b/docs/en/api-reference/bluetooth/esp_gap_bt.rst @@ -1,6 +1,11 @@ -Classic Bluetooth® GAP API +Bluetooth® Classic GAP API ========================== +Overview +-------- + +The Bluetooth Classic GAP (Generic Access Profile) API provides interfaces for device discovery, pairing, and security management, allowing applications to control visibility, initiate connections, and configure authentication and encryption for Bluetooth Classic links. + Application Examples -------------------- diff --git a/docs/en/api-reference/bluetooth/esp_hf_ag.rst b/docs/en/api-reference/bluetooth/esp_hf_ag.rst index ab15744144..64b3b40ba1 100644 --- a/docs/en/api-reference/bluetooth/esp_hf_ag.rst +++ b/docs/en/api-reference/bluetooth/esp_hf_ag.rst @@ -1,5 +1,10 @@ -HFP AG API -============== +Bluetooth® HFP AG API +===================== + +Overview +-------- + +HFP (Hands-Free Profile) AG API provides functions for a Bluetooth device to act as an Audio Gateway (AG), enabling communication with HFP Client devices such as headsets or car kits. It supports connection management, call handling, volume control, and other hands-free operations. Application Examples -------------------- diff --git a/docs/en/api-reference/bluetooth/esp_hf_client.rst b/docs/en/api-reference/bluetooth/esp_hf_client.rst index ab28889212..816ee803db 100644 --- a/docs/en/api-reference/bluetooth/esp_hf_client.rst +++ b/docs/en/api-reference/bluetooth/esp_hf_client.rst @@ -1,5 +1,10 @@ -HFP Client API -============== +Bluetooth® HFP Client API +========================= + +Overview +-------- + +HFP (Hands-Free Profile) Client API provides functions to enable a Bluetooth device to act as an HFP Client, allowing communication with an Audio Gateway (AG) device, such as a smartphone, to handle voice calls, volume control, and other hands-free operations. Application Examples -------------------- diff --git a/docs/en/api-reference/bluetooth/esp_hf_defs.rst b/docs/en/api-reference/bluetooth/esp_hf_defs.rst index 4f9d3f9d2b..400f11a40d 100644 --- a/docs/en/api-reference/bluetooth/esp_hf_defs.rst +++ b/docs/en/api-reference/bluetooth/esp_hf_defs.rst @@ -1,5 +1,17 @@ -HFP Defines -=========== +Bluetooth® HFP Defines +====================== + +Overview +-------- + +This file contains definitions for constants, enumerations, and structures used in the Bluetooth Hands-Free Profile (HFP), enabling features like call management, audio control, and network status reporting. + +Application Examples +-------------------- + +- :example:`bluetooth/bluedroid/classic_bt/hfp_hf` demonstrates how to use the Hands-Free Client Component to communicate with a device that implements Hands-Free Audio Gateway (HF-AG), such as a smartphone. + +- :example:`bluetooth/bluedroid/classic_bt/hfp_ag` demonstrates how to use the Hands-Free Audio Gateway (HF-AG) component to communicate with a device that implements Hands-Free Client Role, such as a headphone set. It provides commands for configuring the project, establishing connections, controlling volume, and answering or rejecting calls. API Reference ------------- diff --git a/docs/en/api-reference/bluetooth/esp_l2cap_bt.rst b/docs/en/api-reference/bluetooth/esp_l2cap_bt.rst index c390b435fa..a2f96388b9 100644 --- a/docs/en/api-reference/bluetooth/esp_l2cap_bt.rst +++ b/docs/en/api-reference/bluetooth/esp_l2cap_bt.rst @@ -1,6 +1,11 @@ -Classic Bluetooth® L2CAP API +Bluetooth® Classic L2CAP API ============================ +Overview +-------- + +Bluetooth Classic L2CAP (Logical Link Control and Adaptation Layer Protocol) API provides functions for data transmission between Bluetooth devices. It supports both client and server roles, allowing the creation of L2CAP connections for reliable, high-throughput communication. + Application Examples -------------------- diff --git a/docs/en/api-reference/bluetooth/esp_sdp.rst b/docs/en/api-reference/bluetooth/esp_sdp.rst index 75a893731e..3bd53c2423 100644 --- a/docs/en/api-reference/bluetooth/esp_sdp.rst +++ b/docs/en/api-reference/bluetooth/esp_sdp.rst @@ -1,10 +1,17 @@ -Bluetooth® SDP APIs -=================== +Bluetooth® SDP API +================== Overview -------- -Bluetooth SDP reference APIs. +SDP (Service Discovery Protocol) API enables devices to discover services and service attributes offered by remote Bluetooth devices. It supports service search, service attribute retrieval, and the establishment of service connections. + +Application Examples +-------------------- + +- :example:`bluetooth/bluedroid/classic_bt/bt_l2cap_client` demonstrates how to use SDP APIs to search for services on remote Bluetooth devices. It shows how to register SDP callbacks, initialize SDP, perform service discovery using ``esp_sdp_search_record()``, and retrieve the L2CAP PSM (Protocol/Service Multiplexer) value from the search results to establish an L2CAP connection. + +- :example:`bluetooth/bluedroid/classic_bt/bt_l2cap_server` demonstrates how to use SDP APIs to create and publish service records. It shows how to register SDP callbacks, initialize SDP, create an SDP record using ``esp_sdp_create_record()`` with L2CAP PSM information, making the service discoverable by remote clients. API Reference ------------- diff --git a/docs/en/api-reference/bluetooth/esp_spp.rst b/docs/en/api-reference/bluetooth/esp_spp.rst index cb9e2cc833..5d7bd66699 100644 --- a/docs/en/api-reference/bluetooth/esp_spp.rst +++ b/docs/en/api-reference/bluetooth/esp_spp.rst @@ -1,5 +1,10 @@ -SPP API -======= +Bluetooth® SPP API +================== + +Overview +-------- + +SPP (Serial Port Profile) enables serial communication between Bluetooth devices, allowing them to exchange data over a virtual serial link. SPP API provides functionality to create both SPP initiators (clients) and acceptors (servers), enabling operation under different security requirements. Application Examples -------------------- diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 6c002fa84f..cb54d44d92 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -353,6 +353,14 @@ Driver Usage The example code for the SPI Master driver can be found in the :example:`peripherals/spi_master` directory of ESP-IDF examples. +.. only:: SOC_PSRAM_DMA_CAPABLE + + Transactions with Data on PSRAM + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + {IDF_TARGET_NAME} supports GPSPI Master with DMA transferring data from/to PSRAM directly without extra internal copy process, which saves memory, by adding :c:macro:`SPI_TRANS_DMA_USE_PSRAM` flag to the transaction. + + Note that this feature shares bandwidth (bus frequency * bus bits width) with MSPI bus, so GPSPI transfer bandwidth should be less than PSRAM bandwidth, **otherwise transmission data may be lost**. You can check the return value or :c:macro:`SPI_TRANS_DMA_RX_FAIL` and :c:macro:`SPI_TRANS_DMA_TX_FAIL` flags after the transaction is finished to check if error occurs during the transmission. If the transaction returns :c:macro:`ESP_ERR_INVALID_STATE` error, the transaction fails. Transactions with Data Not Exceeding 32 Bits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +498,7 @@ GPIO Matrix and IO_MUX Most of the chip's peripheral signals have a direct connection to their dedicated IO_MUX pins. However, the signals can also be routed to any other available pins using the less direct GPIO matrix. If at least one signal is routed through the GPIO matrix, then all signals will be routed through it. - When an SPI Host is set to 80 MHz or lower frequencies, routing SPI pins via the GPIO matrix will behave the same compared to routing them via IOMUX. + When an SPI Host is set to 40 MHz or lower frequencies, routing SPI pins via the GPIO matrix will behave the same compared to routing them via IOMUX. The IO_MUX pins for SPI buses are given below. diff --git a/docs/zh_CN/api-guides/ble/ble-multiconnection-guide.rst b/docs/zh_CN/api-guides/ble/ble-multiconnection-guide.rst new file mode 100644 index 0000000000..504e5ade46 --- /dev/null +++ b/docs/zh_CN/api-guides/ble/ble-multiconnection-guide.rst @@ -0,0 +1,63 @@ +多连接指南 +============================= + +:link_to_translation:`en:[English]` + +介绍 +---- + +下表展示了每个 ESP 低功耗蓝牙主机所支持的最大多连接个数。在多连接场景下,需要对连接参数进行合理配置。通常情况下,随着连接数量的增加,连接间隔(Connection Interval)也应相应增大。具体的参数配置建议和 sdkconfig 详细信息,请参阅下表中的相应示例代码。 + +在本文档中,最大连接数指设备作为中心设备或外围设备时,能够同时维持的最大连接数量。 + +.. table:: ESP 低功耗蓝牙主机支持的最大连接数 + + +---------------+-----------------------------+------------------------------+---------------------+ + | 主机(Host) | 最大连接个数 | SDKconfig | 示例 | + +===============+=============================+==============================+=====================+ + | | | |bluedroid_enable_config| | | + | ESP-Bluedroid | |max_bluedroid_connections| | | |bluedroid_example| | + | | | |bluedroid_connection_num| | | + +---------------+-----------------------------+------------------------------+---------------------+ + | ESP-NimBLE | |max_nimble_connections| | |nimble_connection_num| | |nimble_example| | + +---------------+-----------------------------+------------------------------+---------------------+ + + +注意 +---- + +1. 应用能够支持的最大连接数在很大程度上取决于整体内存使用情况。建议禁用不必要的功能,以优化多连接性能。 + +2. 当设备处于外围角色时,连接稳定性和整体性能将受到中心设备和协商连接参数的影响。 + +.. only:: not esp32 and not esp32c3 and not esp32s3 and not esp32c2 + + 3. 由于 ESP-Bluedroid 的内存占用相对更高,其支持的最大连接数会少于 ESP-Nimble。 + + 4. 如果您的应用需要的同时连接数量超过上述数值,请联系 `乐鑫客户支持团队 `__ 以获取进一步的协助。 + +.. |bluedroid_enable_config| replace:: :ref:`BT_MULTI_CONNECTION_ENBALE ` +.. |bluedroid_connection_num| replace:: :ref:`BT_ACL_CONNECTIONS ` +.. |bluedroid_example| replace:: :example:`multi_conn ` +.. |nimble_connection_num| replace:: :ref:`BT_NIMBLE_MAX_CONNECTIONS ` +.. |nimble_example| replace:: :example:`multi_conn` + +.. only:: esp32 or esp32c3 or esp32s3 + + .. |max_bluedroid_connections| replace:: 9 + .. |max_nimble_connections| replace:: 9 + +.. only:: esp32c2 + + .. |max_bluedroid_connections| replace:: 2 + .. |max_nimble_connections| replace:: 2 + +.. only:: esp32h2 + + .. |max_bluedroid_connections| replace:: 15 + .. |max_nimble_connections| replace:: 70 + +.. only:: esp32c6 or esp32c5 or esp32c61 + + .. |max_bluedroid_connections| replace:: 50 + .. |max_nimble_connections| replace:: 70 diff --git a/docs/zh_CN/api-guides/ble/index.rst b/docs/zh_CN/api-guides/ble/index.rst index 201911777f..79c7db0f7e 100644 --- a/docs/zh_CN/api-guides/ble/index.rst +++ b/docs/zh_CN/api-guides/ble/index.rst @@ -14,6 +14,7 @@ ble-feature-support-status ble-qualification 低功耗模式介绍 <../low-power-mode/low-power-mode-ble> + ble-multiconnection-guide ********** 快速入门 diff --git a/docs/zh_CN/api-guides/low-power-mode/low-power-mode-soc.rst b/docs/zh_CN/api-guides/low-power-mode/low-power-mode-soc.rst index a71940638c..24244d8732 100644 --- a/docs/zh_CN/api-guides/low-power-mode/low-power-mode-soc.rst +++ b/docs/zh_CN/api-guides/low-power-mode/low-power-mode-soc.rst @@ -218,10 +218,10 @@ DFS 有如下可配置选项: - 1000 * - ``max_freq_mhz`` - - 160 + - {IDF_TARGET_NAME} 支持的最大 CPU 频率 * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - false @@ -288,6 +288,14 @@ Light-sleep 模式配置 由于 flash 和 PSRAM 共用供电管脚,PSRAM 关闭供电将会导致数据丢失,因此,为保证 light sleep 不破坏程序运行状态,启用该选项的前提是系统没有使用 PSRAM。 +.. only:: SOC_PM_SUPPORT_TOP_PD + + - 关闭数字外设模块及 TOP 电源域下的所有子电源域 (:ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`) + +.. only:: SOC_PM_SUPPORT_RTC_PERIPH_PD + + - 关闭 RTC 数字外设模块,系统睡眠时自动关闭 RTC 数字外设是系统电源管理默认策略,用户可以调用 `esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)` 在睡眠状态下开启 RTC 数字外设模块 + .. only:: esp32c2 - 减少 Power Managemet 模块片内 RAM 内存资源使用量 (:ref:`CONFIG_PM_SLEEP_FUNC_IN_IRAM`),当 :ref:`CONFIG_PM_SLEEP_FUNC_IN_IRAM` 禁止时,下面表格中选项分别用于控制 Power Management 模块各部分组件启用或禁止片内 RAM 优化 @@ -335,7 +343,61 @@ Light-sleep 模式配置 推荐配置 +++++++++ -.. only:: esp32c3 or esp32s3 +.. only:: esp32c6 or esp32c5 + + .. list-table:: + :header-rows: 1 + :widths: 30 15 + + * - 配置名称 + - 设置情况 + + * - 启用电源管理组件 (:ref:`CONFIG_PM_ENABLE`) + - ON + + * - 启用 Tickless IDLE 模式 (:ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE`) + - ON + + * - RTOS Tick rate (Hz) (:ref:`CONFIG_FREERTOS_HZ`) + - 1000 + + * - 进入睡眠模式前最小 IDLE Tick 数 (:ref:`CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP`) + - 3 + + * - 将 light sleep 相关代码放置在片内 RAM 中 (:ref:`CONFIG_PM_SLP_IRAM_OPT`) + - ON + + * - 将 RTOS IDLE 相关代码放置在片内 RAM 中 (:ref:`CONFIG_PM_RTOS_IDLE_OPT`) + - ON + + * - RTC 慢速时钟源 (:ref:`CONFIG_RTC_CLK_SRC`) + - 内部 150 kHz 振荡器 + + * - 芯片休眠时禁用所有 GPIO (:ref:`CONFIG_PM_SLP_DISABLE_GPIO`) + - ON + + * - 关闭 MAC 和基带 (:ref:`CONFIG_ESP_PHY_MAC_BB_PD`) + - ON + + * - 关闭 CPU (:ref:`CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP`) + - ON + + * - 在 light sleep 状态关闭 flash 供电 (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH`) + - OFF + + * - ``max_freq_mhz`` + - {IDF_TARGET_NAME} 支持的最大 CPU 频率 + + * - ``min_freq_mhz`` + - {CONFIG_XTAL_FREQ} + + * - ``light_sleep_enable`` + - true + + .. note:: + 上表中不涉及的配置均是默认。 + +.. only:: esp32s3 .. list-table:: :header-rows: 1 @@ -374,20 +436,71 @@ Light-sleep 模式配置 * - 关闭 CPU (:ref:`CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP`) - ON -.. only:: SOC_PM_SUPPORT_TAGMEM_PD - * - 关闭指令和数据缓存中的标签存储器 (I/D-cache tag memory) (:ref:`CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP`) - ON - * - 在 light sleep 状态关闭 flash 供电 (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH`) - OFF * - ``max_freq_mhz`` - - 160 + - {IDF_TARGET_NAME} 支持的最大 CPU 频率 * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} + + * - ``light_sleep_enable`` + - true + + .. note:: + 上表中不涉及的配置均是默认。 + +.. only:: esp32c3 + + .. list-table:: + :header-rows: 1 + :widths: 30 15 + + * - 配置名称 + - 设置情况 + + * - 启用电源管理组件 (:ref:`CONFIG_PM_ENABLE`) + - ON + + * - 启用 Tickless IDLE 模式 (:ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE`) + - ON + + * - RTOS Tick rate (Hz) (:ref:`CONFIG_FREERTOS_HZ`) + - 1000 + + * - 进入睡眠模式前最小 IDLE Tick 数 (:ref:`CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP`) + - 3 + + * - 将 light sleep 相关代码放置在片内 RAM 中 (:ref:`CONFIG_PM_SLP_IRAM_OPT`) + - OFF + + * - 将 RTOS IDLE 相关代码放置在片内 RAM 中 (:ref:`CONFIG_PM_RTOS_IDLE_OPT`) + - OFF + + * - RTC 慢速时钟源 (:ref:`CONFIG_RTC_CLK_SRC`) + - 内部 150 kHz 振荡器 + + * - 芯片休眠时禁用所有 GPIO (:ref:`CONFIG_PM_SLP_DISABLE_GPIO`) + - ON + + * - 关闭 MAC 和基带 (:ref:`CONFIG_ESP_PHY_MAC_BB_PD`) + - ON + + * - 关闭 CPU (:ref:`CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP`) + - ON + + * - 在 light sleep 状态关闭 flash 供电 (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH`) + - OFF + + * - ``max_freq_mhz`` + - {IDF_TARGET_NAME} 支持的最大 CPU 频率 + + * - ``min_freq_mhz`` + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - true @@ -432,7 +545,7 @@ Light-sleep 模式配置 - 160 * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - true @@ -480,7 +593,7 @@ Light-sleep 模式配置 - 120 * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - true diff --git a/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst b/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst index 2ffe3331e9..95be299570 100644 --- a/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst +++ b/docs/zh_CN/api-guides/low-power-mode/low-power-mode-wifi.rst @@ -5,9 +5,9 @@ Wi-Fi 场景下低功耗模式介绍 本节将结合纯系统下的功耗模式来介绍 Wi-Fi 场景下的低功耗模式。因为 Wi-Fi 场景的复杂性,本节会首先介绍 Wi-Fi 省电的基本原理,然后再介绍具体的低功耗模式。本节主要针对 station 模式。 -.. todo - add sleep-current/esp32c5_summary.inc and sleep-current/esp32c61_summary.inc +.. todo - add sleep-current/esp32c61_summary.inc -.. only:: not esp32c5 and not esp32c61 +.. only:: not esp32c61 Wi-Fi 场景如何选择低功耗模式 -------------------------------------- @@ -355,17 +355,17 @@ Modem-sleep 模式配置 - 1000 * - ``max_freq_mhz`` - - 160 + - {IDF_TARGET_NAME} 支持的最大 CPU 频率 * - ``min_freq_mhz`` - - 40 + - {CONFIG_XTAL_FREQ} * - ``light_sleep_enable`` - false - .. todo - add sleep-current/esp32c5_modem_sleep.inc sleep-current/esp32c61_modem_sleep.inc + .. todo - add sleep-current/esp32c61_modem_sleep.inc - .. only:: not esp32c5 and not esp32c61 + .. only:: not esp32c61 - 配置表现 @@ -377,9 +377,9 @@ Auto Light-sleep 模式 + Wi-Fi 场景配置 Auto Light-sleep 在 Wi-Fi 场景下的配置比纯系统下少了唤醒源的配置要求,其余几乎与纯系统下配置一致,因此可配置选项、配置步骤、推荐配置的详细介绍可以参考上文 :ref:`Deep-sleep 模式`。同时 Wi-Fi 相关配置保持默认。 -.. todo - add sleep-current/esp32c5_light_sleep.inc and leep-current/esp32c61_light_sleep.inc +.. todo - add sleep-current/esp32c61_light_sleep.inc -.. only:: not esp32c5 and not esp32c61 +.. only:: not esp32c61 - 配置表现 @@ -415,3 +415,11 @@ Deep-sleep 模式在 Wi-Fi 场景下的配置与纯系统下配置基本一致 .. only:: esp32c2 平均电流约 4.9 μA + + .. only:: esp32c6 + + 平均电流约 6.7 μA + + .. only:: esp32c5 + + 平均电流约 10.0 μA diff --git a/docs/zh_CN/api-guides/sleep-current/esp32c5_light_sleep.inc b/docs/zh_CN/api-guides/sleep-current/esp32c5_light_sleep.inc new file mode 100644 index 0000000000..6673f03295 --- /dev/null +++ b/docs/zh_CN/api-guides/sleep-current/esp32c5_light_sleep.inc @@ -0,0 +1,27 @@ +.. list-table:: + :header-rows: 1 + :widths: 20 10 20 20 20 + + * - CPU 频率 + - DTIM + - 平均电流 (mA) + - 最大电流 (mA) + - 最小电流 (mA) + + * - 240 MHz + - 1 + - 1.342 + - 80.375 + - 0.218 + + * - 240 MHz + - 3 + - 0.651 + - 81.179 + - 0.219 + + * - 240 MHz + - 10 + - 0.398 + - 80.518 + - 0.217 diff --git a/docs/zh_CN/api-guides/sleep-current/esp32c5_modem_sleep.inc b/docs/zh_CN/api-guides/sleep-current/esp32c5_modem_sleep.inc new file mode 100644 index 0000000000..55623d7ec8 --- /dev/null +++ b/docs/zh_CN/api-guides/sleep-current/esp32c5_modem_sleep.inc @@ -0,0 +1,107 @@ +.. list-table:: + :header-rows: 1 + :widths: 20 10 10 20 24 20 20 + + * - CPU 频率 + - DFS + - DTIM + - Wi-Fi Band + - 平均电流 (mA) + - 最大电流 (mA) + - 最小电流 (mA) + + * - 240 MHz + - ON + - 1 + - 2.4 GHz + - 24.766 + - 88.836 + - 23.139 + + * - 240 MHz + - OFF + - 1 + - 2.4 GHz + - 32.394 + - 97.378 + - 30.776 + + * - 240 MHz + - ON + - 3 + - 2.4 GHz + - 24.19 + - 89.176 + - 23.229 + + * - 240 MHz + - OFF + - 3 + - 2.4 GHz + - 31.618 + - 97.439 + - 30.778 + + * - 240 MHz + - ON + - 10 + - 2.4 GHz + - 23.998 + - 88.524 + - 23.252 + + * - 240 MHz + - OFF + - 10 + - 2.4 GHz + - 31.281 + - 98.254 + - 30.788 + + * - 240 MHz + - ON + - 1 + - 5 GHz + - 25.467 + - 114.746 + - 24.387 + + * - 240 MHz + - OFF + - 1 + - 5 GHz + - 32.329 + - 117.077 + - 31.948 + + * - 240 MHz + - ON + - 3 + - 5 GHz + - 25.208 + - 112.746 + - 24.421 + + * - 240 MHz + - OFF + - 3 + - 5 GHz + - 32.088 + - 117.227 + - 31.948 + + * - 240 MHz + - ON + - 10 + - 5 GHz + - 25.151 + - 114.438 + - 24.432 + + * - 160 MHz + - OFF + - 10 + - 5 GHz + - 32.011 + - 119.908 + - 31.955 diff --git a/docs/zh_CN/api-guides/sleep-current/esp32c5_summary.inc b/docs/zh_CN/api-guides/sleep-current/esp32c5_summary.inc new file mode 100644 index 0000000000..ca51abd706 --- /dev/null +++ b/docs/zh_CN/api-guides/sleep-current/esp32c5_summary.inc @@ -0,0 +1,87 @@ +.. list-table:: + :header-rows: 1 + :widths: 20 20 30 20 20 + + * - 项目 + - Modem-sleep + - Modem-sleep+DFS + - Auto Light-sleep + - Deep-sleep + + * - 休眠 + - 自动 + - 自动 + - 自动 + - 手动 + + * - 唤醒 + - 自动 + - 自动 + - 自动 + - 配置唤醒源 + + * - Wi-Fi连接 + - 保持 + - 保持 + - 保持 + - 断开 + + * - CPU + - 开 + - 开/降频 + - 暂停或关 + - 关 + + * - 系统时钟 + - 开 + - 开 + - 关 + - 关 + + * - 外设 + - 开 + - 开 + - 暂停或关 + - 关 + + * - DTIM1 (2.4 GHz) + - 32.394 mA + - 24.766 mA + - 1.342 mA + - / + + * - DTIM1 (5 GHz) + - 32.329 mA + - 25.467 mA + - 1.514 mA + - / + + * - DTIM3 (2.4 GHz) + - 31.618 mA + - 24.19 mA + - 0.651 mA + - / + + * - DTIM3 (5 GHz) + - 32.088 mA + - 25.208 mA + - 0.764 mA + - / + + * - DTIM10 (2.4 GHz) + - 31.281 mA + - 23.998 mA + - 0.398 mA + - / + + * - DTIM10 (5 GHz) + - 32.011 mA + - 25.151 mA + - 0.451 mA + - / + + * - 平均电流 + - / + - / + - / + - 10.0 μA diff --git a/docs/zh_CN/api-guides/wifi.rst b/docs/zh_CN/api-guides/wifi.rst index fdf1a9e635..92e6229e7d 100644 --- a/docs/zh_CN/api-guides/wifi.rst +++ b/docs/zh_CN/api-guides/wifi.rst @@ -2901,11 +2901,11 @@ Wi-Fi AMSDU Wi-Fi 分片 ------------------------- -.. only:: esp32 or esp32s2 +.. only:: not SOC_WIFI_TXOP_SUPPORT 支持 Wi-Fi 接收分片,但不支持 Wi-Fi 发送分片。 -.. only:: esp32c3 or esp32s3 or esp32c6 or esp32c5 +.. only:: SOC_WIFI_TXOP_SUPPORT {IDF_TARGET_NAME} 支持 Wi-Fi 接收和发送分片。 diff --git a/docs/zh_CN/api-reference/peripherals/spi_master.rst b/docs/zh_CN/api-reference/peripherals/spi_master.rst index beb77711c6..71f28f4645 100644 --- a/docs/zh_CN/api-reference/peripherals/spi_master.rst +++ b/docs/zh_CN/api-reference/peripherals/spi_master.rst @@ -353,6 +353,14 @@ SPI 总线传输事务由五个阶段构成,详见下表(任意阶段均可 SPI 主机驱动程序的示例代码存放在 ESP-IDF 示例项目的 :example:`peripherals/spi_master` 目录下。 +.. only:: SOC_PSRAM_DMA_CAPABLE + + 使用 PSRAM 的传输事务 + ^^^^^^^^^^^^^^^^^^^^^^ + + {IDF_TARGET_NAME} 支持 GPSPI Master 通过 DMA 直接传输 PSRAM 存储的数据而不用内部额外的零时拷贝,应此可以节省内存,在传输配置中添加 :c:macro:`SPI_TRANS_DMA_USE_PSRAM` 标志信号即可使用。 + + 请注意该功能共享 MSPI 总线带宽(总线频率 * 总线位宽),因此 GPSPI 传输带宽应小于 PSRAM 带宽,否则 **可能会丢失传输数据**。可通过在传输结束时检查返回值或 :c:macro:`SPI_TRANS_DMA_RX_FAIL` 和 :c:macro:`SPI_TRANS_DMA_TX_FAIL` 标志信号来判断传输是否发生了错误。若传输事务返回 :c:macro:`ESP_ERR_INVALID_STATE` 错误,则传输事务失败。 传输数据小于 32 位的传输事务 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +498,7 @@ GPIO 矩阵与 IO_MUX 管脚 芯片的大多数外围信号都与之专用的 IO_MUX 管脚连接,但这些信号也可以通过较不直接的 GPIO 矩阵路由到任何其他可用的管脚。只要有一个信号是通过 GPIO 矩阵路由的,那么所有的信号都将通过它路由。 - 当 SPI 主机被设置为 80 MHz 或更低的频率时,通过 GPIO 矩阵路由 SPI 管脚的行为将与通过 IOMUX 路由相同。 + 当 SPI 主机被设置为 40 MHz 或更低的频率时,通过 GPIO 矩阵路由 SPI 管脚的行为将与通过 IOMUX 路由相同。 SPI 总线的 IO_MUX 管脚如下表所示。 diff --git a/examples/bluetooth/.build-test-rules.yml b/examples/bluetooth/.build-test-rules.yml index 69caebef10..89a6d427b9 100644 --- a/examples/bluetooth/.build-test-rules.yml +++ b/examples/bluetooth/.build-test-rules.yml @@ -27,6 +27,24 @@ examples/bluetooth/bluedroid/ble: depends_filepatterns: - examples/bluetooth/bluedroid/ble/pytest_ble_test.py +examples/bluetooth/bluedroid/ble/ble_acl_latency/cent: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + enable: + - if: IDF_TARGET in ["esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s3"] + temporary: true + reason: only enable build jobs for tested targets + +examples/bluetooth/bluedroid/ble/ble_acl_latency/periph: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + enable: + - if: IDF_TARGET in ["esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s3"] + temporary: true + reason: only enable build jobs for tested targets + examples/bluetooth/bluedroid/ble/ble_hid_device_demo: <<: *bt_default_depends disable: @@ -63,6 +81,7 @@ examples/bluetooth/bluedroid/classic_bt: disable: - if: SOC_BT_CLASSIC_SUPPORTED != 1 depends_components+: + - esp_lcd - esp_console - esp_driver_gpio - esp_driver_i2s @@ -73,6 +92,8 @@ examples/bluetooth/bluedroid/classic_bt: - components/driver/dac/**/* - examples/bluetooth/bluedroid/esp_hid_host/**/* - examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py + - examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py + - examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py - examples/bluetooth/bluedroid/classic_bt/bt_discovery/pytest_classic_bt_discovery_test.py examples/bluetooth/bluedroid/coex/a2dp_gatts_coex: diff --git a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/main/main.c b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/main/main.c index 07e19e6b24..d464c583a5 100644 --- a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/main/main.c +++ b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -362,12 +362,16 @@ static void auto_io_gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_ case ESP_GATTS_WRITE_EVT: ESP_LOGI(GATTS_TAG, "Characteristic write, value len %u, value ", param->write.len); ESP_LOG_BUFFER_HEX(GATTS_TAG, param->write.value, param->write.len); - if (param->write.value[0]) { - ESP_LOGI(GATTS_TAG, "LED ON!"); - led_on(); + if (param->write.len > 0) { + if (param->write.value[0]) { + ESP_LOGI(GATTS_TAG, "LED ON!"); + led_on(); + } else { + ESP_LOGI(GATTS_TAG, "LED OFF!"); + led_off(); + } } else { - ESP_LOGI(GATTS_TAG, "LED OFF!"); - led_off(); + ESP_LOGW(GATTS_TAG, "Empty write data received"); } example_write_event_env(gatts_if, param); break; diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/CMakeLists.txt new file mode 100644 index 0000000000..ea7d4a20a9 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ble_acl_latency_cent) diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/README.md b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/README.md new file mode 100644 index 0000000000..4cb1e830c3 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/README.md @@ -0,0 +1,190 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | + +# ESP-IDF BLE ACL Latency Test - Central + +This example demonstrates how to measure BLE ACL (Asynchronous Connection-Less) link latency. The central device scans for the peripheral, connects to it, and then performs a latency test by sending packets and measuring the round-trip time (RTT). + +This demo should be used together with the `periph` (peripheral) example. + +## How It Works + +1. The central scans for a device named `ESP_ACL_LATENCY` +2. Upon finding the peripheral, it connects and performs MTU exchange +3. After enabling notifications, the central sends 100 test packets (242 bytes each) +4. For each packet, the central records the send time +5. When the echoed packet is received via notification, it calculates RTT +6. Finally, statistics (average, min, max latency, packet loss) are printed + +## Test Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ Central │ │ Peripheral │ + │ (GATT Client)│ │ (GATT Server)│ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ──────────── Connection Setup ─────────── │ + │ │ + │ 1. Scan for "ESP_ACL_LATENCY" │ + │ ─────────────────────────────────────────> │ Advertising + │ │ + │ 2. Connect Request │ + │ ─────────────────────────────────────────> │ + │ │ + │ 3. Connection Established │ + │ <─────────────────────────────────────────> │ + │ │ + │ 4. MTU Exchange (517 bytes) │ + │ <─────────────────────────────────────────> │ + │ │ + │ 5. Connection Parameter Update (7.5ms) │ + │ <─────────────────────────────────────────> │ + │ │ + │ 6. Service Discovery │ + │ ─────────────────────────────────────────> │ + │ │ + │ 7. Enable Notification (CCCD) │ + │ ─────────────────────────────────────────> │ + │ │ + │ ──────────── Latency Test ───────────── │ + │ │ + │ 8. Write Test Packet [SEQ=0] ──┐ │ + │ Record send_time t1│ │ + │ ─────────────────────────────────────────> │ + │ │ │ Echo back + │ 9. Notification [SEQ=0] │ │ via Notify + │ Record recv_time t2│ │ + │ <───────────────────────────────────────── │ + │ │ │ + │ RTT = t2 - t1 ──┘ │ + │ Latency = RTT / 2 │ + │ │ + │ ... Repeat for SEQ 1-99 ... │ + │ │ + │ 10. Print Statistics │ + │ - Average/Min/Max Latency │ + │ - Packet Loss Rate │ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ Central │ │ Peripheral │ + └──────────────┘ └──────────────┘ +``` + +## Test Configuration + +The following parameters can be modified in `gattc_latency.h`: + +| Parameter | Default Value | Description | +|------------------------|---------------|------------------------------------| +| TEST_PACKET_COUNT | 100 | Number of test packets to send | +| TEST_PACKET_INTERVAL_MS| 20 | Interval between packets (ms) | + +## How to Use Example + +### Hardware Required + +* Two development boards with supported SoC (e.g., ESP32-C3-DevKitC, ESP32-DevKitC, etc.) +* Two USB cables for power supply and programming + +See [Development Boards](https://www.espressif.com/en/products/devkits) for more information. + +### Configure the Project + +Before project configuration and build, be sure to set the correct chip target using: + +```bash +idf.py set-target +``` + +### Build and Flash + +1. First, flash the `periph` example to one board: + +```bash +cd ../periph +idf.py -p PORT1 flash +``` + +2. Then, flash this `cent` example to another board: + +```bash +cd ../cent +idf.py -p PORT2 flash +``` + +### Monitor + +Run `idf.py -p PORT monitor` to view the serial output of the central device. + +(To exit the serial monitor, type `Ctrl-]`.) + +See the [Getting Started Guide](https://idf.espressif.com/) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +``` +I (362) BLE_ACL_LATENCY_CENT: BLE ACL Latency Test - Central +I (372) phy_init: phy_version 310,dde1ba9,Jun 4 2024,16:38:11 +I (432) BLE_ACL_LATENCY_CENT: REG_EVT +I (442) BLE_ACL_LATENCY_CENT: scan start success +I (442) BLE_ACL_LATENCY_CENT: Central initialized, scanning for peripheral... +I (622) BLE_ACL_LATENCY_CENT: searched device ESP_ACL_LATENCY +I (622) BLE_ACL_LATENCY_CENT: connect to the remote device. +I (622) BLE_ACL_LATENCY_CENT: stop scan successfully +I (892) BLE_ACL_LATENCY_CENT: ESP_GATTC_CONNECT_EVT conn_id 0, if 4 +I (892) BLE_ACL_LATENCY_CENT: REMOTE BDA: 58:cf:79:ea:77:30 +I (892) BLE_ACL_LATENCY_CENT: open success +I (1042) BLE_ACL_LATENCY_CENT: update connection params status = 0, min_int = 6, max_int = 6,conn_int = 6,latency = 0, timeout = 500 +I (1112) BLE_ACL_LATENCY_CENT: discover service complete conn_id 0 +I (1112) BLE_ACL_LATENCY_CENT: service found +I (1122) BLE_ACL_LATENCY_CENT: ESP_GATTC_CFG_MTU_EVT, Status 0, MTU 517, conn_id 0 +I (1132) BLE_ACL_LATENCY_CENT: ESP_GATTC_REG_FOR_NOTIFY_EVT +I (1172) BLE_ACL_LATENCY_CENT: write descr success +I (1172) BLE_ACL_LATENCY_CENT: Initializing latency test... +I (1172) LATENCY_TEST: Latency test initialized, conn_id=0, handle=42 +I (2182) BLE_ACL_LATENCY_CENT: Starting latency test... +I (2182) LATENCY_TEST: ==================================== +I (2182) LATENCY_TEST: Starting latency test... +I (2182) LATENCY_TEST: Packets: 100, Interval: 20 ms +I (2182) LATENCY_TEST: ==================================== +SEQ= 0, RTT= 20040 us, Latency= 10020 us (10.02 ms) +SEQ= 1, RTT= 18341 us, Latency= 9170 us (9.17 ms) +SEQ= 2, RTT= 13339 us, Latency= 6669 us (6.67 ms) +... +SEQ= 99, RTT= 15835 us, Latency= 7917 us (7.92 ms) +I (4192) LATENCY_TEST: All packets sent, waiting for responses... +I (6192) LATENCY_TEST: +I (6192) LATENCY_TEST: ======================================== +I (6192) LATENCY_TEST: Test Results Summary +I (6192) LATENCY_TEST: ======================================== +I (6192) LATENCY_TEST: Total packets: 100 +I (6202) LATENCY_TEST: Received: 100 +I (6202) LATENCY_TEST: Lost: 0 (0.0%) +I (6202) LATENCY_TEST: ---------------------------------------- +I (6212) LATENCY_TEST: Average latency: 7929 us (7.93 ms) +I (6222) LATENCY_TEST: Min latency: 6667 us (6.67 ms) +I (6222) LATENCY_TEST: Max latency: 10020 us (10.02 ms) +I (6232) LATENCY_TEST: ======================================== +``` + +## Connection Parameters + +The example uses optimized connection parameters for low latency: + +| Parameter | Value | Description | +|---------------------|----------|--------------------------------| +| Connection Interval | 7.5 ms | Minimum allowed by BLE spec | +| Slave Latency | 0 | No skipped connection events | +| Supervision Timeout | 4000 ms | Connection timeout | +| MTU | 517 | Maximum ATT MTU | + +## Understanding the Results + +- **RTT (Round-Trip Time)**: Time from sending a packet until receiving the echo +- **Latency**: Estimated one-way delay (RTT / 2) +- **Expected Results**: With 7.5ms connection interval, typical latency is 6-10ms + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/CMakeLists.txt new file mode 100644 index 0000000000..3b695c9c7e --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "gattc_latency_demo.c" "latency_test.c" + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/gattc_latency.h b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/gattc_latency.h new file mode 100644 index 0000000000..ddd9c5409a --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/gattc_latency.h @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef H_GATTC_LATENCY_ +#define H_GATTC_LATENCY_ + +#include "esp_gattc_api.h" +#include "esp_gap_ble_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Service and Characteristic UUIDs - must match peripheral */ +#define REMOTE_SERVICE_UUID 0x1234 +#define REMOTE_CHAR_UUID 0x5678 + +/* Profile ID */ +#define PROFILE_APP_ID 0 +#define INVALID_HANDLE 0 + +/* Remote device name */ +#define REMOTE_DEVICE_NAME "ESP_ACL_LATENCY" + +/* Test configuration */ +#define TEST_PACKET_COUNT 100 +#define TEST_PACKET_INTERVAL_MS 20 + +/* Test packet structure */ +typedef struct { + uint16_t seq_num; + uint8_t payload[240]; +} __attribute__((packed)) test_packet_t; + +/* Latency record */ +typedef struct { + uint16_t seq; + int64_t send_time_us; + int64_t recv_time_us; + bool received; +} latency_record_t; + +/* Latency test functions */ +void latency_test_init(uint16_t conn_id, uint16_t char_handle); +void latency_test_start(void); +void latency_test_handle_notify(uint8_t *data, uint16_t len); +void latency_test_print_results(void); + +#ifdef __cplusplus +} +#endif + +#endif /* H_GATTC_LATENCY_ */ diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/gattc_latency_demo.c b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/gattc_latency_demo.c new file mode 100644 index 0000000000..09bd9ee5ee --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/gattc_latency_demo.c @@ -0,0 +1,480 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include "nvs.h" +#include "nvs_flash.h" + +#include "esp_bt.h" +#include "esp_gap_ble_api.h" +#include "esp_gattc_api.h" +#include "esp_gatt_defs.h" +#include "esp_bt_main.h" +#include "esp_gatt_common_api.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "gattc_latency.h" + +#define GATTC_TAG "BLE_ACL_LATENCY_CENT" + +#define PROFILE_NUM 1 +#define PROFILE_APP_ID 0 + +static bool connect = false; +static bool get_server = false; +static esp_gattc_char_elem_t *char_elem_result = NULL; +static esp_gattc_descr_elem_t *descr_elem_result = NULL; + +/* Declare static functions */ +static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); +static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); +static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); + +/* Extern function */ +extern void latency_test_set_gattc_if(esp_gatt_if_t gattc_if); + +static esp_bt_uuid_t remote_filter_service_uuid = { + .len = ESP_UUID_LEN_16, + .uuid = {.uuid16 = REMOTE_SERVICE_UUID,}, +}; + +static esp_bt_uuid_t remote_filter_char_uuid = { + .len = ESP_UUID_LEN_16, + .uuid = {.uuid16 = REMOTE_CHAR_UUID,}, +}; + +static esp_bt_uuid_t notify_descr_uuid = { + .len = ESP_UUID_LEN_16, + .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,}, +}; + +static esp_ble_scan_params_t ble_scan_params = { + .scan_type = BLE_SCAN_TYPE_ACTIVE, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), // 50ms + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), // 30ms + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE +}; + +struct gattc_profile_inst { + esp_gattc_cb_t gattc_cb; + uint16_t gattc_if; + uint16_t app_id; + uint16_t conn_id; + uint16_t service_start_handle; + uint16_t service_end_handle; + uint16_t char_handle; + esp_bd_addr_t remote_bda; +}; + +static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = { + [PROFILE_APP_ID] = { + .gattc_cb = gattc_profile_event_handler, + .gattc_if = ESP_GATT_IF_NONE, + }, +}; + +static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) +{ + esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param; + + switch (event) { + case ESP_GATTC_REG_EVT: + ESP_LOGI(GATTC_TAG, "REG_EVT"); + gl_profile_tab[PROFILE_APP_ID].gattc_if = gattc_if; + esp_err_t scan_ret = esp_ble_gap_set_scan_params(&ble_scan_params); + if (scan_ret){ + ESP_LOGE(GATTC_TAG, "set scan params error, error code = %x", scan_ret); + } + break; + case ESP_GATTC_CONNECT_EVT:{ + ESP_LOGI(GATTC_TAG, "ESP_GATTC_CONNECT_EVT conn_id %d, if %d", p_data->connect.conn_id, gattc_if); + gl_profile_tab[PROFILE_APP_ID].conn_id = p_data->connect.conn_id; + memcpy(gl_profile_tab[PROFILE_APP_ID].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t)); + ESP_LOGI(GATTC_TAG, "REMOTE BDA: %02x:%02x:%02x:%02x:%02x:%02x", + p_data->connect.remote_bda[0], p_data->connect.remote_bda[1], + p_data->connect.remote_bda[2], p_data->connect.remote_bda[3], + p_data->connect.remote_bda[4], p_data->connect.remote_bda[5]); + + /* Update connection parameters to minimum interval (7.5ms) for lower latency */ + esp_ble_conn_update_params_t conn_params = {0}; + memcpy(conn_params.bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t)); + conn_params.min_int = ESP_BLE_GAP_CONN_ITVL_MS(7.5); // 7.5ms - minimum allowed + conn_params.max_int = ESP_BLE_GAP_CONN_ITVL_MS(7.5); // 7.5ms - minimum allowed + conn_params.latency = 0; + conn_params.timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(4000); // 4s + esp_ble_gap_update_conn_params(&conn_params); + + esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, p_data->connect.conn_id); + if (mtu_ret){ + ESP_LOGE(GATTC_TAG, "config MTU error, error code = %x", mtu_ret); + } + break; + } + case ESP_GATTC_OPEN_EVT: + if (param->open.status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "open failed, status %d", p_data->open.status); + break; + } + ESP_LOGI(GATTC_TAG, "open success"); + break; + case ESP_GATTC_DIS_SRVC_CMPL_EVT: + if (param->dis_srvc_cmpl.status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "discover service failed, status %d", param->dis_srvc_cmpl.status); + break; + } + ESP_LOGI(GATTC_TAG, "discover service complete conn_id %d", param->dis_srvc_cmpl.conn_id); + esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid); + break; + case ESP_GATTC_CFG_MTU_EVT: + if (param->cfg_mtu.status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG,"config mtu failed, error status = %x", param->cfg_mtu.status); + } + ESP_LOGI(GATTC_TAG, "ESP_GATTC_CFG_MTU_EVT, Status %d, MTU %d, conn_id %d", param->cfg_mtu.status, param->cfg_mtu.mtu, param->cfg_mtu.conn_id); + break; + case ESP_GATTC_SEARCH_RES_EVT: { + ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary); + ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.end_handle, p_data->search_res.srvc_id.inst_id); + if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && p_data->search_res.srvc_id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) { + ESP_LOGI(GATTC_TAG, "service found"); + get_server = true; + gl_profile_tab[PROFILE_APP_ID].service_start_handle = p_data->search_res.start_handle; + gl_profile_tab[PROFILE_APP_ID].service_end_handle = p_data->search_res.end_handle; + ESP_LOGI(GATTC_TAG, "UUID16: %x", p_data->search_res.srvc_id.uuid.uuid.uuid16); + } + break; + } + case ESP_GATTC_SEARCH_CMPL_EVT: + if (p_data->search_cmpl.status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "search service failed, error status = %x", p_data->search_cmpl.status); + break; + } + if(p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_REMOTE_DEVICE) { + ESP_LOGI(GATTC_TAG, "Get service information from remote device"); + } else if (p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_NVS_FLASH) { + ESP_LOGI(GATTC_TAG, "Get service information from flash"); + } else { + ESP_LOGI(GATTC_TAG, "unknown service source"); + } + ESP_LOGI(GATTC_TAG, "ESP_GATTC_SEARCH_CMPL_EVT"); + if (get_server){ + uint16_t count = 0; + esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if, + p_data->search_cmpl.conn_id, + ESP_GATT_DB_CHARACTERISTIC, + gl_profile_tab[PROFILE_APP_ID].service_start_handle, + gl_profile_tab[PROFILE_APP_ID].service_end_handle, + INVALID_HANDLE, + &count); + if (status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error"); + break; + } + + if (count > 0){ + char_elem_result = (esp_gattc_char_elem_t *)malloc(sizeof(esp_gattc_char_elem_t) * count); + if (!char_elem_result){ + ESP_LOGE(GATTC_TAG, "gattc no mem"); + break; + }else{ + status = esp_ble_gattc_get_char_by_uuid( gattc_if, + p_data->search_cmpl.conn_id, + gl_profile_tab[PROFILE_APP_ID].service_start_handle, + gl_profile_tab[PROFILE_APP_ID].service_end_handle, + remote_filter_char_uuid, + char_elem_result, + &count); + if (status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_char_by_uuid error"); + free(char_elem_result); + char_elem_result = NULL; + break; + } + + if (count > 0 && (char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)){ + gl_profile_tab[PROFILE_APP_ID].char_handle = char_elem_result[0].char_handle; + esp_ble_gattc_register_for_notify (gattc_if, gl_profile_tab[PROFILE_APP_ID].remote_bda, char_elem_result[0].char_handle); + } + } + free(char_elem_result); + char_elem_result = NULL; + }else{ + ESP_LOGE(GATTC_TAG, "no char found"); + } + } + break; + case ESP_GATTC_REG_FOR_NOTIFY_EVT: { + ESP_LOGI(GATTC_TAG, "ESP_GATTC_REG_FOR_NOTIFY_EVT"); + if (p_data->reg_for_notify.status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "REG FOR NOTIFY failed: error status = %d", p_data->reg_for_notify.status); + }else{ + uint16_t count = 0; + uint16_t notify_en = 1; + esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if, + gl_profile_tab[PROFILE_APP_ID].conn_id, + ESP_GATT_DB_DESCRIPTOR, + gl_profile_tab[PROFILE_APP_ID].service_start_handle, + gl_profile_tab[PROFILE_APP_ID].service_end_handle, + gl_profile_tab[PROFILE_APP_ID].char_handle, + &count); + if (ret_status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error"); + } + if (count > 0){ + descr_elem_result = malloc(sizeof(esp_gattc_descr_elem_t) * count); + if (!descr_elem_result){ + ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem"); + }else{ + ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if, + gl_profile_tab[PROFILE_APP_ID].conn_id, + p_data->reg_for_notify.handle, + notify_descr_uuid, + descr_elem_result, + &count); + if (ret_status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error"); + } + if (count > 0 && descr_elem_result[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){ + ret_status = esp_ble_gattc_write_char_descr( gattc_if, + gl_profile_tab[PROFILE_APP_ID].conn_id, + descr_elem_result[0].handle, + sizeof(notify_en), + (uint8_t *)¬ify_en, + ESP_GATT_WRITE_TYPE_RSP, + ESP_GATT_AUTH_REQ_NONE); + } + + if (ret_status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error"); + } + + free(descr_elem_result); + descr_elem_result = NULL; + } + } + else{ + ESP_LOGE(GATTC_TAG, "decsr not found"); + } + + } + break; + } + case ESP_GATTC_NOTIFY_EVT: + if (p_data->notify.is_notify){ + ESP_LOGD(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive notify value:"); + }else{ + ESP_LOGD(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive indicate value:"); + } + ESP_LOGD(GATTC_TAG, "Received %d bytes of data", p_data->notify.value_len); + + /* Handle latency test notification */ + latency_test_handle_notify(p_data->notify.value, p_data->notify.value_len); + break; + case ESP_GATTC_WRITE_DESCR_EVT: + if (p_data->write.status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "write descr failed, error status = %x", p_data->write.status); + break; + } + ESP_LOGI(GATTC_TAG, "write descr success "); + + /* After enabling notification, initialize and start latency test */ + ESP_LOGI(GATTC_TAG, "Initializing latency test..."); + latency_test_init(gl_profile_tab[PROFILE_APP_ID].conn_id, gl_profile_tab[PROFILE_APP_ID].char_handle); + latency_test_set_gattc_if(gl_profile_tab[PROFILE_APP_ID].gattc_if); + + vTaskDelay(pdMS_TO_TICKS(1000)); + ESP_LOGI(GATTC_TAG, "Starting latency test..."); + latency_test_start(); + break; + case ESP_GATTC_SRVC_CHG_EVT: { + esp_bd_addr_t bda; + memcpy(bda, p_data->srvc_chg.remote_bda, sizeof(esp_bd_addr_t)); + ESP_LOGI(GATTC_TAG, "ESP_GATTC_SRVC_CHG_EVT, bd_addr: %02x:%02x:%02x:%02x:%02x:%02x", + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + break; + } + case ESP_GATTC_WRITE_CHAR_EVT: + if (p_data->write.status != ESP_GATT_OK){ + ESP_LOGE(GATTC_TAG, "write char failed, error status = %x", p_data->write.status); + break; + } + ESP_LOGD(GATTC_TAG, "write char success "); + break; + case ESP_GATTC_DISCONNECT_EVT: + connect = false; + get_server = false; + ESP_LOGI(GATTC_TAG, "ESP_GATTC_DISCONNECT_EVT, reason = %d", p_data->disconnect.reason); + break; + default: + break; + } +} + +static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + uint8_t *adv_name = NULL; + uint8_t adv_name_len = 0; + switch (event) { + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: { + uint32_t duration = 30; + esp_ble_gap_start_scanning(duration); + break; + } + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTC_TAG, "scan start failed, error status = %x", param->scan_start_cmpl.status); + break; + } + ESP_LOGI(GATTC_TAG, "scan start success"); + + break; + case ESP_GAP_BLE_SCAN_RESULT_EVT: { + esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param; + switch (scan_result->scan_rst.search_evt) { + case ESP_GAP_SEARCH_INQ_RES_EVT: + adv_name = esp_ble_resolve_adv_data_by_type(scan_result->scan_rst.ble_adv, + scan_result->scan_rst.adv_data_len, + ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); + if (adv_name != NULL) { + if (strlen(REMOTE_DEVICE_NAME) == adv_name_len && strncmp((char *)adv_name, REMOTE_DEVICE_NAME, adv_name_len) == 0) { + ESP_LOGI(GATTC_TAG, "searched device %s", REMOTE_DEVICE_NAME); + if (connect == false) { + connect = true; + ESP_LOGI(GATTC_TAG, "connect to the remote device."); + esp_ble_gap_stop_scanning(); + esp_ble_gattc_open(gl_profile_tab[PROFILE_APP_ID].gattc_if, scan_result->scan_rst.bda, scan_result->scan_rst.ble_addr_type, true); + } + } + } + break; + case ESP_GAP_SEARCH_INQ_CMPL_EVT: + break; + default: + break; + } + break; + } + + case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: + if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){ + ESP_LOGE(GATTC_TAG, "scan stop failed, error status = %x", param->scan_stop_cmpl.status); + break; + } + ESP_LOGI(GATTC_TAG, "stop scan successfully"); + break; + + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){ + ESP_LOGE(GATTC_TAG, "adv stop failed, error status = %x", param->adv_stop_cmpl.status); + break; + } + ESP_LOGI(GATTC_TAG, "stop adv successfully"); + break; + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + ESP_LOGI(GATTC_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d", + param->update_conn_params.status, + param->update_conn_params.min_int, + param->update_conn_params.max_int, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); + break; + default: + break; + } +} + +static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) +{ + if (event == ESP_GATTC_REG_EVT) { + if (param->reg.status == ESP_GATT_OK) { + gl_profile_tab[PROFILE_APP_ID].gattc_if = gattc_if; + } else { + ESP_LOGI(GATTC_TAG, "reg app failed, app_id %04x, status %d", + param->reg.app_id, + param->reg.status); + return; + } + } + + do { + int idx; + for (idx = 0; idx < PROFILE_NUM; idx++) { + if (gattc_if == ESP_GATT_IF_NONE || gattc_if == gl_profile_tab[idx].gattc_if) { + if (gl_profile_tab[idx].gattc_cb) { + gl_profile_tab[idx].gattc_cb(event, gattc_if, param); + } + } + } + } while (0); +} + +void app_main(void) +{ + ESP_LOGI(GATTC_TAG, "BLE ACL Latency Test - Central"); + + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK( ret ); + + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ret = esp_bt_controller_init(&bt_cfg); + if (ret) { + ESP_LOGE(GATTC_TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); + if (ret) { + ESP_LOGE(GATTC_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_init(); + if (ret) { + ESP_LOGE(GATTC_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_enable(); + if (ret) { + ESP_LOGE(GATTC_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_ble_gattc_register_callback(esp_gattc_cb); + if(ret){ + ESP_LOGE(GATTC_TAG, "%s gattc register failed, error code = %x", __func__, ret); + return; + } + + ret = esp_ble_gap_register_callback(esp_gap_cb); + if(ret){ + ESP_LOGE(GATTC_TAG, "%s gap register failed, error code = %x", __func__, ret); + return; + } + + ret = esp_ble_gattc_app_register(PROFILE_APP_ID); + if (ret){ + ESP_LOGE(GATTC_TAG, "%s gattc app register failed, error code = %x", __func__, ret); + } + esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(517); + if (local_mtu_ret){ + ESP_LOGE(GATTC_TAG, "set local MTU failed, error code = %x", local_mtu_ret); + } + + ESP_LOGI(GATTC_TAG, "Central initialized, scanning for peripheral..."); +} diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/latency_test.c b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/latency_test.c new file mode 100644 index 0000000000..23743d9482 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/main/latency_test.c @@ -0,0 +1,261 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "esp_log.h" +#include "esp_timer.h" +#include "esp_random.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_gattc_api.h" +#include "gattc_latency.h" + +static const char *TAG = "LATENCY_TEST"; + +/* Global variables */ +static latency_record_t records[TEST_PACKET_COUNT]; +static uint16_t test_conn_id = 0; +static uint16_t char_handle = 0; +static test_packet_t send_packets[TEST_PACKET_COUNT]; +static bool test_running = false; +static bool test_initialized = false; +static esp_gatt_if_t test_gattc_if = 0; + +/** + * Fill random data + */ +static void +fill_random_data(uint8_t *data, uint16_t len) +{ + for (int i = 0; i < len; i++) { + data[i] = esp_random() & 0xFF; + } +} + +/** + * Initialize latency test + */ +void +latency_test_init(uint16_t conn_id, uint16_t handle) +{ + test_conn_id = conn_id; + char_handle = handle; + test_running = false; + test_initialized = true; + + memset(records, 0, sizeof(records)); + memset(send_packets, 0, sizeof(send_packets)); + + ESP_LOGI(TAG, "Latency test initialized, conn_id=%d, handle=%d", conn_id, handle); +} + +/** + * Set GATT interface + */ +void +latency_test_set_gattc_if(esp_gatt_if_t gattc_if) +{ + test_gattc_if = gattc_if; +} + +/** + * Send single test packet + */ +static int +send_test_packet(uint16_t seq) +{ + if (char_handle == 0 || test_gattc_if == 0) { + ESP_LOGE(TAG, "Test not initialized"); + return -1; + } + + /* Prepare packet */ + test_packet_t *pkt = &send_packets[seq]; + pkt->seq_num = seq; + fill_random_data(pkt->payload, sizeof(pkt->payload)); + + /* Record send time */ + records[seq].seq = seq; + records[seq].send_time_us = esp_timer_get_time(); + records[seq].received = false; + + /* Send write command (write without response) */ + esp_err_t ret = esp_ble_gattc_write_char(test_gattc_if, + test_conn_id, + char_handle, + sizeof(test_packet_t), + (uint8_t *)pkt, + ESP_GATT_WRITE_TYPE_NO_RSP, + ESP_GATT_AUTH_REQ_NONE); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Write failed: %s", esp_err_to_name(ret)); + return -1; + } + + return 0; +} + +/** + * Test task + */ +static void +latency_test_task(void *arg) +{ + ESP_LOGI(TAG, "===================================="); + ESP_LOGI(TAG, "Starting latency test..."); + ESP_LOGI(TAG, "Packets: %d, Interval: %d ms", TEST_PACKET_COUNT, TEST_PACKET_INTERVAL_MS); + ESP_LOGI(TAG, "===================================="); + + test_running = true; + + /* Send all test packets */ + for (int i = 0; i < TEST_PACKET_COUNT; i++) { + int rc = send_test_packet(i); + if (rc != 0) { + ESP_LOGW(TAG, "Send failed for seq=%d", i); + } + + /* Wait interval */ + vTaskDelay(pdMS_TO_TICKS(TEST_PACKET_INTERVAL_MS)); + } + + ESP_LOGI(TAG, "All packets sent, waiting for responses..."); + + /* Wait for all responses */ + vTaskDelay(pdMS_TO_TICKS(2000)); + + /* Print results */ + latency_test_print_results(); + + test_running = false; + vTaskDelete(NULL); +} + +/** + * Start latency test + */ +void +latency_test_start(void) +{ + if (test_running) { + ESP_LOGW(TAG, "Test already running"); + return; + } + + if (!test_initialized || char_handle == 0) { + ESP_LOGE(TAG, "Test not initialized"); + return; + } + + xTaskCreate(latency_test_task, "latency_test", 4096, NULL, 5, NULL); +} + +/** + * Handle notification + */ +void +latency_test_handle_notify(uint8_t *data, uint16_t len) +{ + if (!test_running) { + return; + } + + /* Record receive time */ + int64_t recv_time = esp_timer_get_time(); + + /* Parse packet */ + if (len < sizeof(test_packet_t)) { + ESP_LOGW(TAG, "Invalid packet size: %d", len); + return; + } + + test_packet_t *recv_pkt = (test_packet_t *)data; + uint16_t seq = recv_pkt->seq_num; + + /* Validate sequence number */ + if (seq >= TEST_PACKET_COUNT) { + ESP_LOGW(TAG, "Invalid seq number: %d", seq); + return; + } + + /* Verify data consistency */ + if (memcmp(recv_pkt, &send_packets[seq], sizeof(test_packet_t)) != 0) { + ESP_LOGW(TAG, "Data mismatch for seq=%d", seq); + return; + } + + /* Record receive time */ + records[seq].recv_time_us = recv_time; + records[seq].received = true; + + /* Calculate latency */ + int64_t rtt_us = recv_time - records[seq].send_time_us; + int64_t latency_us = rtt_us / 2; + + /* Print real-time result */ + printf("SEQ=%3d, RTT=%6lld us, Latency=%6lld us (%.2f ms)\n", + seq, rtt_us, latency_us, (float)latency_us / 1000.0); +} + +/** + * Print statistics + */ +void +latency_test_print_results(void) +{ + int64_t total_latency = 0; + int64_t min_latency = INT64_MAX; + int64_t max_latency = 0; + int valid_count = 0; + int lost_count = 0; + + /* Collect statistics */ + for (int i = 0; i < TEST_PACKET_COUNT; i++) { + if (records[i].received) { + int64_t rtt = records[i].recv_time_us - records[i].send_time_us; + int64_t latency = rtt / 2; + + total_latency += latency; + valid_count++; + + if (latency < min_latency) { + min_latency = latency; + } + if (latency > max_latency) { + max_latency = latency; + } + } else { + lost_count++; + } + } + + /* Print results */ + ESP_LOGI(TAG, ""); + ESP_LOGI(TAG, "========================================"); + ESP_LOGI(TAG, " Test Results Summary"); + ESP_LOGI(TAG, "========================================"); + ESP_LOGI(TAG, "Total packets: %d", TEST_PACKET_COUNT); + ESP_LOGI(TAG, "Received: %d", valid_count); + ESP_LOGI(TAG, "Lost: %d (%.1f%%)", lost_count, + (float)lost_count * 100.0 / TEST_PACKET_COUNT); + + if (valid_count > 0) { + int64_t avg_latency = total_latency / valid_count; + + ESP_LOGI(TAG, "----------------------------------------"); + ESP_LOGI(TAG, "Average latency: %lld us (%.2f ms)", avg_latency, + (float)avg_latency / 1000.0); + ESP_LOGI(TAG, "Min latency: %lld us (%.2f ms)", min_latency, + (float)min_latency / 1000.0); + ESP_LOGI(TAG, "Max latency: %lld us (%.2f ms)", max_latency, + (float)max_latency / 1000.0); + } + + ESP_LOGI(TAG, "========================================"); + ESP_LOGI(TAG, ""); +} diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/sdkconfig.defaults new file mode 100644 index 0000000000..a218a4da6a --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/sdkconfig.defaults @@ -0,0 +1,7 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_LE_50_FEATURE_SUPPORT is not set diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/sdkconfig.defaults.esp32c2 b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/sdkconfig.defaults.esp32c2 new file mode 100644 index 0000000000..9759e23400 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/sdkconfig.defaults.esp32c2 @@ -0,0 +1,13 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32c2" +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_LE_50_FEATURE_SUPPORT is not set +CONFIG_BT_LE_HCI_EVT_BUF_SIZE=257 + +# XTAL Freq Config +CONFIG_XTAL_FREQ_26=y +CONFIG_XTAL_FREQ=26 diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/CMakeLists.txt new file mode 100644 index 0000000000..333d1e60c4 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ble_acl_latency_periph) diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/README.md b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/README.md new file mode 100644 index 0000000000..3c5f102352 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/README.md @@ -0,0 +1,124 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | + +# ESP-IDF BLE ACL Latency Test - Peripheral + +This example demonstrates how to measure BLE ACL (Asynchronous Connection-Less) link latency. The peripheral acts as a GATT server that echoes back any data written to it, allowing the central device to measure round-trip time (RTT) and calculate one-way latency. + +This demo should be used together with the `cent` (central) example. + +## How It Works + +1. The peripheral advertises with the device name `ESP_ACL_LATENCY` +2. When a central device connects, the peripheral accepts the connection +3. The peripheral provides a GATT service with a characteristic that supports both write and notify +4. When data is written to the characteristic, the peripheral immediately echoes it back via notification +5. The central measures the time between sending and receiving to calculate RTT and latency + +## Test Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ Central │ │ Peripheral │ + │ (GATT Client)│ │ (GATT Server)│ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ │ Advertising + │ │ "ESP_ACL_LATENCY" + │ Scan & Connect │ + │ ─────────────────────────────────────────> │ + │ │ + │ Connection Established │ + │ <─────────────────────────────────────────> │ + │ │ + │ MTU Exchange, Service Discovery │ + │ <─────────────────────────────────────────> │ + │ │ + │ ──────────── Latency Test ───────────── │ + │ │ + │ Write [SEQ=N, 242 bytes] │ + │ ─────────────────────────────────────────> │ + │ ┌───────┴───────┐ + │ │ Echo the same │ + │ │ data back via │ + │ │ Notification │ + │ └───────┬───────┘ + │ Notification [SEQ=N, 242 bytes] │ + │ <───────────────────────────────────────── │ + │ │ + │ ... Repeat for 100 packets ... │ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ Central │ │ Peripheral │ + └──────────────┘ └──────────────┘ + + ┌─────────────────────────────────┐ + │ Latency Calculation │ + ├─────────────────────────────────┤ + │ RTT = recv_time - send_time │ + │ One-way Latency = RTT / 2 │ + │ Typical Result: 6-10 ms │ + └─────────────────────────────────┘ +``` + +## How to Use Example + +### Hardware Required + +* Two development boards with supported SoC (e.g., ESP32-C3-DevKitC, ESP32-DevKitC, etc.) +* Two USB cables for power supply and programming + +See [Development Boards](https://www.espressif.com/en/products/devkits) for more information. + +### Configure the Project + +Before project configuration and build, be sure to set the correct chip target using: + +```bash +idf.py set-target +``` + +### Build and Flash + +Build the project and flash it to the board: + +```bash +idf.py -p PORT flash +``` + +(Replace PORT with the serial port name, e.g., `/dev/ttyUSB0` on Linux or `COM3` on Windows) + +### Monitor + +Run `idf.py -p PORT monitor` to view the serial output. + +(To exit the serial monitor, type `Ctrl-]`.) + +See the [Getting Started Guide](https://idf.espressif.com/) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +``` +I (362) BLE_ACL_LATENCY_PERIPH: BLE ACL Latency Test - Peripheral +I (372) phy_init: phy_version 310,dde1ba9,Jun 4 2024,16:38:11 +I (432) BLE_ACL_LATENCY_PERIPH: GATT server register, status=0, app_id=0 +I (442) BLE_ACL_LATENCY_PERIPH: Create attribute table successfully, the number handle=4 +I (442) BLE_ACL_LATENCY_PERIPH: SERVICE_START_EVT, status=0, service_handle=40 +I (452) BLE_ACL_LATENCY_PERIPH: Advertising started +I (462) BLE_ACL_LATENCY_PERIPH: Peripheral ready, waiting for connection... +I (5532) BLE_ACL_LATENCY_PERIPH: ESP_GATTS_CONNECT_EVT, conn_id=0, remote 7c:df:a1:66:a6:00 +I (5892) BLE_ACL_LATENCY_PERIPH: MTU exchange, MTU=517 +I (5912) BLE_ACL_LATENCY_PERIPH: Connection params updated: status=0, conn_int=6, latency=0, timeout=500 +``` + +## GATT Service Structure + +| Attribute | UUID | Properties | Description | +|-----------|--------|-------------------|---------------------------------| +| Service | 0x1234 | - | Latency test service | +| Char | 0x5678 | Write, Notify | Write data, receive echo back | +| CCCD | 0x2902 | Read, Write | Client Characteristic Config | + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/CMakeLists.txt new file mode 100644 index 0000000000..5c6ae4829f --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "gatts_latency_demo.c" + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/gatts_latency.h b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/gatts_latency.h new file mode 100644 index 0000000000..be0ca817aa --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/gatts_latency.h @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef H_GATTS_LATENCY_ +#define H_GATTS_LATENCY_ + +#include "esp_gatts_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Service UUID */ +#define LATENCY_SERVICE_UUID 0x1234 +#define LATENCY_CHAR_UUID 0x5678 + +/* Profile ID */ +#define PROFILE_APP_ID 0 + +/* Handle table */ +enum { + LATENCY_IDX_SVC, + LATENCY_IDX_CHAR, + LATENCY_IDX_CHAR_VAL, + LATENCY_IDX_CHAR_CFG, + + LATENCY_IDX_NB, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* H_GATTS_LATENCY_ */ diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/gatts_latency_demo.c b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/gatts_latency_demo.c new file mode 100644 index 0000000000..c0e9cab82c --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/main/gatts_latency_demo.c @@ -0,0 +1,360 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_bt.h" + +#include "esp_gap_ble_api.h" +#include "esp_gatts_api.h" +#include "esp_bt_main.h" +#include "esp_gatt_common_api.h" +#include "gatts_latency.h" + +#define GATTS_TAG "BLE_ACL_LATENCY_PERIPH" + +#define DEVICE_NAME "ESP_ACL_LATENCY" +#define GATTS_NUM_HANDLE 4 + +static uint8_t adv_config_done = 0; +#define adv_config_flag (1 << 0) +#define scan_rsp_config_flag (1 << 1) + +/* Advertisement data */ +static esp_ble_adv_data_t adv_data = { + .set_scan_rsp = false, + .include_name = true, + .include_txpower = false, + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), // 7.5ms (minimum) + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), // 20ms + .appearance = 0x00, + .manufacturer_len = 0, + .p_manufacturer_data = NULL, + .service_data_len = 0, + .p_service_data = NULL, + .service_uuid_len = 0, + .p_service_uuid = NULL, + .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), +}; + +/* Scan response data */ +static esp_ble_adv_data_t scan_rsp_data = { + .set_scan_rsp = true, + .include_name = true, + .include_txpower = true, + .appearance = 0x00, + .manufacturer_len = 0, + .p_manufacturer_data = NULL, + .service_data_len = 0, + .p_service_data = NULL, + .service_uuid_len = 0, + .p_service_uuid = NULL, + .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), +}; + +static esp_ble_adv_params_t adv_params = { + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), // 20ms + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), // 40ms + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, +}; + +struct gatts_profile_inst { + esp_gatts_cb_t gatts_cb; + uint16_t gatts_if; + uint16_t app_id; + uint16_t conn_id; + uint16_t service_handle; + esp_gatt_srvc_id_t service_id; + uint16_t char_handle; + esp_bt_uuid_t char_uuid; + esp_gatt_perm_t perm; + esp_gatt_char_prop_t property; + uint16_t descr_handle; + esp_bt_uuid_t descr_uuid; +}; + +static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); + +/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */ +#define PROFILE_NUM 1 +#define PROFILE_APP_IDX 0 + +static struct gatts_profile_inst gl_profile_tab[PROFILE_NUM] = { + [PROFILE_APP_IDX] = { + .gatts_cb = gatts_profile_event_handler, + .gatts_if = ESP_GATT_IF_NONE, + }, +}; + +/* Service */ +static const uint16_t GATTS_SERVICE_UUID = LATENCY_SERVICE_UUID; +static const uint16_t GATTS_CHAR_UUID = LATENCY_CHAR_UUID; + +static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE; +static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE; +static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; +static const uint8_t char_prop_write_notify = ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY; +static uint8_t char_ccc[2] = {0x00, 0x00}; + +/* Full Database Description - Used to add attributes into the database */ +static const esp_gatts_attr_db_t gatt_db[LATENCY_IDX_NB] = +{ + /* Service Declaration */ + [LATENCY_IDX_SVC] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, + sizeof(uint16_t), sizeof(GATTS_SERVICE_UUID), (uint8_t *)&GATTS_SERVICE_UUID}}, + + /* Characteristic Declaration */ + [LATENCY_IDX_CHAR] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, + sizeof(uint8_t), sizeof(uint8_t), (uint8_t *)&char_prop_write_notify}}, + + /* Characteristic Value */ + [LATENCY_IDX_CHAR_VAL] = + {{ESP_GATT_RSP_BY_APP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + 512, 0, NULL}}, + + /* Client Characteristic Configuration Descriptor */ + [LATENCY_IDX_CHAR_CFG] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + sizeof(uint16_t), sizeof(char_ccc), (uint8_t *)char_ccc}}, +}; + +static uint16_t handle_table[LATENCY_IDX_NB]; + +static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + switch (event) { + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: + adv_config_done &= (~adv_config_flag); + if (adv_config_done == 0){ + esp_ble_gap_start_advertising(&adv_params); + } + break; + case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: + adv_config_done &= (~scan_rsp_config_flag); + if (adv_config_done == 0){ + esp_ble_gap_start_advertising(&adv_params); + } + break; + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTS_TAG, "Advertising start failed"); + } else { + ESP_LOGI(GATTS_TAG, "Advertising started"); + } + break; + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTS_TAG, "Advertising stop failed"); + } else { + ESP_LOGI(GATTS_TAG, "Advertising stopped"); + } + break; + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + ESP_LOGI(GATTS_TAG, "Connection params updated: status=%d, conn_int=%d, latency=%d, timeout=%d", + param->update_conn_params.status, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); + break; + default: + break; + } +} + +static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ + switch (event) { + case ESP_GATTS_REG_EVT:{ + ESP_LOGI(GATTS_TAG, "GATT server register, status=%d, app_id=%d", param->reg.status, param->reg.app_id); + gl_profile_tab[PROFILE_APP_IDX].service_id.is_primary = true; + gl_profile_tab[PROFILE_APP_IDX].service_id.id.inst_id = 0x00; + gl_profile_tab[PROFILE_APP_IDX].service_id.id.uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_APP_IDX].service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID; + + esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(DEVICE_NAME); + if (set_dev_name_ret){ + ESP_LOGE(GATTS_TAG, "Set device name failed, error code = %x", set_dev_name_ret); + } + + esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data); + if (ret){ + ESP_LOGE(GATTS_TAG, "Config adv data failed, error code = %x", ret); + } + adv_config_done |= adv_config_flag; + + ret = esp_ble_gap_config_adv_data(&scan_rsp_data); + if (ret){ + ESP_LOGE(GATTS_TAG, "Config scan response data failed, error code = %x", ret); + } + adv_config_done |= scan_rsp_config_flag; + + esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(gatt_db, gatts_if, LATENCY_IDX_NB, 0); + if (create_attr_ret){ + ESP_LOGE(GATTS_TAG, "Create attr table failed, error code = %x", create_attr_ret); + } + } + break; + case ESP_GATTS_READ_EVT: + ESP_LOGD(GATTS_TAG, "ESP_GATTS_READ_EVT"); + break; + case ESP_GATTS_WRITE_EVT: + if (!param->write.is_prep){ + ESP_LOGD(GATTS_TAG, "GATT_WRITE_EVT, handle=%d, value len=%d", param->write.handle, param->write.len); + + if (handle_table[LATENCY_IDX_CHAR_VAL] == param->write.handle) { + /* Echo the data back via notification */ + esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, handle_table[LATENCY_IDX_CHAR_VAL], + param->write.len, param->write.value, false); + } + } + break; + case ESP_GATTS_EXEC_WRITE_EVT: + case ESP_GATTS_MTU_EVT: + ESP_LOGI(GATTS_TAG, "MTU exchange, MTU=%d", param->mtu.mtu); + break; + case ESP_GATTS_CONF_EVT: + break; + case ESP_GATTS_START_EVT: + ESP_LOGI(GATTS_TAG, "SERVICE_START_EVT, status=%d, service_handle=%d", param->start.status, param->start.service_handle); + break; + case ESP_GATTS_CONNECT_EVT: + ESP_LOGI(GATTS_TAG, "ESP_GATTS_CONNECT_EVT, conn_id=%d, remote "ESP_BD_ADDR_STR"", + param->connect.conn_id, ESP_BD_ADDR_HEX(param->connect.remote_bda)); + gl_profile_tab[PROFILE_APP_IDX].conn_id = param->connect.conn_id; + break; + case ESP_GATTS_DISCONNECT_EVT: + ESP_LOGI(GATTS_TAG, "ESP_GATTS_DISCONNECT_EVT, reason=0x%x", param->disconnect.reason); + esp_ble_gap_start_advertising(&adv_params); + break; + case ESP_GATTS_CREAT_ATTR_TAB_EVT:{ + if (param->add_attr_tab.status != ESP_GATT_OK){ + ESP_LOGE(GATTS_TAG, "Create attribute table failed, error code=0x%x", param->add_attr_tab.status); + } + else if (param->add_attr_tab.num_handle != LATENCY_IDX_NB){ + ESP_LOGE(GATTS_TAG, "Create attribute table abnormally, num_handle (%d) \ + doesn't equal to LATENCY_IDX_NB(%d)", param->add_attr_tab.num_handle, LATENCY_IDX_NB); + } + else { + ESP_LOGI(GATTS_TAG, "Create attribute table successfully, the number handle=%d",param->add_attr_tab.num_handle); + memcpy(handle_table, param->add_attr_tab.handles, sizeof(handle_table)); + esp_ble_gatts_start_service(handle_table[LATENCY_IDX_SVC]); + } + break; + } + case ESP_GATTS_STOP_EVT: + case ESP_GATTS_OPEN_EVT: + case ESP_GATTS_CANCEL_OPEN_EVT: + case ESP_GATTS_CLOSE_EVT: + case ESP_GATTS_LISTEN_EVT: + case ESP_GATTS_CONGEST_EVT: + case ESP_GATTS_UNREG_EVT: + case ESP_GATTS_DELETE_EVT: + default: + break; + } +} + +static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ + if (event == ESP_GATTS_REG_EVT) { + if (param->reg.status == ESP_GATT_OK) { + gl_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if; + } else { + ESP_LOGE(GATTS_TAG, "Reg app failed, app_id %04x, status %d", + param->reg.app_id, + param->reg.status); + return; + } + } + do { + int idx; + for (idx = 0; idx < PROFILE_NUM; idx++) { + if (gatts_if == ESP_GATT_IF_NONE || gatts_if == gl_profile_tab[idx].gatts_if) { + if (gl_profile_tab[idx].gatts_cb) { + gl_profile_tab[idx].gatts_cb(event, gatts_if, param); + } + } + } + } while (0); +} + +void app_main(void) +{ + esp_err_t ret; + + ESP_LOGI(GATTS_TAG, "BLE ACL Latency Test - Peripheral"); + + /* Initialize NVS */ + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ret = esp_bt_controller_init(&bt_cfg); + if (ret) { + ESP_LOGE(GATTS_TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); + if (ret) { + ESP_LOGE(GATTS_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_init(); + if (ret) { + ESP_LOGE(GATTS_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_enable(); + if (ret) { + ESP_LOGE(GATTS_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_ble_gatts_register_callback(gatts_event_handler); + if (ret){ + ESP_LOGE(GATTS_TAG, "gatts register error, error code = %x", ret); + return; + } + + ret = esp_ble_gap_register_callback(gap_event_handler); + if (ret){ + ESP_LOGE(GATTS_TAG, "gap register error, error code = %x", ret); + return; + } + + ret = esp_ble_gatts_app_register(PROFILE_APP_ID); + if (ret){ + ESP_LOGE(GATTS_TAG, "gatts app register error, error code = %x", ret); + return; + } + + esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(517); + if (local_mtu_ret){ + ESP_LOGE(GATTS_TAG, "set local MTU failed, error code = %x", local_mtu_ret); + } + + ESP_LOGI(GATTS_TAG, "Peripheral ready, waiting for connection..."); +} diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/sdkconfig.defaults new file mode 100644 index 0000000000..a218a4da6a --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/sdkconfig.defaults @@ -0,0 +1,7 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_LE_50_FEATURE_SUPPORT is not set diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/sdkconfig.defaults.esp32c2 b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/sdkconfig.defaults.esp32c2 new file mode 100644 index 0000000000..9759e23400 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/sdkconfig.defaults.esp32c2 @@ -0,0 +1,13 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32c2" +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_LE_50_FEATURE_SUPPORT is not set +CONFIG_BT_LE_HCI_EVT_BUF_SIZE=257 + +# XTAL Freq Config +CONFIG_XTAL_FREQ_26=y +CONFIG_XTAL_FREQ=26 diff --git a/examples/bluetooth/bluedroid/ble/ble_ancs/README.md b/examples/bluetooth/bluedroid/ble/ble_ancs/README.md index a839e400f8..da4d0ab4d0 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ancs/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_ancs/README.md @@ -5,6 +5,55 @@ The purpose of the Apple Notification Center Service (ANCS) is to give Bluetooth accessories (that connect to iOS devices through a Bluetooth low-energy link) a simple and convenient way to access many kinds of notifications that are generated on iOS devices. +## Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ ESP32 │ │ iOS Device │ + │ (ANCS Client)│ │ (ANCS Server)│ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ─────────── Connection ─────────── │ + │ │ + │ 1. Start Advertising │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 2. iOS connects & pairs │ + │ <─────────────────────────────────────────────── │ + │ │ + │ ─────────── Service Discovery ─────────── │ + │ │ + │ 3. Discover ANCS Service │ + │ (UUID: 7905F431-B5CE-4E99-A40F-4B1E122D00D0) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 4. Subscribe to Notification Source │ + │ (UUID: 9FBF120D-6301-42D9-8C58-25E699A21DBD) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 5. Subscribe to Data Source │ + │ (UUID: 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ ─────────── Notification Flow ─────────── │ + │ │ + │ 6. New notification on iOS │ + │ (Call, SMS, Email, App, etc.) │ + │ <─────────────────────────────────────────────── │ + │ │ + │ 7. Request notification details │ + │ (Write to Control Point) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 8. Receive notification attributes │ + │ (Title, Message, App, etc.) │ + │ <─────────────────────────────────────────────── │ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ ESP32 │ │ iOS Device │ + └──────────────┘ └──────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_ancs/main/ble_ancs_demo.c b/examples/bluetooth/bluedroid/ble/ble_ancs/main/ble_ancs_demo.c index 4dfb0bd4b1..70d6f822b2 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ancs/main/ble_ancs_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_ancs/main/ble_ancs_demo.c @@ -83,8 +83,8 @@ static uint8_t hidd_service_uuid128[] = { static esp_ble_adv_data_t adv_config = { .set_scan_rsp = false, .include_txpower = false, - .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec - .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), //slave connection min interval + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), //slave connection max interval .appearance = ESP_BLE_APPEARANCE_GENERIC_HID, .service_uuid_len = sizeof(hidd_service_uuid128), .p_service_uuid = hidd_service_uuid128, @@ -99,8 +99,8 @@ static esp_ble_adv_data_t scan_rsp_config = { }; static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x100, - .adv_int_max = 0x100, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(160), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(160), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_RPA_PUBLIC, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md index acbae4e97e..4a886f60f0 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md @@ -5,6 +5,52 @@ This example is to test the Bluetooth compatibility and mobile phones. +## Flow Diagram + +``` + ┌──────────────────┐ ┌──────────────────┐ + │ ESP32 BLE │ │ Mobile Phone │ + │ (Compatibility) │ │ (LightBlue App) │ + └────────┬─────────┘ └────────┬─────────┘ + │ │ + │ 1. Initialize BLE │ + │ 2. Create GATT Services │ + │ 3. Start Advertising │ + │ │ + │ ─────────── Test Scenarios ─────────── │ + │ │ + │ Scan & Discover │ + │ <════════════════════════════════════════════│ + │ │ + │ Connection Request │ + │ <════════════════════════════════════════════│ + │ │ + │ Service Discovery │ + │ <════════════════════════════════════════════│ + │ │ + │ Read Characteristic │ + │ <════════════════════════════════════════════│ + │ Read Response │ + │ ════════════════════════════════════════════>│ + │ │ + │ Write Characteristic │ + │ <════════════════════════════════════════════│ + │ Write Confirmation │ + │ ════════════════════════════════════════════>│ + │ │ + │ Enable Notification │ + │ <════════════════════════════════════════════│ + │ Notification Data │ + │ ════════════════════════════════════════════>│ + │ │ + │ Disconnection │ + │ <═══════════════════════════════════════════>│ + │ │ + ┌────────┴─────────┐ ┌────────┴─────────┐ + │ ESP32 BLE │ │ Mobile Phone │ + └──────────────────┘ └──────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c index 171289a8a9..27457f8b4c 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -101,8 +101,8 @@ static esp_ble_adv_data_t adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, - .min_interval = 0x20, - .max_interval = 0x40, + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(40), + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(80), .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //test_manufacturer, @@ -118,8 +118,8 @@ static esp_ble_adv_data_t scan_rsp_data = { .set_scan_rsp = true, .include_name = true, .include_txpower = true, - .min_interval = 0x20, - .max_interval = 0x40, + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(40), + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(80), .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //&test_manufacturer[0], @@ -132,8 +132,8 @@ static esp_ble_adv_data_t scan_rsp_data = { #endif /* CONFIG_SET_RAW_ADV_DATA */ static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x40, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(40), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md index 3ec829bee2..918968fafe 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md @@ -5,11 +5,43 @@ This example demonstrates Eddystone-compatible BLE scanning of eddystone frame, including UID and URL. -Eddystone is an open beacon protocol specification from Google aimed at improving “proximity-based experiences” +Eddystone is an open beacon protocol specification from Google aimed at improving "proximity-based experiences" with support for both Android and iOS smart device platforms. Learn more on [Beacons](https://developers.google.com/nearby/notifications/get-started) and [Eddystone](https://github.com/google/eddystone). +## Flow Diagram + +``` + ┌──────────────────┐ ┌──────────────────┐ + │ Eddystone Sender │ │Eddystone Receiver│ + │ (Advertiser) │ │ (this example) │ + └────────┬─────────┘ └────────┬─────────┘ + │ │ + │ Broadcasting Eddystone Frames │ 1. Initialize BLE + │ │ 2. Start Scanning + │ │ + │ ─────────── Scanning ─────────── │ + │ │ + │ Eddystone UID Frame │ + │ ═══════════════════════════════════════════>│ + │ │ 3. Detect Eddystone + │ │ 4. Parse UID Frame: + │ │ - Namespace ID + │ │ - Instance ID + │ │ - RSSI + │ │ + │ Eddystone URL Frame │ + │ ═══════════════════════════════════════════>│ + │ │ 5. Parse URL Frame: + │ │ - Decode URL + │ │ - TX Power + │ │ + ┌────────┴─────────┐ ┌────────┴─────────┐ + │ Eddystone Sender │ │Eddystone Receiver│ + └──────────────────┘ └──────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_demo.c b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_demo.c index f4849f8b7b..14602043b4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_demo.c @@ -39,8 +39,8 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md index 7cb1a69290..f0251f4412 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md @@ -5,11 +5,43 @@ This example demonstrates Eddystone-compatible BLE sending of eddystone frame, including UID and URL and TLM. -Eddystone is an open beacon protocol specification from Google aimed at improving “proximity-based experiences” +Eddystone is an open beacon protocol specification from Google aimed at improving "proximity-based experiences" with support for both Android and iOS smart device platforms. Learn more on [Beacons](https://developers.google.com/nearby/notifications/get-started) and [Eddystone](https://github.com/google/eddystone). +## Flow Diagram + +``` + ┌──────────────────┐ ┌──────────────────┐ + │ Eddystone Sender │ │ Eddystone Receiver│ + │ (Advertiser) │ │ (Scanner) │ + └────────┬─────────┘ └────────┬─────────┘ + │ │ + │ 1. Initialize BLE │ + │ 2. Configure Eddystone Frame: │ + │ - UID Frame (Namespace + Instance) │ + │ - URL Frame (Encoded URL) │ + │ - TLM Frame (Telemetry Data) │ + │ 3. Set Raw Advertising Data │ + │ 4. Start Advertising │ + │ │ + │ ─────────── Broadcasting ─────────── │ + │ │ + │ Eddystone Advertisement Packet │ + │ ═══════════════════════════════════════════>│ + │ (Broadcast periodically) │ + │ │ + │ │ Parse Frame: + │ │ - UID: Namespace ID + │ │ - URL: Decoded URL + │ │ - TLM: Battery, Temp + │ │ + ┌────────┴─────────┐ ┌────────┴─────────┐ + │ Eddystone Sender │ │ Eddystone Receiver│ + └──────────────────┘ └──────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_demo.c b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_demo.c index 8b62d61d93..9ca3559682 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_demo.c @@ -36,8 +36,8 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* par static void eddystone_send_raw(const esp_eddystone_result_t *res); static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/CMakeLists.txt new file mode 100644 index 0000000000..6daf7bc1f0 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(enc_adv_data_cent) diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/README.md b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/README.md new file mode 100644 index 0000000000..7649b1e653 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/README.md @@ -0,0 +1,273 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | + +# BLE Encrypted Advertising Data Central Example (Bluedroid) + +This example demonstrates how to receive and decrypt BLE Encrypted Advertising Data (EAD) with Bluedroid stack. + +## Overview + +This central example works with the `enc_adv_data_prph` peripheral example to demonstrate: + +1. Scanning for devices that advertise encrypted data +2. Connecting to read the Key Material characteristic +3. Decrypting advertising data using the obtained key + +## Two Operation Modes + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Mode Selection │ +├────────────────────────────────┬────────────────────────────────────────────┤ +│ Mode 1: With Connection │ Mode 2: No Connection │ +│ (Default) │ (Pre-shared Key) │ +├────────────────────────────────┼────────────────────────────────────────────┤ +│ │ │ +│ First scan: │ All scans: │ +│ ┌─────────┐ ┌─────────┐ │ ┌─────────┐ ┌─────────┐ │ +│ │ Central │══▶│ Periph │ │ │ Central │──▶│ Periph │ │ +│ └─────────┘ └─────────┘ │ └─────────┘ └─────────┘ │ +│ │ │ │ │ │ +│ │ Connect │ │ │ Scan only │ +│ │ Read Key │ │ ▼ │ +│ │ Disconnect │ │ Use pre-configured │ +│ ▼ │ │ key to decrypt │ +│ Store key │ │ │ │ +│ │ │ │ ▼ │ +│ ▼ │ │ ✅ Decrypt immediately │ +│ Later scans: │ │ │ +│ ┌─────────┐ ┌─────────┐ │ │ +│ │ Central │──▶│ Periph │ │ │ +│ └─────────┘ └─────────┘ │ │ +│ │ │ │ +│ │ No connection needed │ │ +│ ▼ │ │ +│ ✅ Decrypt using stored key │ │ +│ │ │ +├────────────────────────────────┼────────────────────────────────────────────┤ +│ ✓ Secure key exchange │ ✓ No connection latency │ +│ ✓ Dynamic key support │ ✓ Simpler implementation │ +│ ✗ First-time connection needed │ ✗ Key must be pre-provisioned │ +└────────────────────────────────┴────────────────────────────────────────────┘ +``` + +## System Flow Diagram + +### Mode 1: With Connection (Default) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Central Flow - With Connection Mode │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────┐ ┌─────────────┐ │ +│ │ Central │ │ Peripheral │ │ +│ └────┬────┘ └──────┬──────┘ │ +│ │ │ │ +│ │ ════════════════ First Encounter ════════════════ │ │ +│ │ │ │ +│ │ 1. Scan │ │ +│ │ ──────────────────────────────────────────────────▶ │ │ +│ │ │ │ +│ │ 2. Receive Adv (UUID=0x2C01, Encrypted Data) │ │ +│ │ ◀────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ [No key yet - cannot decrypt] │ │ +│ │ │ │ +│ │ 3. Connect │ │ +│ │ ═══════════════════════════════════════════════════▶│ │ +│ │ │ │ +│ │ 4. Establish Encrypted Link (Pairing) │ │ +│ │ ◀═══════════════════════════════════════════════════│ │ +│ │ │ │ +│ │ 5. Read Key Material Characteristic (0x2B88) │ │ +│ │ ═══════════════════════════════════════════════════▶│ │ +│ │ │ │ +│ │ 6. Response: [Session Key (16B)] [IV (8B)] │ │ +│ │ ◀═══════════════════════════════════════════════════│ │ +│ │ │ │ +│ │ 7. Store key in memory │ │ +│ │ 8. Disconnect │ │ +│ │ ═══════════════════════════════════════════════════▶│ │ +│ │ │ │ +│ │ ════════════════ Later Scans ════════════════════ │ │ +│ │ │ │ +│ │ 9. Scan │ │ +│ │ ──────────────────────────────────────────────────▶ │ │ +│ │ │ │ +│ │ 10. Receive Encrypted Adv Data │ │ +│ │ ◀────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ 11. Decrypt using stored key (NO CONNECTION!) │ │ +│ │ ┌────────────────────────────────────────┐ │ │ +│ │ │ ble_ead_decrypt(session_key, iv, ...) │ │ │ +│ │ │ Result: "prph" (decrypted name) │ │ │ +│ │ └────────────────────────────────────────┘ │ │ +│ │ │ │ +│ ▼ ▼ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Mode 2: No Connection (Pre-shared Key) + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Central Flow - No Connection Mode │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────┐ │ +│ │ Pre-configured Key (same as Peripheral) │ │ +│ │ Session Key: 19 6a 0a d1 2a 61 20 1e │ │ +│ │ 13 6e 2e d1 12 da a9 57 │ │ +│ │ IV: 9E 7a 00 ef b1 7a e7 46 │ │ +│ └─────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────┐ ┌─────────────┐ │ +│ │ Central │ │ Peripheral │ │ +│ └────┬────┘ └──────┬──────┘ │ +│ │ │ │ +│ │ 1. Scan (passive) │ │ +│ │ ──────────────────────────────────────────────────▶ │ │ +│ │ │ │ +│ │ 2. Receive Encrypted Adv Data │ │ +│ │ ◀────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ 3. Immediately decrypt (NO CONNECTION!) │ │ +│ │ ┌────────────────────────────────────────┐ │ │ +│ │ │ ble_ead_decrypt(pre_shared_key, ...) │ │ │ +│ │ │ Result: "prph" (decrypted name) │ │ │ +│ │ └────────────────────────────────────────┘ │ │ +│ │ │ │ +│ ▼ ▼ │ +│ │ +│ ⚡ No connection overhead - instant decryption! │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +## Decryption Process + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Decryption Process │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Received Encrypted Advertising Data: │ +│ ┌───────────────────┬─────────────────────┬─────────────────┐ │ +│ │ Randomizer │ Ciphertext │ MIC │ │ +│ │ (5 bytes) │ (6 bytes) │ (4 bytes) │ │ +│ └─────────┬─────────┴──────────┬──────────┴────────┬────────┘ │ +│ │ │ │ │ +│ ▼ │ │ │ +│ 1. Extract Randomizer │ │ │ +│ ┌─────────────────────┐ │ │ │ +│ │ XX XX XX XX [D|XX] │ │ │ │ +│ └─────────────────────┘ │ │ │ +│ │ │ │ │ +│ ▼ │ │ │ +│ 2. Build Nonce │ │ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Randomizer (5B) + IV from Key Material (8B) = Nonce (13B) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ 3. AES-CCM Decrypt + Verify │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Input: Ciphertext, MIC, Nonce, Session Key, AAD (0xEA) │ │ +│ │ Algorithm: AES-CCM-128 Authenticated Decryption │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ 4. Output: Decrypted Plaintext │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ [05] [09] [70 72 70 68] │ │ +│ │ Len Type 'p' 'r' 'p' 'h' │ │ +│ │ │ │ +│ │ → Complete Local Name: "prph" │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +## How to Use Example + +### Hardware Required + +* Two development boards with ESP32/ESP32-C2/ESP32-C3/ESP32-C5/ESP32-C6/ESP32-C61/ESP32-H2/ESP32-S3 SoC +* USB cables for power supply and programming + +### Setup + +1. Flash `enc_adv_data_prph` on one board (peripheral) +2. Flash `enc_adv_data_cent` on another board (central) + +### Configure the project + +```bash +idf.py set-target +idf.py menuconfig +``` + +In menuconfig, navigate to: +- `Example Configuration` → `Central Mode` + - `With Connection` - Connect to read key (default) + - `No Connection` - Use pre-shared key + +### Build and Flash + +```bash +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type `Ctrl-]`.) + +### Example Output + +**Mode 1 - With Connection (first scan):** +``` +I (XXX) ENC_ADV_CENT: Encrypted Advertising Data Central started +I (XXX) ENC_ADV_CENT: Scanning started +I (XXX) ENC_ADV_CENT: Found target device: xx:xx:xx:xx:xx:xx +I (XXX) ENC_ADV_CENT: Connecting to get key material... +I (XXX) ENC_ADV_CENT: Connected, conn_id 0 +I (XXX) ENC_ADV_CENT: Authentication success +I (XXX) ENC_ADV_CENT: Key material received: +I (XXX) ENC_ADV_CENT: 19 6a 0a d1 2a 61 20 1e 13 6e 2e d1 12 da a9 57 9e 7a 00 ef b1 7a e7 46 +I (XXX) ENC_ADV_CENT: Disconnected +``` + +**Mode 1 - With Connection (subsequent scans):** +``` +I (XXX) ENC_ADV_CENT: Found target device: xx:xx:xx:xx:xx:xx +I (XXX) ENC_ADV_CENT: Have key material, decrypting... +I (XXX) ENC_ADV_CENT: Decryption successful! +I (XXX) ENC_ADV_CENT: Decrypted data: +I (XXX) ENC_ADV_CENT: 05 09 70 72 70 68 +I (XXX) ENC_ADV_CENT: Decrypted device name: prph +``` + +**Mode 2 - No Connection:** +``` +I (XXX) ENC_ADV_CENT_SIMPLE: ======================================== +I (XXX) ENC_ADV_CENT_SIMPLE: EAD Central - No Connection Mode +I (XXX) ENC_ADV_CENT_SIMPLE: ======================================== +I (XXX) ENC_ADV_CENT_SIMPLE: ⚡ This example decrypts WITHOUT connecting! +I (XXX) ENC_ADV_CENT_SIMPLE: 🔍 Scanning started (no connection mode) +... +I (XXX) ENC_ADV_CENT_SIMPLE: ✅ Decryption successful (no connection needed!) +I (XXX) ENC_ADV_CENT_SIMPLE: 📛 Decrypted device name: "prph" +``` + +## Troubleshooting + +### Authentication Failed +- Ensure both devices have matching security parameters +- Try erasing NVS on both devices: `idf.py erase_flash` + +### Decryption Failed +- Verify the peripheral and central use matching session key and IV +- Check that the encrypted advertising data format is correct + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/CMakeLists.txt new file mode 100644 index 0000000000..6bf438be39 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/CMakeLists.txt @@ -0,0 +1,8 @@ +if(CONFIG_EXAMPLE_MODE_NO_CONNECTION) + set(MAIN_SRC "enc_adv_data_cent_no_connect.c") +else() + set(MAIN_SRC "enc_adv_data_cent.c") +endif() + +idf_component_register(SRCS ${MAIN_SRC} "ble_ead.c" + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/Kconfig.projbuild new file mode 100644 index 0000000000..a4c00b02ea --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/Kconfig.projbuild @@ -0,0 +1,22 @@ +menu "Example Configuration" + + choice EXAMPLE_MODE + prompt "Central Mode" + default EXAMPLE_MODE_WITH_CONNECTION + help + Select the central operation mode. + + config EXAMPLE_MODE_WITH_CONNECTION + bool "With Connection (read key from peripheral)" + help + Connect to peripheral to read Key Material characteristic. + This is the standard way when key is not pre-shared. + + config EXAMPLE_MODE_NO_CONNECTION + bool "No Connection (use pre-shared key)" + help + Use pre-configured key to decrypt without connecting. + Key must match the peripheral's key. + endchoice + +endmenu diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/ble_ead.c b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/ble_ead.c new file mode 100644 index 0000000000..92420dd406 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/ble_ead.c @@ -0,0 +1,394 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "ble_ead.h" +#include "esp_random.h" +#include "esp_log.h" +#include "sdkconfig.h" + +#define TAG "BLE_EAD" + +/* Select crypto library based on configuration */ +#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT) +#include "tinycrypt/aes.h" +#include "tinycrypt/ccm_mode.h" +#include "tinycrypt/constants.h" +#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS) +#include "mbedtls/ccm.h" +#else +#error "Please select either CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT or CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS" +#endif + +/* Additional Authenticated Data for EAD - EA (Encrypted Advertising) */ +static const uint8_t ble_ead_aad[BLE_EAD_AAD_SIZE] = { 0xEA }; + +/** + * @brief Generate randomizer with direction bit set + * + * Per Bluetooth Core Spec Supplement v11, Part A 1.23.3: + * The MSB of the Randomizer shall be set to indicate direction + */ +static int ble_ead_generate_randomizer(uint8_t randomizer[BLE_EAD_RANDOMIZER_SIZE]) +{ + /* Generate random bytes */ + esp_fill_random(randomizer, BLE_EAD_RANDOMIZER_SIZE); + + /* Set direction bit (MSB of last byte) - required by spec */ + randomizer[BLE_EAD_RANDOMIZER_SIZE - 1] |= (1 << BLE_EAD_RANDOMIZER_DIRECTION_BIT); + + return 0; +} + +/** + * @brief Generate nonce from IV and randomizer + * + * Nonce = Randomizer (5 bytes) || IV (8 bytes) = 13 bytes + */ +static int ble_ead_generate_nonce(const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t randomizer[BLE_EAD_RANDOMIZER_SIZE], + uint8_t nonce[BLE_EAD_NONCE_SIZE]) +{ + if (iv == NULL || nonce == NULL) { + return -1; + } + + /* Randomizer in first 5 bytes */ + if (randomizer != NULL) { + memcpy(nonce, randomizer, BLE_EAD_RANDOMIZER_SIZE); + } else { + /* Generate new randomizer with direction bit */ + ble_ead_generate_randomizer(nonce); + } + + /* IV in last 8 bytes */ + memcpy(nonce + BLE_EAD_RANDOMIZER_SIZE, iv, BLE_EAD_IV_SIZE); + + return 0; +} + +/** + * @brief AES-CCM encryption using selected crypto library + */ +static int ble_aes_ccm_encrypt(const uint8_t *key, const uint8_t *nonce, + const uint8_t *plaintext, size_t plaintext_len, + const uint8_t *aad, size_t aad_len, + uint8_t *ciphertext, size_t tag_len) +{ +#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT) + struct tc_aes_key_sched_struct sched; + struct tc_ccm_mode_struct ccm_state; + int ret; + + /* Validate inputs */ + if (key == NULL || nonce == NULL || ciphertext == NULL) { + ESP_LOGE(TAG, "Invalid input parameters"); + return -1; + } + + /* Set AES encryption key */ + ret = tc_aes128_set_encrypt_key(&sched, key); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_aes128_set_encrypt_key failed"); + memset(&sched, 0, sizeof(sched)); + return -1; + } + + /* Configure CCM mode */ + ccm_state.sched = &sched; + ccm_state.nonce = (uint8_t *)nonce; + ccm_state.mlen = tag_len; + + ret = tc_ccm_config(&ccm_state, &sched, (uint8_t *)nonce, BLE_EAD_NONCE_SIZE, tag_len); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_config failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Encrypt and generate tag */ + /* TinyCrypt outputs: ciphertext || tag */ + ret = tc_ccm_generation_encryption(ciphertext, plaintext_len + tag_len, + aad, aad_len, + plaintext, plaintext_len, + &ccm_state); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_generation_encryption failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Clear sensitive data from key schedule */ + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return 0; + +#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS) + mbedtls_ccm_context ctx = {0}; + int ret; + + /* Validate inputs */ + if (key == NULL || nonce == NULL || ciphertext == NULL) { + ESP_LOGE(TAG, "Invalid input parameters"); + return -1; + } + + mbedtls_ccm_init(&ctx); + + /* Set encryption key */ + ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + /* Encrypt and authenticate */ + /* mbedtls_ccm_encrypt_and_tag outputs: ciphertext || tag */ + ret = mbedtls_ccm_encrypt_and_tag(&ctx, plaintext_len, + nonce, BLE_EAD_NONCE_SIZE, + aad, aad_len, + plaintext, ciphertext, + ciphertext + plaintext_len, tag_len); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_encrypt_and_tag failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + mbedtls_ccm_free(&ctx); + return 0; +#else + #error "No crypto library selected" +#endif +} + +/** + * @brief AES-CCM decryption with authentication using selected crypto library + */ +static int ble_aes_ccm_decrypt(const uint8_t *key, const uint8_t *nonce, + const uint8_t *ciphertext, size_t ciphertext_len, + const uint8_t *aad, size_t aad_len, + uint8_t *plaintext, size_t tag_len) +{ +#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT) + struct tc_aes_key_sched_struct sched; + struct tc_ccm_mode_struct ccm_state; + int ret; + /* ciphertext_len here includes both ciphertext and tag */ + size_t plaintext_len; + + /* Validate inputs */ + if (key == NULL || nonce == NULL || ciphertext == NULL || plaintext == NULL) { + ESP_LOGE(TAG, "Invalid input parameters"); + return -1; + } + + /* Check for integer underflow */ + if (ciphertext_len < tag_len) { + ESP_LOGE(TAG, "ciphertext_len (%zu) < tag_len (%zu)", ciphertext_len, tag_len); + return -1; + } + + plaintext_len = ciphertext_len - tag_len; + + /* Set AES encryption key */ + ret = tc_aes128_set_encrypt_key(&sched, key); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_aes128_set_encrypt_key failed"); + memset(&sched, 0, sizeof(sched)); + return -1; + } + + /* Configure CCM mode */ + ccm_state.sched = &sched; + ccm_state.nonce = (uint8_t *)nonce; + ccm_state.mlen = tag_len; + + ret = tc_ccm_config(&ccm_state, &sched, (uint8_t *)nonce, BLE_EAD_NONCE_SIZE, tag_len); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_config failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Decrypt and verify tag */ + /* TinyCrypt expects: ciphertext || tag */ + ret = tc_ccm_decryption_verification(plaintext, plaintext_len, + aad, aad_len, + (uint8_t *)ciphertext, ciphertext_len, + &ccm_state); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_decryption_verification failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Clear sensitive data from key schedule */ + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return 0; + +#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS) + mbedtls_ccm_context ctx = {0}; + int ret; + /* ciphertext_len here includes both ciphertext and tag */ + size_t plaintext_len; + + /* Validate inputs */ + if (key == NULL || nonce == NULL || ciphertext == NULL || plaintext == NULL) { + ESP_LOGE(TAG, "Invalid input parameters"); + return -1; + } + + /* Check for integer underflow */ + if (ciphertext_len < tag_len) { + ESP_LOGE(TAG, "ciphertext_len (%zu) < tag_len (%zu)", ciphertext_len, tag_len); + return -1; + } + + plaintext_len = ciphertext_len - tag_len; + + mbedtls_ccm_init(&ctx); + + /* Set decryption key */ + ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + /* Decrypt and verify */ + /* mbedtls_ccm_auth_decrypt expects: ciphertext || tag */ + /* ciphertext_len here already includes tag length */ + ret = mbedtls_ccm_auth_decrypt(&ctx, plaintext_len, + nonce, BLE_EAD_NONCE_SIZE, + aad, aad_len, + ciphertext, plaintext, + ciphertext + plaintext_len, tag_len); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_auth_decrypt failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + mbedtls_ccm_free(&ctx); + return 0; +#else + #error "No crypto library selected" +#endif +} + +int ble_ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *payload, size_t payload_size, + uint8_t *encrypted_payload) +{ + int ret; + uint8_t nonce[BLE_EAD_NONCE_SIZE]; + + if (session_key == NULL) { + ESP_LOGE(TAG, "session_key is NULL"); + return -1; + } + + if (iv == NULL) { + ESP_LOGE(TAG, "iv is NULL"); + return -1; + } + + if (payload == NULL && payload_size > 0) { + ESP_LOGE(TAG, "payload is NULL but payload_size > 0"); + return -1; + } + + if (encrypted_payload == NULL) { + ESP_LOGE(TAG, "encrypted_payload is NULL"); + return -1; + } + + /* Generate nonce with random randomizer */ + ret = ble_ead_generate_nonce(iv, NULL, nonce); + if (ret != 0) { + return ret; + } + + /* Copy randomizer to the start of encrypted payload */ + memcpy(encrypted_payload, nonce, BLE_EAD_RANDOMIZER_SIZE); + + /* Encrypt: output = ciphertext + MIC */ + ret = ble_aes_ccm_encrypt(session_key, nonce, + payload, payload_size, + ble_ead_aad, BLE_EAD_AAD_SIZE, + &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE], + BLE_EAD_MIC_SIZE); + + return ret; +} + +int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *encrypted_payload, size_t encrypted_payload_size, + uint8_t *payload) +{ + int ret; + uint8_t nonce[BLE_EAD_NONCE_SIZE]; + const uint8_t *randomizer; + const uint8_t *ciphertext; + size_t ciphertext_len; + + if (session_key == NULL) { + ESP_LOGE(TAG, "session_key is NULL"); + return -1; + } + + if (iv == NULL) { + ESP_LOGE(TAG, "iv is NULL"); + return -1; + } + + if (encrypted_payload == NULL) { + ESP_LOGE(TAG, "encrypted_payload is NULL"); + return -1; + } + + if (payload == NULL) { + ESP_LOGE(TAG, "payload is NULL"); + return -1; + } + + if (encrypted_payload_size < BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE) { + ESP_LOGE(TAG, "encrypted_payload_size too small"); + return -1; + } + + /* Extract randomizer from the start of encrypted payload */ + randomizer = encrypted_payload; + + /* Ciphertext + MIC follows the randomizer */ + ciphertext = &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE]; + /* ciphertext_len includes both ciphertext and MIC (tag) for mbedTLS API */ + ciphertext_len = encrypted_payload_size - BLE_EAD_RANDOMIZER_SIZE; + + /* Generate nonce from randomizer and IV */ + ret = ble_ead_generate_nonce(iv, randomizer, nonce); + if (ret != 0) { + return ret; + } + + /* Decrypt and verify */ + ret = ble_aes_ccm_decrypt(session_key, nonce, + ciphertext, ciphertext_len, + ble_ead_aad, BLE_EAD_AAD_SIZE, + payload, BLE_EAD_MIC_SIZE); + + return ret; +} diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/ble_ead.h b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/ble_ead.h new file mode 100644 index 0000000000..a9bf8954eb --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/ble_ead.h @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BLE_EAD_H +#define BLE_EAD_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief BLE Encrypted Advertising Data (EAD) definitions + * Based on Bluetooth Core Specification Version 5.4 + */ + +#define BLE_EAD_KEY_SIZE 16 /* 128-bit session key */ +#define BLE_EAD_IV_SIZE 8 /* 64-bit Initialization Vector */ +#define BLE_EAD_RANDOMIZER_SIZE 5 /* 40-bit Randomizer */ +#define BLE_EAD_MIC_SIZE 4 /* 32-bit Message Integrity Check */ +#define BLE_EAD_NONCE_SIZE 13 /* 104-bit Nonce (Randomizer + IV) */ +#define BLE_EAD_AAD_SIZE 1 /* Additional Authenticated Data size */ + +/* Direction bit position in Randomizer (MSB of last byte) + * Per Bluetooth Core Spec Supplement v11, Part A 1.23.3 + */ +#define BLE_EAD_RANDOMIZER_DIRECTION_BIT 7 + +/* AD Type for Encrypted Advertising Data (0x31) */ +#define ESP_BLE_AD_TYPE_ENC_ADV_DATA 0x31 + +/** + * @brief Calculate encrypted payload size from plaintext size + */ +#define BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size) \ + (BLE_EAD_RANDOMIZER_SIZE + (payload_size) + BLE_EAD_MIC_SIZE) + +/** + * @brief Calculate decrypted payload size from encrypted payload size + */ +#define BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_size) \ + ((encrypted_size) - BLE_EAD_RANDOMIZER_SIZE - BLE_EAD_MIC_SIZE) + +/** + * @brief Key material structure for EAD + */ +typedef struct { + uint8_t session_key[BLE_EAD_KEY_SIZE]; /* 128-bit session key */ + uint8_t iv[BLE_EAD_IV_SIZE]; /* 64-bit Initialization Vector */ +} ble_ead_key_material_t; + +/** + * @brief Encrypt advertising data using AES-CCM + * + * @param session_key 16-byte session key + * @param iv 8-byte Initialization Vector + * @param payload Plaintext advertising data to encrypt + * @param payload_size Size of plaintext data + * @param encrypted_payload Output buffer for encrypted data + * Size must be at least BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size) + * + * @return 0 on success, negative error code on failure + */ +int ble_ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *payload, size_t payload_size, + uint8_t *encrypted_payload); + +/** + * @brief Decrypt advertising data using AES-CCM + * + * @param session_key 16-byte session key + * @param iv 8-byte Initialization Vector + * @param encrypted_payload Encrypted advertising data (includes randomizer and MIC) + * @param encrypted_payload_size Size of encrypted data + * @param payload Output buffer for decrypted data + * Size must be at least BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_payload_size) + * + * @return 0 on success, negative error code on failure + */ +int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *encrypted_payload, size_t encrypted_payload_size, + uint8_t *payload); + +#ifdef __cplusplus +} +#endif + +#endif /* BLE_EAD_H */ diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/enc_adv_data_cent.c b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/enc_adv_data_cent.c new file mode 100644 index 0000000000..e03c3b86ad --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/enc_adv_data_cent.c @@ -0,0 +1,519 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +/** + * @brief BLE Encrypted Advertising Data Central Example + * + * This example demonstrates how to: + * 1. Scan for devices broadcasting encrypted advertising data + * 2. Connect to read Key Material characteristic + * 3. Decrypt the advertising data using the obtained key + * + * Based on Bluetooth Core Specification Version 5.4 - Encrypted Advertising Data + */ + +#include +#include +#include +#include +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_bt.h" +#include "esp_gap_ble_api.h" +#include "esp_gattc_api.h" +#include "esp_gatt_defs.h" +#include "esp_bt_main.h" +#include "esp_gatt_common_api.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "ble_ead.h" + +#define TAG "ENC_ADV_CENT" + +/* Service and characteristic UUIDs */ +#define GAP_SERVICE_UUID 0x1800 /* GAP Service UUID */ +#define KEY_MATERIAL_CHAR_UUID 0x2B88 /* Key Material Characteristic UUID */ + +/* Profile configuration */ +#define PROFILE_NUM 1 +#define PROFILE_APP_ID 0 +#define INVALID_HANDLE 0 + +/* Maximum peers to track */ +#define MAX_PEERS 5 + +/* Peer information structure */ +typedef struct { + bool valid; + esp_bd_addr_t addr; + bool key_material_exist; + ble_ead_key_material_t key_material; +} peer_info_t; + +static peer_info_t peers[MAX_PEERS] = {0}; + +/* GATT client state */ +static bool is_connected = false; +static bool get_server = false; +static uint16_t conn_id_stored = 0; +static uint16_t service_start_handle = 0; +static uint16_t service_end_handle = 0; +static uint16_t key_material_char_handle = INVALID_HANDLE; +static esp_bd_addr_t current_peer_addr = {0}; + +/* GATT interface */ +static esp_gatt_if_t gattc_if_stored = ESP_GATT_IF_NONE; + +/* Scan parameters */ +static esp_ble_scan_params_t ble_scan_params = { + .scan_type = BLE_SCAN_TYPE_ACTIVE, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, + .scan_interval = 0x50, + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE, +}; + +/* Forward declarations */ +static void start_scan(void); + +/** + * @brief Find peer by address + */ +static int find_peer(const esp_bd_addr_t addr) +{ + for (int i = 0; i < MAX_PEERS; i++) { + if (peers[i].valid && memcmp(peers[i].addr, addr, sizeof(esp_bd_addr_t)) == 0) { + return i; + } + } + return -1; +} + +/** + * @brief Add or update peer + */ +static int add_peer(const esp_bd_addr_t addr) +{ + int idx = find_peer(addr); + if (idx >= 0) { + return idx; /* Already exists */ + } + + /* Find empty slot */ + for (int i = 0; i < MAX_PEERS; i++) { + if (!peers[i].valid) { + peers[i].valid = true; + memcpy(peers[i].addr, addr, sizeof(esp_bd_addr_t)); + peers[i].key_material_exist = false; + return i; + } + } + return -1; /* No space */ +} + +/** + * @brief Decrypt encrypted advertising data + */ +static void decrypt_enc_adv_data(const uint8_t *adv_data, uint8_t adv_len, const esp_bd_addr_t addr) +{ + int peer_idx = find_peer(addr); + if (peer_idx < 0 || !peers[peer_idx].key_material_exist) { + ESP_LOGW(TAG, "No key material for peer, cannot decrypt"); + return; + } + + uint8_t offset = 0; + while (offset < adv_len) { + uint8_t len = adv_data[offset]; + if (len == 0 || offset + len >= adv_len) { + break; + } + + uint8_t type = adv_data[offset + 1]; + if (type == ESP_BLE_AD_TYPE_ENC_ADV_DATA) { + /* Found encrypted advertising data */ + const uint8_t *enc_data = &adv_data[offset + 2]; + uint8_t enc_data_len = len - 1; /* Exclude type byte */ + + if (enc_data_len < BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE) { + ESP_LOGW(TAG, "Encrypted data too short"); + break; + } + + uint8_t dec_data[32]; /* Buffer for decrypted data */ + size_t dec_len = BLE_EAD_DECRYPTED_PAYLOAD_SIZE(enc_data_len); + + int rc = ble_ead_decrypt( + peers[peer_idx].key_material.session_key, + peers[peer_idx].key_material.iv, + enc_data, enc_data_len, + dec_data); + + if (rc == 0) { + ESP_LOGI(TAG, "Decryption successful!"); + ESP_LOGI(TAG, "Decrypted data:"); + ESP_LOG_BUFFER_HEX(TAG, dec_data, dec_len); + + /* Parse decrypted advertising structure */ + if (dec_len >= 2) { + uint8_t dec_type = dec_data[1]; + if (dec_type == ESP_BLE_AD_TYPE_NAME_CMPL || dec_type == ESP_BLE_AD_TYPE_NAME_SHORT) { + char name[32] = {0}; + size_t name_len = dec_data[0] - 1; + if (name_len < sizeof(name)) { + memcpy(name, &dec_data[2], name_len); + ESP_LOGI(TAG, "Decrypted device name: %s", name); + } + } + } + } else { + ESP_LOGE(TAG, "Decryption failed: %d", rc); + } + break; + } + offset += len + 1; + } +} + +/** + * @brief Check if device advertises GAP service UUID + */ +static bool should_connect(const uint8_t *adv_data, uint8_t adv_len) +{ + uint8_t offset = 0; + while (offset < adv_len) { + uint8_t len = adv_data[offset]; + if (len == 0 || offset + len >= adv_len) { + break; + } + + uint8_t type = adv_data[offset + 1]; + if (type == ESP_BLE_AD_TYPE_16SRV_CMPL || type == ESP_BLE_AD_TYPE_16SRV_PART) { + /* Check for GAP service UUID */ + for (int i = 0; i < len - 1; i += 2) { + uint16_t uuid = adv_data[offset + 2 + i] | (adv_data[offset + 3 + i] << 8); + if (uuid == GAP_SERVICE_UUID) { + return true; + } + } + } + offset += len + 1; + } + return false; +} + +/** + * @brief Start scanning + */ +static void start_scan(void) +{ + esp_ble_gap_start_scanning(30); /* Scan for 30 seconds */ +} + +/** + * @brief GAP event handler + */ +static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + switch (event) { + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: + ESP_LOGI(TAG, "Scan parameters set"); + start_scan(); + break; + + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "Scan start failed: %d", param->scan_start_cmpl.status); + } else { + ESP_LOGI(TAG, "Scanning started"); + } + break; + + case ESP_GAP_BLE_SCAN_RESULT_EVT: { + esp_ble_gap_cb_param_t *scan_result = param; + if (scan_result->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { + uint8_t *adv_data = scan_result->scan_rst.ble_adv; + uint8_t adv_len = scan_result->scan_rst.adv_data_len; + + if (should_connect(adv_data, adv_len)) { + ESP_LOGI(TAG, "Found target device: "ESP_BD_ADDR_STR"", + ESP_BD_ADDR_HEX(scan_result->scan_rst.bda)); + + int peer_idx = find_peer(scan_result->scan_rst.bda); + if (peer_idx >= 0 && peers[peer_idx].key_material_exist) { + /* Already have key, try to decrypt */ + ESP_LOGI(TAG, "Have key material, decrypting..."); + decrypt_enc_adv_data(adv_data, adv_len, scan_result->scan_rst.bda); + } else { + /* Need to connect and get key */ + if (!is_connected) { + ESP_LOGI(TAG, "Connecting to get key material..."); + add_peer(scan_result->scan_rst.bda); + memcpy(current_peer_addr, scan_result->scan_rst.bda, sizeof(esp_bd_addr_t)); + + esp_ble_gap_stop_scanning(); + + esp_ble_gatt_creat_conn_params_t conn_params = {0}; + memcpy(conn_params.remote_bda, scan_result->scan_rst.bda, ESP_BD_ADDR_LEN); + conn_params.remote_addr_type = scan_result->scan_rst.ble_addr_type; + conn_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC; + conn_params.is_direct = true; + conn_params.is_aux = false; + esp_ble_gattc_enh_open(gattc_if_stored, &conn_params); + } + } + } + } else if (scan_result->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) { + ESP_LOGI(TAG, "Scan complete"); + if (!is_connected) { + start_scan(); /* Restart scanning */ + } + } + break; + } + + case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: + ESP_LOGI(TAG, "Scan stopped"); + break; + + case ESP_GAP_BLE_SEC_REQ_EVT: + ESP_LOGI(TAG, "Security request"); + esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true); + break; + + case ESP_GAP_BLE_AUTH_CMPL_EVT: + if (param->ble_security.auth_cmpl.success) { + ESP_LOGI(TAG, "Authentication success"); + } else { + ESP_LOGW(TAG, "Authentication failed: 0x%x", param->ble_security.auth_cmpl.fail_reason); + } + break; + + default: + break; + } +} + +/** + * @brief GATTC event handler + */ +static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) +{ + switch (event) { + case ESP_GATTC_REG_EVT: + ESP_LOGI(TAG, "GATT client registered, status %d, if %d", param->reg.status, gattc_if); + gattc_if_stored = gattc_if; + esp_ble_gap_set_scan_params(&ble_scan_params); + break; + + case ESP_GATTC_CONNECT_EVT: + ESP_LOGI(TAG, "Connected, conn_id %d", param->connect.conn_id); + conn_id_stored = param->connect.conn_id; + is_connected = true; + + /* Request MTU exchange */ + esp_ble_gattc_send_mtu_req(gattc_if, param->connect.conn_id); + break; + + case ESP_GATTC_OPEN_EVT: + if (param->open.status != ESP_GATT_OK) { + ESP_LOGE(TAG, "Open failed: %d", param->open.status); + is_connected = false; + start_scan(); + } + break; + + case ESP_GATTC_CFG_MTU_EVT: + ESP_LOGI(TAG, "MTU configured: %d", param->cfg_mtu.mtu); + break; + + case ESP_GATTC_DIS_SRVC_CMPL_EVT: + ESP_LOGI(TAG, "Service discovery complete"); + /* Search for GAP service that contains Key Material characteristic */ + ESP_LOGI(TAG, "Searching for GAP service UUID 0x%04X", GAP_SERVICE_UUID); + esp_bt_uuid_t gap_uuid = { + .len = ESP_UUID_LEN_16, + .uuid = {.uuid16 = GAP_SERVICE_UUID}, + }; + esp_ble_gattc_search_service(gattc_if, param->dis_srvc_cmpl.conn_id, &gap_uuid); + break; + + case ESP_GATTC_SEARCH_RES_EVT: + ESP_LOGI(TAG, "Service found, UUID 0x%04X, start_handle %d, end_handle %d", + param->search_res.srvc_id.uuid.uuid.uuid16, + param->search_res.start_handle, param->search_res.end_handle); + if (param->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && + param->search_res.srvc_id.uuid.uuid.uuid16 == GAP_SERVICE_UUID) { + get_server = true; + service_start_handle = param->search_res.start_handle; + service_end_handle = param->search_res.end_handle; + } + break; + + case ESP_GATTC_SEARCH_CMPL_EVT: + ESP_LOGI(TAG, "Service search complete"); + if (get_server) { + /* Get characteristics */ + uint16_t count = 0; + esp_ble_gattc_get_attr_count(gattc_if, conn_id_stored, + ESP_GATT_DB_CHARACTERISTIC, + service_start_handle, + service_end_handle, + INVALID_HANDLE, &count); + + if (count > 0) { + esp_gattc_char_elem_t *char_elem = malloc(sizeof(esp_gattc_char_elem_t) * count); + if (char_elem) { + esp_bt_uuid_t km_uuid = { + .len = ESP_UUID_LEN_16, + .uuid = {.uuid16 = KEY_MATERIAL_CHAR_UUID}, + }; + esp_ble_gattc_get_char_by_uuid(gattc_if, conn_id_stored, + service_start_handle, + service_end_handle, + km_uuid, char_elem, &count); + + if (count > 0) { + key_material_char_handle = char_elem[0].char_handle; + ESP_LOGI(TAG, "Key Material characteristic found, handle %d", key_material_char_handle); + + /* Read characteristic with encryption requirement + * GATT layer will automatically trigger encryption if needed */ + ESP_LOGI(TAG, "Reading key material (will trigger encryption if needed)..."); + esp_ble_gattc_read_char(gattc_if, conn_id_stored, + key_material_char_handle, ESP_GATT_AUTH_REQ_NO_MITM); + } + free(char_elem); + } + } + } + break; + + case ESP_GATTC_READ_CHAR_EVT: + if (param->read.status == ESP_GATT_OK) { + ESP_LOGI(TAG, "Read characteristic success, handle %d, len %d", + param->read.handle, param->read.value_len); + + if (param->read.handle == key_material_char_handle && + param->read.value_len == sizeof(ble_ead_key_material_t)) { + /* Store key material */ + int peer_idx = find_peer(current_peer_addr); + if (peer_idx >= 0) { + memcpy(&peers[peer_idx].key_material, param->read.value, + sizeof(ble_ead_key_material_t)); + peers[peer_idx].key_material_exist = true; + + ESP_LOGI(TAG, "Key material received:"); + ESP_LOG_BUFFER_HEX(TAG, &peers[peer_idx].key_material, + sizeof(ble_ead_key_material_t)); + } + + /* Disconnect and resume scanning */ + esp_ble_gattc_close(gattc_if, conn_id_stored); + } + } else { + ESP_LOGE(TAG, "Read failed: %d", param->read.status); + } + break; + + case ESP_GATTC_DISCONNECT_EVT: + ESP_LOGI(TAG, "Disconnected, reason 0x%02x", param->disconnect.reason); + is_connected = false; + get_server = false; + key_material_char_handle = INVALID_HANDLE; + start_scan(); + break; + + default: + break; + } +} + + +void app_main(void) +{ + esp_err_t ret; + + /* Initialize NVS */ + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + /* Release memory for Classic BT */ + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); + + /* Initialize BT controller */ + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ret = esp_bt_controller_init(&bt_cfg); + if (ret) { + ESP_LOGE(TAG, "initialize controller failed: %s", esp_err_to_name(ret)); + return; + } + + ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); + if (ret) { + ESP_LOGE(TAG, "enable controller failed: %s", esp_err_to_name(ret)); + return; + } + + /* Initialize Bluedroid */ + esp_bluedroid_config_t cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT(); + ret = esp_bluedroid_init_with_cfg(&cfg); + if (ret) { + ESP_LOGE(TAG, "init bluetooth failed: %s", esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_enable(); + if (ret) { + ESP_LOGE(TAG, "enable bluetooth failed: %s", esp_err_to_name(ret)); + return; + } + + /* Register callbacks */ + ret = esp_ble_gap_register_callback(gap_event_handler); + if (ret) { + ESP_LOGE(TAG, "gap register error: %x", ret); + return; + } + + ret = esp_ble_gattc_register_callback(gattc_event_handler); + if (ret) { + ESP_LOGE(TAG, "gattc register error: %x", ret); + return; + } + + ret = esp_ble_gattc_app_register(PROFILE_APP_ID); + if (ret) { + ESP_LOGE(TAG, "gattc app register error: %x", ret); + return; + } + + /* Set MTU */ + esp_ble_gatt_set_local_mtu(500); + + /* Configure security parameters + * Using SC (Secure Connections) with bonding, no MITM (since IO_CAP is NONE) + */ + esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_BOND; /* SC + Bond, no MITM */ + esp_ble_io_cap_t io_cap = ESP_IO_CAP_NONE; + uint8_t key_size = 16; + uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; + uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; + + esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(auth_req)); + esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &io_cap, sizeof(io_cap)); + esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(key_size)); + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(init_key)); + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(rsp_key)); + + ESP_LOGI(TAG, "Encrypted Advertising Data Central started"); +} diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/enc_adv_data_cent_no_connect.c b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/enc_adv_data_cent_no_connect.c new file mode 100644 index 0000000000..62416b1ecc --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/main/enc_adv_data_cent_no_connect.c @@ -0,0 +1,239 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +/** + * @brief BLE Encrypted Advertising Data Central Example - No Connection Version + * + * This simplified example demonstrates decrypting advertising data WITHOUT connecting. + * The key material is pre-configured (same as peripheral). + * + * Use case: When the key is pre-shared or provisioned out-of-band. + */ + +#include +#include +#include +#include +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_bt.h" +#include "esp_gap_ble_api.h" +#include "esp_bt_main.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "ble_ead.h" + +#define TAG "ENC_ADV_CENT_SIMPLE" + +/* Custom service UUID to identify target device */ +#define CUSTOM_SERVICE_UUID 0x2C01 + +/* + * Pre-shared Key Material - MUST match the Peripheral! + * In real applications, this would be provisioned securely. + */ +static const ble_ead_key_material_t pre_shared_key = { + .session_key = { + 0x19, 0x6a, 0x0a, 0xd1, 0x2a, 0x61, 0x20, 0x1e, + 0x13, 0x6e, 0x2e, 0xd1, 0x12, 0xda, 0xa9, 0x57 + }, + .iv = {0x9E, 0x7a, 0x00, 0xef, 0xb1, 0x7a, 0xe7, 0x46}, +}; + +/* Scan parameters */ +static esp_ble_scan_params_t ble_scan_params = { + .scan_type = BLE_SCAN_TYPE_PASSIVE, /* Passive scan is enough */ + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, + .scan_interval = 0x50, + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE, +}; + +/** + * @brief Check if device advertises our target service UUID + */ +static bool is_target_device(const uint8_t *adv_data, uint8_t adv_len) +{ + uint8_t offset = 0; + while (offset < adv_len) { + uint8_t len = adv_data[offset]; + if (len == 0 || offset + len >= adv_len) { + break; + } + + uint8_t type = adv_data[offset + 1]; + if (type == ESP_BLE_AD_TYPE_16SRV_CMPL || type == ESP_BLE_AD_TYPE_16SRV_PART) { + for (int i = 0; i < len - 1; i += 2) { + uint16_t uuid = adv_data[offset + 2 + i] | (adv_data[offset + 3 + i] << 8); + if (uuid == CUSTOM_SERVICE_UUID) { + return true; + } + } + } + offset += len + 1; + } + return false; +} + +/** + * @brief Decrypt encrypted advertising data using pre-shared key + * + * No connection required! + */ +static void decrypt_adv_data_no_connect(const uint8_t *adv_data, uint8_t adv_len, + const esp_bd_addr_t addr) +{ + uint8_t offset = 0; + + ESP_LOGI(TAG, "Processing advertising data from "ESP_BD_ADDR_STR"", + ESP_BD_ADDR_HEX(addr)); + + while (offset < adv_len) { + uint8_t len = adv_data[offset]; + if (len == 0 || offset + len >= adv_len) { + break; + } + + uint8_t type = adv_data[offset + 1]; + + /* Look for Encrypted Advertising Data (AD Type 0x31) */ + if (type == ESP_BLE_AD_TYPE_ENC_ADV_DATA) { + const uint8_t *enc_data = &adv_data[offset + 2]; + uint8_t enc_data_len = len - 1; /* Exclude type byte */ + + ESP_LOGI(TAG, "Found encrypted advertising data (%d bytes)", enc_data_len); + ESP_LOG_BUFFER_HEX(TAG, enc_data, enc_data_len); + + if (enc_data_len < BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE) { + ESP_LOGW(TAG, "Encrypted data too short"); + break; + } + + /* Decrypt using pre-shared key */ + uint8_t dec_data[32]; + size_t dec_len = BLE_EAD_DECRYPTED_PAYLOAD_SIZE(enc_data_len); + + int rc = ble_ead_decrypt( + pre_shared_key.session_key, + pre_shared_key.iv, + enc_data, enc_data_len, + dec_data); + + if (rc == 0) { + ESP_LOGI(TAG, "✅ Decryption successful (no connection needed!)"); + ESP_LOGI(TAG, "Decrypted data (%d bytes):", dec_len); + ESP_LOG_BUFFER_HEX(TAG, dec_data, dec_len); + + /* Parse the decrypted advertising structure */ + if (dec_len >= 2) { + uint8_t inner_len = dec_data[0]; + uint8_t inner_type = dec_data[1]; + + if (inner_type == ESP_BLE_AD_TYPE_NAME_CMPL || + inner_type == ESP_BLE_AD_TYPE_NAME_SHORT) { + char name[32] = {0}; + size_t name_len = inner_len - 1; + if (name_len < sizeof(name) && name_len <= dec_len - 2) { + memcpy(name, &dec_data[2], name_len); + ESP_LOGI(TAG, "📛 Decrypted device name: \"%s\"", name); + } + } + } + } else { + ESP_LOGE(TAG, "❌ Decryption failed (rc=%d) - wrong key?", rc); + } + return; /* Found and processed encrypted data */ + } + offset += len + 1; + } + + ESP_LOGW(TAG, "No encrypted advertising data found in this packet"); +} + +/** + * @brief GAP event handler + */ +static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + switch (event) { + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: + ESP_LOGI(TAG, "Scan parameters set, starting scan..."); + esp_ble_gap_start_scanning(0); /* Scan indefinitely */ + break; + + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + if (param->scan_start_cmpl.status == ESP_BT_STATUS_SUCCESS) { + ESP_LOGI(TAG, "🔍 Scanning started (no connection mode)"); + ESP_LOGI(TAG, "Looking for devices with UUID 0x%04X...", CUSTOM_SERVICE_UUID); + } else { + ESP_LOGE(TAG, "Scan start failed: %d", param->scan_start_cmpl.status); + } + break; + + case ESP_GAP_BLE_SCAN_RESULT_EVT: { + esp_ble_gap_cb_param_t *scan_result = param; + + if (scan_result->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { + uint8_t *adv_data = scan_result->scan_rst.ble_adv; + uint8_t adv_len = scan_result->scan_rst.adv_data_len; + + /* Check if this is our target device */ + if (is_target_device(adv_data, adv_len)) { + /* Decrypt without connecting! */ + decrypt_adv_data_no_connect(adv_data, adv_len, scan_result->scan_rst.bda); + } + } + break; + } + + default: + break; + } +} + +void app_main(void) +{ + esp_err_t ret; + + ESP_LOGI(TAG, "========================================"); + ESP_LOGI(TAG, " EAD Central - No Connection Mode"); + ESP_LOGI(TAG, "========================================"); + + /* Initialize NVS */ + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); + ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); + + esp_bluedroid_config_t cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_bluedroid_init_with_cfg(&cfg)); + ESP_ERROR_CHECK(esp_bluedroid_enable()); + + ESP_ERROR_CHECK(esp_ble_gap_register_callback(gap_event_handler)); + + /* Display pre-shared key */ + ESP_LOGI(TAG, "Using pre-shared key material:"); + ESP_LOGI(TAG, " Session Key:"); + ESP_LOG_BUFFER_HEX(TAG, pre_shared_key.session_key, BLE_EAD_KEY_SIZE); + ESP_LOGI(TAG, " IV:"); + ESP_LOG_BUFFER_HEX(TAG, pre_shared_key.iv, BLE_EAD_IV_SIZE); + + /* Start scanning */ + ESP_ERROR_CHECK(esp_ble_gap_set_scan_params(&ble_scan_params)); + + ESP_LOGI(TAG, ""); + ESP_LOGI(TAG, "⚡ This example decrypts WITHOUT connecting!"); + ESP_LOGI(TAG, " Key must be pre-shared with peripheral."); +} diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/sdkconfig.defaults new file mode 100644 index 0000000000..ae0ee30898 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_cent/sdkconfig.defaults @@ -0,0 +1,13 @@ +# Enable BLE +CONFIG_BT_ENABLED=y +CONFIG_BT_BLUEDROID_ENABLED=y +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set + +# Enable SMP for security +CONFIG_BT_BLE_SMP_ENABLE=y + +# Select crypto library for EAD (Encrypted Advertising Data) +# Options: CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT or CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS +CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT=y diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/CMakeLists.txt new file mode 100644 index 0000000000..b78df5cd06 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(enc_adv_data_prph) diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/README.md b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/README.md new file mode 100644 index 0000000000..95e86da46b --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/README.md @@ -0,0 +1,172 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | + +# BLE Encrypted Advertising Data Peripheral Example (Bluedroid) + +This example demonstrates how to use BLE Encrypted Advertising Data (EAD) feature with Bluedroid stack. + +## Overview + +The Encrypted Advertising Data feature (introduced in Bluetooth Core Specification 5.4) allows devices to encrypt portions of their advertising data using AES-CCM. This enables: + +- Privacy protection for sensitive advertising data +- Selective disclosure of advertising data to authorized devices +- Enhanced security for BLE advertising + +## System Architecture + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PERIPHERAL (This Example) │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────┐ │ +│ │ Original Data │───▶│ AES-CCM Encrypt │───▶│ Encrypted Adv Data │ │ +│ │ "prph" (name) │ │ (Session Key+IV)│ │ (Randomizer+Cipher │ │ +│ └─────────────────┘ └──────────────────┘ │ +MIC) │ │ +│ └──────────┬──────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ BLE Advertising Packet │ │ +│ ├──────────┬─────────────┬────────────────┬────────────────────────────┤ │ +│ │ Flags │ Name "key" │ UUID 0x2C01 │ Encrypted Data (AD 0x31) │ │ +│ │ (3B) │ (5B) │ (4B) │ (16B) │ │ +│ └──────────┴─────────────┴────────────────┴────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ GATT Server │ │ +│ ├──────────────────────────────────────────────────────────────────────┤ │ +│ │ GAP Service (0x1800) │ │ +│ │ └── Key Material Characteristic (0x2B88) │ │ +│ │ └── Value: [Session Key (16B)] [IV (8B)] │ │ +│ │ └── Permission: Read (Encrypted Link Required) │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +## Encryption Flow + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Encryption Process │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. Generate Random Randomizer (5 bytes) │ +│ ┌─────────────────────────────────────────┐ │ +│ │ XX XX XX XX [D|XX] │ D = Direction Bit = 1 │ +│ └─────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ 2. Build Nonce (13 bytes) │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Randomizer (5B) │ IV (8B) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ 3. AES-CCM Encryption │ +│ ┌─────────────────┐ │ +│ │ Plaintext │ + Session Key + Nonce + AAD (0xEA) │ +│ │ [05 09 p r p h]│ │ +│ └─────────────────┘ │ +│ │ │ +│ ▼ │ +│ 4. Output: Encrypted Payload │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Randomizer (5B) │ Ciphertext (6B) │ MIC (4B) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +## Advertising Data Format + +``` +Complete Advertising Packet (29 bytes): + +Offset Length Type Data Description +────── ────── ──── ──── ─────────── +0 2 0x01 0x06 Flags: LE General Discoverable +3 4 0x09 'k' 'e' 'y' Complete Local Name +8 3 0x03 0x01 0x2C 16-bit Service UUID: 0x2C01 +12 16 0x31 [Encrypted Payload] Encrypted Advertising Data + +Encrypted Payload Detail: +┌───────────────────┬─────────────────────┬─────────────────┐ +│ Randomizer │ Ciphertext │ MIC │ +│ (5 bytes) │ (6 bytes) │ (4 bytes) │ +│ Random + Dir=1 │ AES-CCM output │ Auth Tag │ +└───────────────────┴─────────────────────┴─────────────────┘ +``` + +## How to Use Example + +### Hardware Required + +* A development board with ESP32/ESP32-C2/ESP32-C3/ESP32-C5/ESP32-C6/ESP32-C61/ESP32-H2/ESP32-S3 SoC +* A USB cable for power supply and programming + +### Configure the project + +```bash +idf.py set-target +idf.py menuconfig +``` + +### Build and Flash + +```bash +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type `Ctrl-]`.) + +### Example Output + +``` +I (XXX) ENC_ADV_PRPH: Encrypted Advertising Data Peripheral started +I (XXX) ENC_ADV_PRPH: Key Material (Session Key + IV): +I (XXX) ENC_ADV_PRPH: 19 6a 0a d1 2a 61 20 1e 13 6e 2e d1 12 da a9 57 9e 7a 00 ef b1 7a e7 46 +I (XXX) ENC_ADV_PRPH: Data before encryption: +I (XXX) ENC_ADV_PRPH: 05 09 70 72 70 68 +I (XXX) ENC_ADV_PRPH: Encryption of adv data done successfully +I (XXX) ENC_ADV_PRPH: Raw advertising data set complete +I (XXX) ENC_ADV_PRPH: Advertising start successfully +``` + +## Testing with Central + +Use the `enc_adv_data_cent` example as the central device: + +``` +┌──────────────────┐ ┌──────────────────┐ +│ PERIPHERAL │ │ CENTRAL │ +│ (This Example) │ │ (enc_adv_data_ │ +│ │ │ cent) │ +└────────┬─────────┘ └────────┬─────────┘ + │ │ + │ 1. Broadcast Encrypted Adv │ + │ ─────────────────────────────────────▶│ + │ │ + │ 2. Connect (first time only) │ + │ ◀═══════════════════════════════════ │ + │ │ + │ 3. Read Key Material (0x2B88) │ + │ ═══════════════════════════════════▶ │ + │ │ + │ 4. Return Session Key + IV │ + │ ◀═══════════════════════════════════ │ + │ │ + │ 5. Disconnect │ + │ ◀═══════════════════════════════════ │ + │ │ + │ 6. Future: Decrypt without connect │ + │ ─────────────────────────────────────▶│ + │ │ + ▼ ▼ +``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/CMakeLists.txt new file mode 100644 index 0000000000..a9fa58c00e --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "enc_adv_data_prph.c" "ble_ead.c" + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/Kconfig.projbuild new file mode 100644 index 0000000000..305d0bfab6 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/Kconfig.projbuild @@ -0,0 +1,14 @@ +menu "Example Configuration" + + config EXAMPLE_ENABLE_KEY_MATERIAL + bool "Enable Key Material characteristic in GAP Service" + default y + select BT_GATTS_KEY_MATERIAL_CHAR + help + Enable the Key Material characteristic in the built-in GAP service + (UUID 0x1800) using the Bluedroid stack's support for this feature. + + This is the standard-compliant approach as defined in Bluetooth + Core Specification Version 5.4. + +endmenu diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/ble_ead.c b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/ble_ead.c new file mode 100644 index 0000000000..cc0abeca1d --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/ble_ead.c @@ -0,0 +1,387 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "ble_ead.h" +#include "esp_random.h" +#include "esp_log.h" +#include "sdkconfig.h" + +#define TAG "BLE_EAD" + +/* Select crypto library based on configuration */ +#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT) +#include "tinycrypt/aes.h" +#include "tinycrypt/ccm_mode.h" +#include "tinycrypt/constants.h" +#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS) +#include "mbedtls/ccm.h" +#else +#error "Please select either CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT or CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS" +#endif + +/* Additional Authenticated Data for EAD - EA (Encrypted Advertising) */ +static const uint8_t ble_ead_aad[BLE_EAD_AAD_SIZE] = { 0xEA }; + +/** + * @brief Generate randomizer with direction bit set + * + * Per Bluetooth Core Spec Supplement v11, Part A 1.23.3: + * The MSB of the Randomizer shall be set to indicate direction + */ +static int ble_ead_generate_randomizer(uint8_t randomizer[BLE_EAD_RANDOMIZER_SIZE]) +{ + /* Generate random bytes */ + esp_fill_random(randomizer, BLE_EAD_RANDOMIZER_SIZE); + + /* Set direction bit (MSB of last byte) - required by spec */ + randomizer[BLE_EAD_RANDOMIZER_SIZE - 1] |= (1 << BLE_EAD_RANDOMIZER_DIRECTION_BIT); + + return 0; +} + +/** + * @brief Generate nonce from IV and randomizer + * + * Nonce = Randomizer (5 bytes) || IV (8 bytes) = 13 bytes + */ +static int ble_ead_generate_nonce(const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t randomizer[BLE_EAD_RANDOMIZER_SIZE], + uint8_t nonce[BLE_EAD_NONCE_SIZE]) +{ + if (iv == NULL || nonce == NULL) { + return -1; + } + + /* Randomizer in first 5 bytes */ + if (randomizer != NULL) { + memcpy(nonce, randomizer, BLE_EAD_RANDOMIZER_SIZE); + } else { + /* Generate new randomizer with direction bit */ + ble_ead_generate_randomizer(nonce); + } + + /* IV in last 8 bytes */ + memcpy(nonce + BLE_EAD_RANDOMIZER_SIZE, iv, BLE_EAD_IV_SIZE); + + return 0; +} + +/** + * @brief AES-CCM encryption using selected crypto library + */ +static int ble_aes_ccm_encrypt(const uint8_t *key, const uint8_t *nonce, + const uint8_t *plaintext, size_t plaintext_len, + const uint8_t *aad, size_t aad_len, + uint8_t *ciphertext, size_t tag_len) +{ +#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT) + struct tc_aes_key_sched_struct sched; + struct tc_ccm_mode_struct ccm_state; + int ret; + + /* Validate inputs */ + if (key == NULL || nonce == NULL || ciphertext == NULL) { + ESP_LOGE(TAG, "Invalid input parameters"); + return -1; + } + + /* Set AES encryption key */ + ret = tc_aes128_set_encrypt_key(&sched, key); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_aes128_set_encrypt_key failed"); + memset(&sched, 0, sizeof(sched)); + return -1; + } + + /* Configure CCM mode */ + ccm_state.sched = &sched; + ccm_state.nonce = (uint8_t *)nonce; + ccm_state.mlen = tag_len; + + ret = tc_ccm_config(&ccm_state, &sched, (uint8_t *)nonce, BLE_EAD_NONCE_SIZE, tag_len); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_config failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Encrypt and generate tag */ + /* TinyCrypt outputs: ciphertext || tag */ + ret = tc_ccm_generation_encryption(ciphertext, plaintext_len + tag_len, + aad, aad_len, + plaintext, plaintext_len, + &ccm_state); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_generation_encryption failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Clear sensitive data from key schedule */ + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return 0; + +#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS) + mbedtls_ccm_context ctx = {0}; + int ret; + + mbedtls_ccm_init(&ctx); + + /* Set encryption key */ + ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + /* Encrypt and authenticate */ + /* mbedtls_ccm_encrypt_and_tag outputs: ciphertext || tag */ + ret = mbedtls_ccm_encrypt_and_tag(&ctx, plaintext_len, + nonce, BLE_EAD_NONCE_SIZE, + aad, aad_len, + plaintext, ciphertext, + ciphertext + plaintext_len, tag_len); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_encrypt_and_tag failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + mbedtls_ccm_free(&ctx); + return 0; +#else + #error "No crypto library selected" +#endif +} + +/** + * @brief AES-CCM decryption with authentication using selected crypto library + */ +static int ble_aes_ccm_decrypt(const uint8_t *key, const uint8_t *nonce, + const uint8_t *ciphertext, size_t ciphertext_len, + const uint8_t *aad, size_t aad_len, + uint8_t *plaintext, size_t tag_len) +{ +#if defined(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT) + struct tc_aes_key_sched_struct sched; + struct tc_ccm_mode_struct ccm_state; + int ret; + /* ciphertext_len here includes both ciphertext and tag */ + size_t plaintext_len; + + /* Validate inputs */ + if (key == NULL || nonce == NULL || ciphertext == NULL || plaintext == NULL) { + ESP_LOGE(TAG, "Invalid input parameters"); + return -1; + } + + /* Check for integer underflow */ + if (ciphertext_len < tag_len) { + ESP_LOGE(TAG, "ciphertext_len (%zu) < tag_len (%zu)", ciphertext_len, tag_len); + return -1; + } + + plaintext_len = ciphertext_len - tag_len; + + /* Set AES encryption key */ + ret = tc_aes128_set_encrypt_key(&sched, key); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_aes128_set_encrypt_key failed"); + memset(&sched, 0, sizeof(sched)); + return -1; + } + + /* Configure CCM mode */ + ccm_state.sched = &sched; + ccm_state.nonce = (uint8_t *)nonce; + ccm_state.mlen = tag_len; + + ret = tc_ccm_config(&ccm_state, &sched, (uint8_t *)nonce, BLE_EAD_NONCE_SIZE, tag_len); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_config failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Decrypt and verify tag */ + /* TinyCrypt expects: ciphertext || tag */ + ret = tc_ccm_decryption_verification(plaintext, plaintext_len, + aad, aad_len, + (uint8_t *)ciphertext, ciphertext_len, + &ccm_state); + if (ret != TC_CRYPTO_SUCCESS) { + ESP_LOGE(TAG, "tc_ccm_decryption_verification failed"); + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return -1; + } + + /* Clear sensitive data from key schedule */ + memset(&sched, 0, sizeof(sched)); + memset(&ccm_state, 0, sizeof(ccm_state)); + return 0; + +#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS) + mbedtls_ccm_context ctx = {0}; + int ret; + /* ciphertext_len here includes both ciphertext and tag */ + size_t plaintext_len; + + /* Validate inputs */ + if (key == NULL || nonce == NULL || ciphertext == NULL || plaintext == NULL) { + ESP_LOGE(TAG, "Invalid input parameters"); + return -1; + } + + /* Check for integer underflow */ + if (ciphertext_len < tag_len) { + ESP_LOGE(TAG, "ciphertext_len (%zu) < tag_len (%zu)", ciphertext_len, tag_len); + return -1; + } + + plaintext_len = ciphertext_len - tag_len; + + mbedtls_ccm_init(&ctx); + + /* Set decryption key */ + ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + /* Decrypt and verify */ + /* mbedtls_ccm_auth_decrypt expects: ciphertext || tag */ + ret = mbedtls_ccm_auth_decrypt(&ctx, plaintext_len, + nonce, BLE_EAD_NONCE_SIZE, + aad, aad_len, + ciphertext, plaintext, + ciphertext + plaintext_len, tag_len); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ccm_auth_decrypt failed: %d", ret); + mbedtls_ccm_free(&ctx); + return -1; + } + + mbedtls_ccm_free(&ctx); + return 0; +#else + #error "No crypto library selected" +#endif +} + +int ble_ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *payload, size_t payload_size, + uint8_t *encrypted_payload) +{ + int ret; + uint8_t nonce[BLE_EAD_NONCE_SIZE]; + + if (session_key == NULL) { + ESP_LOGE(TAG, "session_key is NULL"); + return -1; + } + + if (iv == NULL) { + ESP_LOGE(TAG, "iv is NULL"); + return -1; + } + + if (payload == NULL && payload_size > 0) { + ESP_LOGE(TAG, "payload is NULL but payload_size > 0"); + return -1; + } + + if (encrypted_payload == NULL) { + ESP_LOGE(TAG, "encrypted_payload is NULL"); + return -1; + } + + /* Generate nonce with random randomizer */ + ret = ble_ead_generate_nonce(iv, NULL, nonce); + if (ret != 0) { + return ret; + } + + /* Copy randomizer to the start of encrypted payload */ + memcpy(encrypted_payload, nonce, BLE_EAD_RANDOMIZER_SIZE); + + /* Encrypt: output = ciphertext + MIC */ + ret = ble_aes_ccm_encrypt(session_key, nonce, + payload, payload_size, + ble_ead_aad, BLE_EAD_AAD_SIZE, + &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE], + BLE_EAD_MIC_SIZE); + + return ret; +} + +int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *encrypted_payload, size_t encrypted_payload_size, + uint8_t *payload) +{ + int ret; + uint8_t nonce[BLE_EAD_NONCE_SIZE]; + const uint8_t *randomizer; + const uint8_t *ciphertext; + size_t ciphertext_len; + + if (session_key == NULL) { + ESP_LOGE(TAG, "session_key is NULL"); + return -1; + } + + if (iv == NULL) { + ESP_LOGE(TAG, "iv is NULL"); + return -1; + } + + if (encrypted_payload == NULL) { + ESP_LOGE(TAG, "encrypted_payload is NULL"); + return -1; + } + + if (payload == NULL) { + ESP_LOGE(TAG, "payload is NULL"); + return -1; + } + + if (encrypted_payload_size < BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE) { + ESP_LOGE(TAG, "encrypted_payload_size too small"); + return -1; + } + + /* Extract randomizer from the start of encrypted payload */ + randomizer = encrypted_payload; + + /* Ciphertext + MIC follows the randomizer */ + ciphertext = &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE]; + /* ciphertext_len includes both ciphertext and MIC (tag) for mbedTLS API */ + ciphertext_len = encrypted_payload_size - BLE_EAD_RANDOMIZER_SIZE; + + /* Generate nonce from randomizer and IV */ + ret = ble_ead_generate_nonce(iv, randomizer, nonce); + if (ret != 0) { + return ret; + } + + /* Decrypt and verify */ + ret = ble_aes_ccm_decrypt(session_key, nonce, + ciphertext, ciphertext_len, + ble_ead_aad, BLE_EAD_AAD_SIZE, + payload, BLE_EAD_MIC_SIZE); + + return ret; +} diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/ble_ead.h b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/ble_ead.h new file mode 100644 index 0000000000..a9bf8954eb --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/ble_ead.h @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BLE_EAD_H +#define BLE_EAD_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief BLE Encrypted Advertising Data (EAD) definitions + * Based on Bluetooth Core Specification Version 5.4 + */ + +#define BLE_EAD_KEY_SIZE 16 /* 128-bit session key */ +#define BLE_EAD_IV_SIZE 8 /* 64-bit Initialization Vector */ +#define BLE_EAD_RANDOMIZER_SIZE 5 /* 40-bit Randomizer */ +#define BLE_EAD_MIC_SIZE 4 /* 32-bit Message Integrity Check */ +#define BLE_EAD_NONCE_SIZE 13 /* 104-bit Nonce (Randomizer + IV) */ +#define BLE_EAD_AAD_SIZE 1 /* Additional Authenticated Data size */ + +/* Direction bit position in Randomizer (MSB of last byte) + * Per Bluetooth Core Spec Supplement v11, Part A 1.23.3 + */ +#define BLE_EAD_RANDOMIZER_DIRECTION_BIT 7 + +/* AD Type for Encrypted Advertising Data (0x31) */ +#define ESP_BLE_AD_TYPE_ENC_ADV_DATA 0x31 + +/** + * @brief Calculate encrypted payload size from plaintext size + */ +#define BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size) \ + (BLE_EAD_RANDOMIZER_SIZE + (payload_size) + BLE_EAD_MIC_SIZE) + +/** + * @brief Calculate decrypted payload size from encrypted payload size + */ +#define BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_size) \ + ((encrypted_size) - BLE_EAD_RANDOMIZER_SIZE - BLE_EAD_MIC_SIZE) + +/** + * @brief Key material structure for EAD + */ +typedef struct { + uint8_t session_key[BLE_EAD_KEY_SIZE]; /* 128-bit session key */ + uint8_t iv[BLE_EAD_IV_SIZE]; /* 64-bit Initialization Vector */ +} ble_ead_key_material_t; + +/** + * @brief Encrypt advertising data using AES-CCM + * + * @param session_key 16-byte session key + * @param iv 8-byte Initialization Vector + * @param payload Plaintext advertising data to encrypt + * @param payload_size Size of plaintext data + * @param encrypted_payload Output buffer for encrypted data + * Size must be at least BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(payload_size) + * + * @return 0 on success, negative error code on failure + */ +int ble_ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *payload, size_t payload_size, + uint8_t *encrypted_payload); + +/** + * @brief Decrypt advertising data using AES-CCM + * + * @param session_key 16-byte session key + * @param iv 8-byte Initialization Vector + * @param encrypted_payload Encrypted advertising data (includes randomizer and MIC) + * @param encrypted_payload_size Size of encrypted data + * @param payload Output buffer for decrypted data + * Size must be at least BLE_EAD_DECRYPTED_PAYLOAD_SIZE(encrypted_payload_size) + * + * @return 0 on success, negative error code on failure + */ +int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], + const uint8_t iv[BLE_EAD_IV_SIZE], + const uint8_t *encrypted_payload, size_t encrypted_payload_size, + uint8_t *payload); + +#ifdef __cplusplus +} +#endif + +#endif /* BLE_EAD_H */ diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/enc_adv_data_prph.c b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/enc_adv_data_prph.c new file mode 100644 index 0000000000..7520bbc9d8 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/main/enc_adv_data_prph.c @@ -0,0 +1,353 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +/** + * @brief BLE Encrypted Advertising Data Peripheral Example + * + * This example demonstrates how to: + * 1. Encrypt advertising data using AES-CCM + * 2. Broadcast encrypted advertising data + * 3. Provide Key Material characteristic for central devices to read + * + * Based on Bluetooth Core Specification Version 5.4 - Encrypted Advertising Data + */ + +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_bt.h" +#include "esp_gap_ble_api.h" +#include "esp_gatts_api.h" +#include "esp_bt_defs.h" +#include "esp_bt_main.h" +#include "esp_gatt_common_api.h" +#include "ble_ead.h" + +#define TAG "ENC_ADV_PRPH" + +/* Device name */ +#define DEVICE_NAME "ENC_ADV_PRPH" +#define GAP_SERVICE_UUID 0x1800 /* GAP Service UUID */ + +/* Profile configuration */ +#define PROFILE_NUM 1 +#define PROFILE_APP_ID 0 + +/* Unencrypted advertising pattern to be encrypted */ +static uint8_t unencrypted_adv_pattern[] = { + 0x05, 0x09, 'p', 'r', 'p', 'h' /* Complete Local Name: "prph" */ +}; + +/* Session key and IV for encryption - in real application, generate securely! */ +static ble_ead_key_material_t key_material = { + .session_key = { + 0x19, 0x6a, 0x0a, 0xd1, 0x2a, 0x61, 0x20, 0x1e, + 0x13, 0x6e, 0x2e, 0xd1, 0x12, 0xda, 0xa9, 0x57 + }, + .iv = {0x9E, 0x7a, 0x00, 0xef, 0xb1, 0x7a, 0xe7, 0x46}, +}; + +/* GATT state */ +static esp_gatt_if_t gatts_if_stored = ESP_GATT_IF_NONE; +static uint16_t conn_id_stored = 0; +static bool is_connected = false; + +/* Advertising parameters */ +static esp_ble_adv_params_t adv_params = { + .adv_int_min = 0x20, + .adv_int_max = 0x40, + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, +}; + +/* Calculate encrypted payload size */ +#define ENCRYPTED_ADV_DATA_LEN BLE_EAD_ENCRYPTED_PAYLOAD_SIZE(sizeof(unencrypted_adv_pattern)) + +/** + * @brief Encrypt advertising data and set raw advertising data + */ +static void set_encrypted_adv_data(void) +{ + esp_err_t ret; + uint8_t encrypted_adv_data[ENCRYPTED_ADV_DATA_LEN]; + int rc; + + ESP_LOGI(TAG, "Data before encryption:"); + ESP_LOG_BUFFER_HEX(TAG, unencrypted_adv_pattern, sizeof(unencrypted_adv_pattern)); + + /* Encrypt the advertising data */ + rc = ble_ead_encrypt(key_material.session_key, key_material.iv, + unencrypted_adv_pattern, sizeof(unencrypted_adv_pattern), + encrypted_adv_data); + if (rc != 0) { + ESP_LOGE(TAG, "Encryption of adv data failed: %d", rc); + return; + } + + ESP_LOGI(TAG, "Encryption of adv data done successfully"); + ESP_LOGI(TAG, "Data after encryption:"); + ESP_LOG_BUFFER_HEX(TAG, encrypted_adv_data, sizeof(encrypted_adv_data)); + + /* + * Build raw advertising data: + * - Flags (3 bytes) + * - Complete Local Name (device name) + * - Complete 16-bit Service UUIDs (for central to recognize) + * - Encrypted Advertising Data + */ + uint8_t raw_adv_data[31]; + uint8_t pos = 0; + + /* Flags */ + raw_adv_data[pos++] = 0x02; /* Length */ + raw_adv_data[pos++] = ESP_BLE_AD_TYPE_FLAG; + raw_adv_data[pos++] = ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT; + + /* Complete Local Name - "key" (short name for recognition) */ + raw_adv_data[pos++] = 0x04; /* Length */ + raw_adv_data[pos++] = ESP_BLE_AD_TYPE_NAME_CMPL; + raw_adv_data[pos++] = 'k'; + raw_adv_data[pos++] = 'e'; + raw_adv_data[pos++] = 'y'; + + /* Complete 16-bit Service UUIDs - GAP Service (0x1800) */ + raw_adv_data[pos++] = 0x03; /* Length */ + raw_adv_data[pos++] = ESP_BLE_AD_TYPE_16SRV_CMPL; + raw_adv_data[pos++] = GAP_SERVICE_UUID & 0xFF; + raw_adv_data[pos++] = (GAP_SERVICE_UUID >> 8) & 0xFF; + + /* Encrypted Advertising Data */ + raw_adv_data[pos++] = ENCRYPTED_ADV_DATA_LEN + 1; /* Length */ + raw_adv_data[pos++] = ESP_BLE_AD_TYPE_ENC_ADV_DATA; + memcpy(&raw_adv_data[pos], encrypted_adv_data, ENCRYPTED_ADV_DATA_LEN); + pos += ENCRYPTED_ADV_DATA_LEN; + + /* Set raw advertising data */ + ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, pos); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "config raw adv data failed: %s", esp_err_to_name(ret)); + } +} + +/** + * @brief Start advertising + */ +static void start_advertising(void) +{ + esp_err_t ret = esp_ble_gap_start_advertising(&adv_params); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "start advertising failed: %s", esp_err_to_name(ret)); + } +} + +/** + * @brief GAP event handler + */ +static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + switch (event) { + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: + ESP_LOGI(TAG, "Raw advertising data set complete"); + start_advertising(); + break; + + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "Advertising start failed: %d", param->adv_start_cmpl.status); + } else { + ESP_LOGI(TAG, "Advertising start successfully"); + } + break; + + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "Advertising stop failed: %d", param->adv_stop_cmpl.status); + } else { + ESP_LOGI(TAG, "Advertising stop successfully"); + } + break; + + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + ESP_LOGI(TAG, "Connection params update, status %d, conn_int %d, latency %d, timeout %d", + param->update_conn_params.status, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); + break; + + case ESP_GAP_BLE_SEC_REQ_EVT: + ESP_LOGI(TAG, "Security request received"); + esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true); + break; + + case ESP_GAP_BLE_AUTH_CMPL_EVT: + ESP_LOGI(TAG, "Authentication complete, addr_type %d, addr "ESP_BD_ADDR_STR"", + param->ble_security.auth_cmpl.addr_type, + ESP_BD_ADDR_HEX(param->ble_security.auth_cmpl.bd_addr)); + if (param->ble_security.auth_cmpl.success) { + ESP_LOGI(TAG, "Authentication success, auth_mode %d", param->ble_security.auth_cmpl.auth_mode); + } else { + ESP_LOGW(TAG, "Authentication failed, reason 0x%x", param->ble_security.auth_cmpl.fail_reason); + } + break; + + default: + break; + } +} + +/** + * @brief GATTS profile event handler + */ +static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) +{ + switch (event) { + case ESP_GATTS_REG_EVT: + ESP_LOGI(TAG, "GATT server register, status %d, app_id %d, gatts_if %d", + param->reg.status, param->reg.app_id, gatts_if); + gatts_if_stored = gatts_if; + + /* Set device name */ + esp_ble_gap_set_device_name(DEVICE_NAME); + + /* Set encrypted advertising data */ + set_encrypted_adv_data(); + + /* Set Key Material in GAP service + * The Key Material characteristic is part of the built-in GAP service + */ + ESP_LOGI(TAG, "Setting Key Material in GAP service"); + esp_ble_gap_set_key_material(key_material.session_key, key_material.iv); + break; + + case ESP_GATTS_CONNECT_EVT: + ESP_LOGI(TAG, "Connected, conn_id %d, remote "ESP_BD_ADDR_STR"", + param->connect.conn_id, ESP_BD_ADDR_HEX(param->connect.remote_bda)); + conn_id_stored = param->connect.conn_id; + is_connected = true; + + /* Update connection parameters */ + esp_ble_conn_update_params_t conn_params = {0}; + memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); + conn_params.latency = 0; + conn_params.max_int = 0x20; + conn_params.min_int = 0x10; + conn_params.timeout = 400; + esp_ble_gap_update_conn_params(&conn_params); + break; + + case ESP_GATTS_DISCONNECT_EVT: + ESP_LOGI(TAG, "Disconnected, remote "ESP_BD_ADDR_STR", reason 0x%02x", + ESP_BD_ADDR_HEX(param->disconnect.remote_bda), param->disconnect.reason); + is_connected = false; + + /* Re-encrypt and restart advertising with new randomizer */ + set_encrypted_adv_data(); + break; + + case ESP_GATTS_MTU_EVT: + ESP_LOGI(TAG, "MTU exchange, MTU %d", param->mtu.mtu); + break; + + default: + break; + } +} + +void app_main(void) +{ + esp_err_t ret; + + /* Initialize NVS */ + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + /* Release memory for Classic BT */ + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); + + /* Initialize BT controller */ + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ret = esp_bt_controller_init(&bt_cfg); + if (ret) { + ESP_LOGE(TAG, "initialize controller failed: %s", esp_err_to_name(ret)); + return; + } + + ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); + if (ret) { + ESP_LOGE(TAG, "enable controller failed: %s", esp_err_to_name(ret)); + return; + } + + /* Initialize Bluedroid */ + esp_bluedroid_config_t cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT(); + ret = esp_bluedroid_init_with_cfg(&cfg); + if (ret) { + ESP_LOGE(TAG, "init bluetooth failed: %s", esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_enable(); + if (ret) { + ESP_LOGE(TAG, "enable bluetooth failed: %s", esp_err_to_name(ret)); + return; + } + + /* Register callbacks */ + ret = esp_ble_gatts_register_callback(gatts_event_handler); + if (ret) { + ESP_LOGE(TAG, "gatts register error: %x", ret); + return; + } + + ret = esp_ble_gap_register_callback(gap_event_handler); + if (ret) { + ESP_LOGE(TAG, "gap register error: %x", ret); + return; + } + + /* Register GATT application */ + ret = esp_ble_gatts_app_register(PROFILE_APP_ID); + if (ret) { + ESP_LOGE(TAG, "gatts app register error: %x", ret); + return; + } + + /* Set MTU */ + esp_ble_gatt_set_local_mtu(500); + + /* Configure security parameters for Key Material characteristic access + * Using SC (Secure Connections) with bonding, no MITM (since IO_CAP is NONE) + */ + esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_BOND; /* SC + Bond, no MITM */ + esp_ble_io_cap_t io_cap = ESP_IO_CAP_NONE; + uint8_t key_size = 16; + uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; + uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; + + esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(auth_req)); + esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &io_cap, sizeof(io_cap)); + esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(key_size)); + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(init_key)); + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(rsp_key)); + + ESP_LOGI(TAG, "Encrypted Advertising Data Peripheral started"); + ESP_LOGI(TAG, "Key Material (Session Key + IV):"); + ESP_LOG_BUFFER_HEX(TAG, &key_material, sizeof(key_material)); +} diff --git a/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/sdkconfig.defaults new file mode 100644 index 0000000000..ae0ee30898 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_enc_adv_data/enc_adv_data_prph/sdkconfig.defaults @@ -0,0 +1,13 @@ +# Enable BLE +CONFIG_BT_ENABLED=y +CONFIG_BT_BLUEDROID_ENABLED=y +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set + +# Enable SMP for security +CONFIG_BT_BLE_SMP_ENABLE=y + +# Select crypto library for EAD (Encrypted Advertising Data) +# Options: CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT or CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS +CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT=y diff --git a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/README.md b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/README.md index 95fcaf166a..0bb49a7da4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/README.md @@ -13,6 +13,54 @@ This example implement a BLE HID device profile related functions, in which the Users can choose different reports according to their own application scenarios. BLE HID profile inheritance and USB HID class. +## Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ BLE HID │ │ Host │ + │ Device │ │ (PC/Phone) │ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ─────────── Initialization ─────────── │ + │ │ + │ 1. Create HID Service │ + │ - HID Information Char │ + │ - Report Map Char │ + │ - Report Chars (Mouse/Keyboard/Consumer) │ + │ - HID Control Point Char │ + │ 2. Start Advertising │ + │ │ + │ ─────────── Connection & Pairing ─────────── │ + │ │ + │ Scan & Connect │ + │ <─────────────────────────────────────────────── │ + │ │ + │ Pairing (Bonding) │ + │ <────────────────────────────────────────────────>│ + │ │ + │ Enable Report Notification │ + │ <─────────────────────────────────────────────── │ + │ │ + │ ─────────── HID Data Transfer ─────────── │ + │ │ + │ Send Keyboard Report │ + │ (Key Press/Release) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ Send Mouse Report │ + │ (X/Y Movement, Buttons) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ Send Consumer Report │ + │ (Volume +/-, Media Control) │ + │ ───────────────────────────────────────────────> │ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ BLE HID │ │ Host │ + │ Device │ │ (PC/Phone) │ + └──────────────┘ └──────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/main/ble_hidd_demo_main.c b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/main/ble_hidd_demo_main.c index 0a9240fb92..9922033966 100644 --- a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/main/ble_hidd_demo_main.c +++ b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/main/ble_hidd_demo_main.c @@ -67,8 +67,8 @@ static esp_ble_adv_data_t hidd_adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, - .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec - .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), //slave connection min interval + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), //slave connection max interval .appearance = 0x03c0, //HID Generic, .manufacturer_len = 0, .p_manufacturer_data = NULL, @@ -80,8 +80,8 @@ static esp_ble_adv_data_t hidd_adv_data = { }; static esp_ble_adv_params_t hidd_adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x30, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(30), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, //.peer_addr = diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md b/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md index b375876e87..065a2efe83 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md @@ -5,6 +5,61 @@ From welcoming people as they arrive at a sporting event to providing information about a nearby museum exhibit, iBeacon opens a new world of possibilities for location awareness, and countless opportunities for interactivity between iOS devices and iBeacon hardware. +## Flow Diagram + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ iBeacon System │ +└─────────────────────────────────────────────────────────────────────────────┘ + + ┌──────────────────┐ ┌──────────────────┐ + │ iBeacon Sender │ │ iBeacon Receiver │ + │ (Advertiser) │ │ (Scanner) │ + └────────┬─────────┘ └────────┬─────────┘ + │ │ + │ ─────────── Sender Operation ─────────── │ + │ │ + │ 1. Initialize BLE │ + │ 2. Configure iBeacon Data: │ + │ - Proximity UUID (16 bytes) │ + │ - Major ID (2 bytes) │ + │ - Minor ID (2 bytes) │ + │ - TX Power (1 byte) │ + │ 3. Start Advertising │ + │ │ + │ ─────────── Broadcasting ─────────── │ + │ │ + │ iBeacon Advertisement Packet │ + │ ═══════════════════════════════════════════>│ + │ (Broadcast every ~100ms) │ + │ │ + │ │ ─── Receiver ─── + │ │ + │ │ 1. Start Scan + │ │ 2. Receive Adv + │ │ 3. Parse iBeacon: + │ │ - UUID + │ │ - Major/Minor + │ │ - RSSI + │ │ 4. Calculate + │ │ Distance + │ │ + ┌────────┴─────────┐ ┌────────┴─────────┐ + │ iBeacon Sender │ │ iBeacon Receiver │ + └──────────────────┘ └──────────────────┘ + + + ┌─────────────────────────────────┐ + │ iBeacon Packet Structure │ + ├─────────────────────────────────┤ + │ Prefix: 9 bytes │ + │ UUID: 16 bytes │ + │ Major: 2 bytes │ + │ Minor: 2 bytes │ + │ TX Power: 1 byte │ + └─────────────────────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.c b/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.c index 132eb69195..9dad0849cf 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.c +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.c @@ -29,9 +29,9 @@ const uint8_t uuid_zeros[ESP_UUID_LEN_128] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* For iBeacon packet format, please refer to Apple "Proximity Beacon Specification" doc */ /* Constant part of iBeacon data */ esp_ble_ibeacon_head_t ibeacon_common_head = { - .flags = {0x02, 0x01, 0x06}, + .flags = {0x02, ESP_BLE_AD_TYPE_FLAG, ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT}, .length = 0x1A, - .type = 0xFF, + .type = ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE, .company_id = 0x004C, .beacon_type = 0x1502 }; diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/ibeacon_demo.c b/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/ibeacon_demo.c index 846f7fea31..beaabe96f5 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/ibeacon_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/ibeacon_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -43,15 +43,15 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; #elif (IBEACON_MODE == IBEACON_SENDER) static esp_ble_adv_params_t ble_adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_NONCONN_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/README.md b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/README.md index 8e86afbdbe..51c95b7401 100644 --- a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/README.md @@ -7,6 +7,52 @@ **This example relies on the BLE controller. please use the chip modules listed under Supported Targets.** +## Flow Diagram + +``` + ┌──────────────────────────────────────────────────────────────────────────┐ + │ BLE Multi-Connection Central │ + └──────────────────────────────────────────────────────────────────────────┘ + + ┌───────────────────┐ + │ Multi-Conn Cent │ + │ (GATTC + GATTS) │ + └─────────┬─────────┘ + │ + │ 1. Initialize GATT Client & Server + │ 2. Set Random Address + │ 3. Start Scanning + │ + ▼ + ┌───────────────────────────────────────────────────────────────────────┐ + │ Scan for Peripherals │ + └───────────────────────────────────────────────────────────────────────┘ + │ + │ Found peripheral? + │ + ├───────────────────┬───────────────────┬───────────────────┐ + ▼ ▼ ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ... + │ Peripheral 1 │ │ Peripheral 2 │ │ Peripheral 3 │ + └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ + │ │ │ + │ ─────────── For Each Peripheral ─────────── + │ + │ 4. Stop Scanning + │ 5. Create Connection + │ 6. Update Scheduling Length + │ 7. Connection Established + │ 8. Add to Peer List + │ 9. Change Random Address + │ 10. Resume Scanning + │ + ▼ + ┌───────────────────────────────────────────────────────────────────────┐ + │ All peripherals connected (up to CONFIG limit) │ + │ Maintain multiple connections │ + └───────────────────────────────────────────────────────────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/main/ble_multiconn_cent_demo.c b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/main/ble_multiconn_cent_demo.c index 49bf214bcf..c61853bb8b 100644 --- a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/main/ble_multiconn_cent_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_cent/main/ble_multiconn_cent_demo.c @@ -101,7 +101,7 @@ const static esp_ble_conn_params_t phy_1m_conn_params = { .interval_min = BLE_PREF_CONN_ITVL_MS * 1000 / 1250, .interval_max = BLE_PREF_CONN_ITVL_MS * 1000 / 1250, .latency = 0, - .supervision_timeout = 600, + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), .min_ce_len = BLE_PREF_CE_LEN, .max_ce_len = BLE_PREF_CE_LEN, }; @@ -113,7 +113,7 @@ const static esp_ble_conn_params_t phy_2m_conn_params = { .interval_min = BLE_PREF_CONN_ITVL_MS * 1000 / 1250, .interval_max = BLE_PREF_CONN_ITVL_MS * 1000 / 1250, .latency = 0, - .supervision_timeout = 600, + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), .min_ce_len = BLE_PREF_CE_LEN, .max_ce_len = BLE_PREF_CE_LEN, }; @@ -124,7 +124,7 @@ const static esp_ble_conn_params_t phy_coded_conn_params = { .interval_min = BLE_PREF_CONN_ITVL_MS * 1000 / 1250, .interval_max = BLE_PREF_CONN_ITVL_MS * 1000 / 1250, .latency = 0, - .supervision_timeout = 600, + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), .min_ce_len = BLE_PREF_CE_LEN, .max_ce_len = BLE_PREF_CE_LEN, }; @@ -160,8 +160,8 @@ struct gatts_profile_inst #if (BLE50_SUPPORTED == 0) esp_ble_adv_params_t legacy_adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x20, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(20), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_RANDOM, .channel_map = ADV_CHNL_ALL, @@ -171,8 +171,8 @@ esp_ble_adv_params_t legacy_adv_params = { #else esp_ble_gap_ext_adv_params_t ext_adv_params = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE, - .interval_min = 0x20, - .interval_max = 0x20, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(20), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, diff --git a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/README.md b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/README.md index 01cf4ff01c..2eb99a15f5 100644 --- a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/README.md @@ -7,6 +7,45 @@ **This example relies on the BLE controller. Please use the chip modules listed under Supported Targets.** +## Flow Diagram + +``` + ┌──────────────────────────────────────────────────────────────────────────┐ + │ BLE Multi-Connection Peripheral │ + └──────────────────────────────────────────────────────────────────────────┘ + + ┌───────────────────┐ ┌───────────────────┐ + │ Multi-Conn Prph │ │ Centrals │ + │ (GATT Server) │ │ (1, 2, 3, ...) │ + └─────────┬─────────┘ └─────────┬─────────┘ + │ │ + │ 1. Initialize GATT Server │ + │ 2. Create Service │ + │ 3. Set Random Address │ + │ 4. Start Advertising │ + │ │ + │ ─────────── Connection Loop ─────────── + │ │ + │ Central 1 connects │ + │ <───────────────────────────│ + │ │ + │ 5. Stop Advertising │ + │ 6. Connection Established │ + │ 7. Change Random Address │ + │ 8. Restart Advertising │ + │ │ + │ Central 2 connects │ + │ <───────────────────────────│ + │ │ + │ ... Repeat for each Central ... + │ │ + ▼ │ + ┌───────────────────────────────────────────────────────────────────────┐ + │ Maintain multiple connections simultaneously │ + │ (Limited by CONFIG_BT_ACL_CONNECTIONS) │ + └───────────────────────────────────────────────────────────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/main/ble_multiconn_prph_demo.c b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/main/ble_multiconn_prph_demo.c index 43e6a34a21..91513af992 100644 --- a/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/main/ble_multiconn_prph_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_multi_conn/ble_multi_conn_prph/main/ble_multiconn_prph_demo.c @@ -68,8 +68,8 @@ static esp_ble_gap_ext_adv_t ext_adv[1] = { esp_ble_gap_ext_adv_params_t ext_adv_params = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE, - .interval_min = 0x20, - .interval_max = 0x20, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(20), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, @@ -82,8 +82,8 @@ esp_ble_gap_ext_adv_params_t ext_adv_params = { }; #else static esp_ble_adv_params_t legacy_adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_RANDOM, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md b/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md index e0ca60fd04..72ad1f99b1 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md @@ -9,6 +9,71 @@ This vendor-specific custom profile is implemented in [spp_client_demo.c](../ble_spp_client/main/spp_client_demo.c) and [spp_server_demo.c](../ble_spp_server/main/ble_spp_server_demo.c). +## Flow Diagram + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ BLE SPP Data Flow │ +└─────────────────────────────────────────────────────────────────────────────┘ + + SPP Client SPP Server + ┌───────────┐ ┌───────────┐ + │ UART │ │ UART │ + │ Terminal │ │ Terminal │ + └─────┬─────┘ └─────┬─────┘ + │ │ + ▼ ▼ + ┌───────────┐ ┌───────────┐ + │ uart_task │ │ uart_task │ + └─────┬─────┘ └─────┬─────┘ + │ │ + │ ─────────── Connection Phase ─────────── │ + │ │ + │ 1. Scan for SPP Server │ Advertising + │ ───────────────────────────────────────────────────> │ + │ │ + │ 2. Connect │ + │ ───────────────────────────────────────────────────> │ + │ │ + │ 3. MTU Exchange (200 bytes) │ + │ <────────────────────────────────────────────────────>│ + │ │ + │ 4. Service Discovery │ + │ ───────────────────────────────────────────────────> │ + │ │ + │ 5. Enable Notification (CCCD) │ + │ ───────────────────────────────────────────────────> │ + │ │ + │ ─────────── Data Exchange ─────────── │ + │ │ + │ UART Input ──> WriteNoRsp (SPP_DATA_RECV_CHAR) │ + │ ───────────────────────────────────────────────────> │──> UART Output + │ │ + │ UART Output <── Notification (SPP_DATA_NOTIFY_CHAR) │ + │ <─────────────────────────────────────────────────── │<── UART Input + │ │ + ┌─────┴─────┐ ┌─────┴─────┐ + │ SPP Client│ │SPP Server │ + └───────────┘ └───────────┘ + + + ┌─────────────────────────────────┐ + │ SPP Characteristics │ + ├─────────────────────────────────┤ + │ SPP_DATA_RECV (0xABF1) │ + │ - Client writes data here │ + │ │ + │ SPP_DATA_NOTIFY (0xABF2) │ + │ - Server sends data here │ + │ │ + │ SPP_COMMAND (0xABF3) │ + │ - Command channel │ + │ │ + │ SPP_STATUS (0xABF4) │ + │ - Status notification │ + └─────────────────────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_client/main/spp_client_demo.c b/examples/bluetooth/bluedroid/ble/ble_spp_client/main/spp_client_demo.c index f38d4beff8..9c1b7cf761 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_client/main/spp_client_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_spp_client/main/spp_client_demo.c @@ -89,8 +89,8 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; @@ -255,7 +255,7 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par phy_1m_conn_params.interval_max = 32; phy_1m_conn_params.interval_min = 32; phy_1m_conn_params.latency = 0; - phy_1m_conn_params.supervision_timeout = 600; + phy_1m_conn_params.supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000); esp_ble_gatt_creat_conn_params_t creat_conn_params = {0}; memcpy(&creat_conn_params.remote_bda, scan_result->scan_rst.bda,ESP_BD_ADDR_LEN); creat_conn_params.remote_addr_type = scan_result->scan_rst.ble_addr_type; diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md b/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md index 9f570d67c9..d9b16345ab 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md @@ -5,6 +5,42 @@ For description of this application please refer to [ESP-IDF GATT CLIENT SPP Example](../ble_spp_client/README.md) +## Flow Diagram + +``` + SPP Server SPP Client + ┌───────────┐ ┌───────────┐ + │ UART │ │ UART │ + │ Terminal │ │ Terminal │ + └─────┬─────┘ └─────┬─────┘ + │ │ + │ ─────────── Initialization ─────────── │ + │ │ + │ 1. Create SPP Service (UUID: 0xABF0) │ + │ 2. Add Characteristics │ + │ 3. Start Advertising │ + │ │ + │ ─────────── Connection ─────────── │ + │ │ + │ Scan & Connect │ + │ <─────────────────────────────────────────────────── │ + │ │ + │ Connection Established │ + │ ─────────────────────────────────────────────────────>│ + │ │ + │ ─────────── Data Exchange ─────────── │ + │ │ + │ UART Input ──> Notification (SPP_DATA_NOTIFY_CHAR) │ + │ ─────────────────────────────────────────────────────>│──> UART Output + │ │ + │ UART Output <── WriteNoRsp (SPP_DATA_RECV_CHAR) │ + │ <─────────────────────────────────────────────────── │<── UART Input + │ │ + ┌─────┴─────┐ ┌─────┴─────┐ + │SPP Server │ │ SPP Client│ + └───────────┘ └───────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_server/main/ble_spp_server_demo.c b/examples/bluetooth/bluedroid/ble/ble_spp_server/main/ble_spp_server_demo.c index 8e4351231e..e588c790e1 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_server/main/ble_spp_server_demo.c +++ b/examples/bluetooth/bluedroid/ble/ble_spp_server/main/ble_spp_server_demo.c @@ -52,11 +52,11 @@ static const uint16_t spp_service_uuid = 0xABF0; static const uint8_t spp_adv_data[23] = { /* Flags */ - 0x02,0x01,0x06, + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, /* Complete List of 16-bit Service Class UUIDs */ - 0x03,0x03,0xF0,0xAB, + 0x03, ESP_BLE_AD_TYPE_16SRV_CMPL, 0xF0, 0xAB, /* Complete Local Name in advertising */ - 0x0F,0x09, 'E', 'S', 'P', '_', 'S', 'P', 'P', '_', 'S', 'E', 'R','V', 'E', 'R' + 0x0F, ESP_BLE_AD_TYPE_NAME_CMPL, 'E', 'S', 'P', '_', 'S', 'P', 'P', '_', 'S', 'E', 'R','V', 'E', 'R' }; static uint16_t spp_mtu_size = SPP_GATT_MTU_SIZE; @@ -79,8 +79,8 @@ static esp_bd_addr_t spp_remote_bda = {0x0,}; static uint16_t spp_handle_table[SPP_IDX_NB]; static esp_ble_adv_params_t spp_adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/README.md b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/README.md index 6b90e7a23e..f7a5b0375d 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/README.md @@ -6,6 +6,49 @@ This is the demo used to test the BLE throughput, this demo should used with throughput server demo together. The throughput of BLE can up to 720-767 Kbps between to ESP32 board. +## Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ Throughput │ │ Throughput │ + │ Client │ │ Server │ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ─────────── Connection Setup ─────────── │ + │ │ + │ 1. Scan for "THROUGHPUT_DEMO" │ Advertising + │ ───────────────────────────────────────────────> │ + │ │ + │ 2. Connect │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 3. MTU Exchange (517 bytes) │ + │ <────────────────────────────────────────────────>│ + │ │ + │ 4. Enable Notification │ + │ ───────────────────────────────────────────────> │ + │ │ + │ ─────────── Throughput Test ─────────── │ + │ │ + │ Mode 1: Notify Test (Server → Client) │ + │ <═══════════════════════════════════════════════ │ + │ Continuous notifications (514 bytes/packet) │ + │ │ + │ Mode 2: Write Test (Client → Server) │ + │ ═══════════════════════════════════════════════> │ + │ Continuous writes (514 bytes/packet) │ + │ │ + │ ─────────── Statistics ─────────── │ + │ │ + │ Calculate: Bytes/s, bits/s │ + │ Expected: 600-767 Kbps │ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ Throughput │ │ Throughput │ + │ Client │ │ Server │ + └──────────────┘ └──────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/main/example_ble_client_throughput.c b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/main/example_ble_client_throughput.c index 8759479bbe..adcdde612e 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/main/example_ble_client_throughput.c +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/main/example_ble_client_throughput.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -95,8 +95,8 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; @@ -412,7 +412,7 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par phy_1m_conn_params.interval_min = 32; #endif phy_1m_conn_params.latency = 0; - phy_1m_conn_params.supervision_timeout = 600; + phy_1m_conn_params.supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000); esp_ble_gatt_creat_conn_params_t creat_conn_params = {0}; memcpy(&creat_conn_params.remote_bda, scan_result->scan_rst.bda, ESP_BD_ADDR_LEN); diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/README.md b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/README.md index 18851f22ea..c540c43760 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/README.md @@ -6,6 +6,48 @@ This is the demo used to test the BLE throughput, this demo should used with throughput client demo together. The throughput of BLE can up to 720-767 Kbps between to ESP32 board. +## Flow Diagram + +``` + ┌──────────────────┐ ┌──────────────────┐ + │ Throughput Server│ │ Throughput Client│ + │ (this example) │ │ │ + └────────┬─────────┘ └────────┬─────────┘ + │ │ + │ 1. Initialize BLE │ + │ 2. Create GATT Service │ + │ 3. Add Characteristic (Notify) │ + │ 4. Start Advertising │ + │ │ + │ ─────────── Connection Setup ─────────── │ + │ │ + │ Connection Request │ + │ <════════════════════════════════════════════│ + │ │ + │ 5. Accept Connection │ + │ │ + │ MTU Exchange (517 bytes) │ + │ <═══════════════════════════════════════════>│ + │ │ + │ Enable Notification │ + │ <════════════════════════════════════════════│ + │ │ + │ ─────────── Throughput Test ─────────── │ + │ │ + │ Notification Data (large packets) │ + │ ════════════════════════════════════════════>│ + │ Notification Data (large packets) │ + │ ════════════════════════════════════════════>│ + │ ... (continuous data stream) ... │ + │ ════════════════════════════════════════════>│ + │ │ Calculate + │ │ Throughput + │ │ + ┌────────┴─────────┐ ┌────────┴─────────┐ + │ Throughput Server│ │ Throughput Client│ + └──────────────────┘ └──────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/main/example_ble_server_throughput.c b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/main/example_ble_server_throughput.c index 9569d04c73..8d5492d23c 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/main/example_ble_server_throughput.c +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/main/example_ble_server_throughput.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -127,8 +127,8 @@ static esp_ble_adv_data_t adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, - .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec - .max_interval = 0x000C, //slave connection max interval, Time = max_interval * 1.25 msec + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), //slave connection min interval + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(15), //slave connection max interval .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //&test_manufacturer[0], @@ -143,8 +143,8 @@ static esp_ble_adv_data_t scan_rsp_data = { .set_scan_rsp = true, .include_name = true, .include_txpower = true, - .min_interval = 0x0006, - .max_interval = 0x000C, + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(15), .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //&test_manufacturer[0], @@ -158,8 +158,8 @@ static esp_ble_adv_data_t scan_rsp_data = { #endif /* CONFIG_EXAMPLE_SET_RAW_ADV_DATA */ static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, //.peer_addr = diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/README.md b/examples/bluetooth/bluedroid/ble/gatt_client/README.md index df97a162c5..d7348f8ed1 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_client/README.md @@ -5,6 +5,65 @@ This example shows how to use ESP APIs to create a GATT Client. +## Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ GATT Client │ │ GATT Server │ + │ (this example)│ │(gatt_server) │ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ─────────── Scanning Phase ─────────── │ + │ │ + │ 1. Start Scan │ Advertising + │ ───────────────────────────────────────────────> │ "ESP_GATTS_DEMO" + │ │ + │ 2. Found "ESP_GATTS_DEMO" │ + │ <─────────────────────────────────────────────── │ + │ │ + │ ─────────── Connection Phase ─────────── │ + │ │ + │ 3. Connect │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 4. Connection Established │ + │ <─────────────────────────────────────────────────│ + │ │ + │ 5. MTU Exchange │ + │ <────────────────────────────────────────────────>│ + │ │ + │ ─────────── Service Discovery ─────────── │ + │ │ + │ 6. Discover Service (UUID: 0x00FF) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 7. Service Found │ + │ <─────────────────────────────────────────────── │ + │ │ + │ 8. Get Characteristic (UUID: 0xFF01) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ ─────────── Enable Notification ─────────── │ + │ │ + │ 9. Register for Notify │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 10. Write CCCD (Enable Notify) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ ─────────── Data Exchange ─────────── │ + │ │ + │ 11. Write Characteristic │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 12. Receive Notification │ + │ <─────────────────────────────────────────────── │ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ GATT Client │ │ GATT Server │ + └──────────────┘ └──────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/main/gattc_demo.c b/examples/bluetooth/bluedroid/ble/gatt_client/main/gattc_demo.c index 8c628b685a..481b671df2 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/bluedroid/ble/gatt_client/main/gattc_demo.c @@ -72,8 +72,8 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md b/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md index 2fe96fc901..f6ab4b81a2 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md @@ -5,6 +5,59 @@ This example shows how to use the ESP BLE security APIs to secure connect to and encrypt with peer devices. +## Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ Security │ │ Security │ + │ Client │ │ Server │ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ─────────── Security Parameters Setup ───────── │ + │ │ + │ 1. Set IO Capability │ + │ 2. Set Auth Mode (Bonding, MITM, SC) │ + │ 3. Set Key Distribution │ + │ │ + │ ─────────── Connection Phase ─────────── │ + │ │ + │ 4. Scan for Server │ Advertising + │ ───────────────────────────────────────────────> │ + │ │ + │ 5. Connect │ + │ ───────────────────────────────────────────────> │ + │ │ + │ Connection Established │ + │ <─────────────────────────────────────────────────│ + │ │ + │ ─────────── Pairing & Encryption ─────────── │ + │ │ + │ 6. Start Encryption (esp_ble_set_encryption) │ + │ ───────────────────────────────────────────────> │ + │ │ + │ 7. Exchange Pairing Features │ + │ <────────────────────────────────────────────────>│ + │ │ + │ 8. Generate Keys (LTK, IRK, CSRK) │ + │ <────────────────────────────────────────────────>│ + │ │ + │ 9. Encrypt Link │ + │ <────────────────────────────────────────────────>│ + │ │ + │ 10. ESP_GAP_BLE_AUTH_CMPL_EVT │ + │ <─────────────────────────────────────────────── │ + │ │ + │ ─────────── Secure Data Exchange ─────────── │ + │ │ + │ Encrypted GATT Operations │ + │ <────────────────────────────────────────────────>│ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ Security │ │ Security │ + │ Client │ │ Server │ + └──────────────┘ └──────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/main/example_ble_sec_gattc_demo.c b/examples/bluetooth/bluedroid/ble/gatt_security_client/main/example_ble_sec_gattc_demo.c index 7955da0c71..38fe1f50ce 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_client/main/example_ble_sec_gattc_demo.c +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/main/example_ble_sec_gattc_demo.c @@ -57,8 +57,8 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_RPA_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md b/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md index 36b1d60d27..337689ebc7 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md @@ -9,6 +9,56 @@ To test this example, you can run [gatt_security_client_demo](../gatt_security_c Please, check this [tutorial](tutorial/Gatt_Security_Server_Example_Walkthrough.md) for more information about this example. +## Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ Security │ │ Security │ + │ Server │ │ Client │ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ─────────── Initialization ─────────── │ + │ │ + │ 1. Set Security Parameters │ + │ - IO Capability │ + │ - Auth Requirements │ + │ - Key Size │ + │ 2. Create GATT Service │ + │ 3. Start Advertising │ + │ │ + │ ─────────── Connection ─────────── │ + │ │ + │ Scan & Connect │ + │ <─────────────────────────────────────────────── │ + │ │ + │ ─────────── Security Request ─────────── │ + │ │ + │ ESP_GAP_BLE_SEC_REQ_EVT │ + │ <─────────────────────────────────────────────── │ + │ │ + │ Send Security Response │ + │ ───────────────────────────────────────────────> │ + │ │ + │ ─────────── Pairing Process ─────────── │ + │ │ + │ Exchange Pairing Features │ + │ <────────────────────────────────────────────────>│ + │ │ + │ Key Generation & Distribution │ + │ <────────────────────────────────────────────────>│ + │ │ + │ Link Encrypted │ + │ <────────────────────────────────────────────────>│ + │ │ + │ ESP_GAP_BLE_AUTH_CMPL_EVT │ + │ ───────────────────────────────────────────────> │ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ Security │ │ Security │ + │ Server │ │ Client │ + └──────────────┘ └──────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c b/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c index 35def35da8..9679350b49 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -49,8 +49,8 @@ static uint8_t sec_service_uuid[16] = { static esp_ble_adv_data_t heart_rate_adv_config = { .set_scan_rsp = false, .include_txpower = true, - .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec - .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), //slave connection min interval + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), //slave connection max interval .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //&test_manufacturer[0], @@ -69,8 +69,8 @@ static esp_ble_adv_data_t heart_rate_scan_rsp_config = { }; static esp_ble_adv_params_t heart_rate_adv_params = { - .adv_int_min = 0x100, - .adv_int_max = 0x100, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(160), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(160), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_RPA_PUBLIC, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/README.md b/examples/bluetooth/bluedroid/ble/gatt_server/README.md index fe79948f1c..07c4481b61 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server/README.md @@ -13,6 +13,62 @@ To test this demo, we can run the [gatt_client_demo](../gatt_client), which can Please, check this [tutorial](tutorial/Gatt_Server_Example_Walkthrough.md) for more information about this example. +## Flow Diagram + +``` + ┌──────────────┐ ┌──────────────┐ + │ GATT Server │ │ GATT Client │ + │(this example)│ │(gatt_client) │ + └──────┬───────┘ └──────┬───────┘ + │ │ + │ ─────────── Initialization ─────────── │ + │ │ + │ 1. Register GATT Server App │ + │ 2. Create Service (UUID: 0x00FF) │ + │ 3. Add Characteristic (UUID: 0xFF01) │ + │ 4. Add Descriptor (CCCD) │ + │ 5. Start Service │ + │ 6. Start Advertising "ESP_GATTS_DEMO" │ + │ │ + │ ─────────── Connection Phase ─────────── │ + │ │ + │ Scan & Connect │ + │ <─────────────────────────────────────────────── │ + │ │ + │ Connection Established │ + │ ─────────────────────────────────────────────────>│ + │ │ + │ MTU Exchange │ + │ <────────────────────────────────────────────────>│ + │ │ + │ ─────────── Service Discovery ─────────── │ + │ │ + │ Service Discovery │ + │ <─────────────────────────────────────────────── │ + │ │ + │ Return Service Info │ + │ ─────────────────────────────────────────────────>│ + │ │ + │ ─────────── Enable Notification ─────────── │ + │ │ + │ Write CCCD (0x0001) │ + │ <─────────────────────────────────────────────── │ + │ │ + │ Notification Enabled │ + │ │ + │ ─────────── Data Exchange ─────────── │ + │ │ + │ Write Request │ + │ <─────────────────────────────────────────────── │ + │ │ + │ Send Notification │ + │ ─────────────────────────────────────────────────>│ + │ │ + ┌──────┴───────┐ ┌──────┴───────┐ + │ GATT Server │ │ GATT Client │ + └──────────────┘ └──────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/main/gatts_demo.c b/examples/bluetooth/bluedroid/ble/gatt_server/main/gatts_demo.c index a8b8254bc4..6acc6ff1c3 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/main/gatts_demo.c +++ b/examples/bluetooth/bluedroid/ble/gatt_server/main/gatts_demo.c @@ -118,8 +118,8 @@ static esp_ble_adv_data_t adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = false, - .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec - .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), //slave connection min interval + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), //slave connection max interval .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //&test_manufacturer[0], @@ -149,8 +149,8 @@ static esp_ble_adv_data_t scan_rsp_data = { #endif /* CONFIG_SET_RAW_ADV_DATA */ static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, //.peer_addr = diff --git a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md index 4edb06cf0c..6296ff6ad3 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md @@ -7,6 +7,56 @@ This example shows how to create a GATT service with an attribute table defined Please, check this [tutorial](tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md) for more information about this example. +## Flow Diagram + +``` + ┌──────────────────────────────────────────────────────────────────────────┐ + │ GATT Server Initialization Flow │ + └──────────────────────────────────────────────────────────────────────────┘ + + ┌───────────────────┐ + │ GATT Server │ + └─────────┬─────────┘ + │ + │ 1. Define Attribute Table (gatt_db[]) + │ ┌─────────────────────────────────────┐ + │ │ [0] Service Declaration │ + │ │ [1] Char Declaration │ + │ │ [2] Char Value │ + │ │ [3] CCCD (Notify Enable) │ + │ │ ... │ + │ └─────────────────────────────────────┘ + │ + │ 2. esp_ble_gatts_create_attr_tab() + │ - Create all attributes at once + │ + │ 3. ESP_GATTS_CREAT_ATTR_TAB_EVT + │ - Receive handle table + │ + │ 4. esp_ble_gatts_start_service() + │ + │ 5. Start Advertising + │ + ▼ + ┌───────────────────┐ ┌───────────────────┐ + │ GATT Server │ │ GATT Client │ + │ (Advertising) │ │ │ + └─────────┬─────────┘ └─────────┬─────────┘ + │ │ + │ Scan & Connect │ + │ <───────────────────────────────────────────│ + │ │ + │ Service Discovery │ + │ ───────────────────────────────────────────>│ + │ │ + │ Read/Write/Notify Operations │ + │ <──────────────────────────────────────────>│ + │ │ + ┌─────────┴─────────┐ ┌─────────┴─────────┐ + │ GATT Server │ │ GATT Client │ + └───────────────────┘ └───────────────────┘ +``` + ## How to Use Example Before project configuration and build, be sure to set the correct chip target using: diff --git a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/main/gatts_table_creat_demo.c b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/main/gatts_table_creat_demo.c index 9c468cd351..bc088bcc29 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/main/gatts_table_creat_demo.c +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/main/gatts_table_creat_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -94,8 +94,8 @@ static esp_ble_adv_data_t adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, - .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec - .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), //slave connection min interval + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), //slave connection max interval .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //test_manufacturer, @@ -111,8 +111,8 @@ static esp_ble_adv_data_t scan_rsp_data = { .set_scan_rsp = true, .include_name = true, .include_txpower = true, - .min_interval = 0x0006, - .max_interval = 0x0010, + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), .appearance = 0x00, .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, .p_manufacturer_data = NULL, //&test_manufacturer[0], @@ -125,8 +125,8 @@ static esp_ble_adv_data_t scan_rsp_data = { #endif /* CONFIG_SET_RAW_ADV_DATA */ static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, diff --git a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md index 889efc13fe..af422337b0 100644 --- a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md +++ b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md @@ -3,34 +3,169 @@ # ESP-IDF Gatt Client Multi Connection Example -This example shows the usage of APIs to create a GATT multi-connection client. It can be used to connect to three GATT servers at the same time. +This example demonstrates how to use the BLE GATT client APIs to create a multi-connection client that can connect to multiple GATT servers simultaneously. By default, it supports connecting to up to 3 GATT servers at the same time. -To test this example, please run [gatt_server_demo](../gatt_server) to create three GATT server devices, namely ESP_GATTS_DEMO_a, ESP_GATTS_DEMO_b and ESP_GATTS_DEMO_c, `Gatt_client_multi_connection_demo` will connect to these three gatt server demos, and then exchange data. +## How It Works -Please, check this [tutorial](tutorial/Gatt_Client_Multi_Connection_Example_Walkthrough.md) for more information about this example. +The example creates three GATT client profiles (A, B, C), each corresponding to one connection. It scans for devices with specific names, connects to them, discovers services, registers for notifications, and exchanges data with each server. + +### Target Devices + +The example searches for three GATT servers with the following names: +- `ESP_GATTS_DEMO_a` → Profile A +- `ESP_GATTS_DEMO_b` → Profile B +- `ESP_GATTS_DEMO_c` → Profile C + +You can use the [gatt_server](../gatt_server) example to create these server devices by modifying the device name. + +## Flow Diagram + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ GATT Client Multi-Connection │ +└─────────────────────────────────────────────────────────────────────────────┘ + + ┌──────────────────┐ + │ GATTC Client │ + │ (Multi-Connect) │ + └────────┬─────────┘ + │ + │ 1. Start Scanning + │ + ▼ + ┌────────────────────────────────────────────────────────────────────────┐ + │ Scan for BLE Devices │ + │ Looking for: ESP_GATTS_DEMO_a, _b, _c │ + └────────────────────────────────────────────────────────────────────────┘ + │ + │ Found device matching name? + │ + ├─────────────────────┬─────────────────────┐ + ▼ ▼ ▼ + ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ + │ ESP_GATTS_DEMO_a│ │ ESP_GATTS_DEMO_b│ │ ESP_GATTS_DEMO_c│ + │ (Server A) │ │ (Server B) │ │ (Server C) │ + └───────┬────────┘ └───────┬────────┘ └───────┬────────┘ + │ │ │ + ▼ ▼ ▼ + ┌───────────────────────────────────────────────────────────────────────┐ + │ For Each Connected Device: │ + ├───────────────────────────────────────────────────────────────────────┤ + │ 2. Stop Scanning │ + │ 3. Connect (esp_ble_gattc_enh_open) │ + │ 4. MTU Exchange │ + │ 5. Service Discovery (UUID: 0x00FF) │ + │ 6. Find Characteristic (UUID: 0xFF01) │ + │ 7. Register for Notification │ + │ 8. Write CCCD (Enable Notification) │ + │ 9. Write Test Data (35 bytes) │ + │ 10. Resume Scanning for remaining devices │ + └───────────────────────────────────────────────────────────────────────┘ + │ + │ All 3 devices connected? + ▼ + ┌────────────────────────────────────────────────────────────────────────┐ + │ Stop Scanning │ + │ Continue receiving notifications from all devices │ + └────────────────────────────────────────────────────────────────────────┘ + + + ┌────────────────────────────────────┐ + │ Connection Sequence Detail │ + └────────────────────────────────────┘ + + Client Server + │ │ + │ ─────────── Connection Phase ─────────── │ + │ │ + │ Connect Request │ + │ ────────────────────────────────────────────────> │ + │ │ + │ Connection Established │ + │ <────────────────────────────────────────────────>│ + │ │ + │ MTU Exchange Request │ + │ ────────────────────────────────────────────────> │ + │ │ + │ MTU Exchange Response │ + │ <──────────────────────────────────────────────── │ + │ │ + │ ─────────── Service Discovery ─────────── │ + │ │ + │ Discover Services (UUID: 0x00FF) │ + │ ────────────────────────────────────────────────> │ + │ │ + │ Service Found │ + │ <──────────────────────────────────────────────── │ + │ │ + │ Get Characteristic (UUID: 0xFF01) │ + │ ────────────────────────────────────────────────> │ + │ │ + │ Characteristic Found │ + │ <──────────────────────────────────────────────── │ + │ │ + │ ─────────── Enable Notification ─────────── │ + │ │ + │ Register for Notify │ + │ ────────────────────────────────────────────────> │ + │ │ + │ Write CCCD (0x0001 = Enable Notify) │ + │ ────────────────────────────────────────────────> │ + │ │ + │ ─────────── Data Exchange ─────────── │ + │ │ + │ Write Characteristic (35 bytes test data) │ + │ ────────────────────────────────────────────────> │ + │ │ + │ Notification (data from server) │ + │ <──────────────────────────────────────────────── │ + │ │ +``` ## How to Use Example -Before project configuration and build, be sure to set the correct chip target using: +### Hardware Required + +* Four development boards with supported SoC: + - One board for the GATT Client (this example) + - Three boards for GATT Servers (using [gatt_server](../gatt_server) example) +* Four USB cables for power supply and programming + +See [Development Boards](https://www.espressif.com/en/products/devkits) for more information. + +### Setup GATT Servers + +1. Flash the [gatt_server](../gatt_server) example to three separate boards +2. Modify each server's device name before flashing: + - Server 1: Change `ESP_GATT_DEMO` to `ESP_GATTS_DEMO_a` + - Server 2: Change `ESP_GATT_DEMO` to `ESP_GATTS_DEMO_b` + - Server 3: Change `ESP_GATT_DEMO` to `ESP_GATTS_DEMO_c` + +### Configure the Project + +Set the correct chip target: ```bash idf.py set-target ``` -The code can be modified to connect to more devices (up to 4 devices by default). If you need to connect to more devices (more than 4 devices), you need to change `BT/BLE MAX ACL CONNECTIONS` in menuconfig. +**Connecting More Than 4 Devices:** -### Hardware Required +The default maximum number of ACL connections is 4. To connect more devices: -* A development board with ESP32/ESP32-C3/ESP32-C2/ESP32-H2/ESP32-S3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) -* A USB cable for Power supply and programming +```bash +idf.py menuconfig +``` -See [Development Boards](https://www.espressif.com/en/products/devkits) for more information about it. +Navigate to: `Component config` → `Bluetooth` → `Bluedroid Options` → `BT/BLE MAX ACL CONNECTIONS` ### Build and Flash -Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. +```bash +idf.py -p PORT flash monitor +``` -(To exit the serial monitor, type ``Ctrl-]``.) +(To exit the serial monitor, type `Ctrl-]`.) See the [Getting Started Guide](https://idf.espressif.com/) for full steps to configure and use ESP-IDF to build projects. diff --git a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/main/gattc_multi_connect.c b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/main/gattc_multi_connect.c index 0908e5e4ee..213523d05c 100644 --- a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/main/gattc_multi_connect.c +++ b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/main/gattc_multi_connect.c @@ -92,8 +92,8 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c index 720fd61924..06c1274953 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -66,32 +66,32 @@ static esp_ble_ext_scan_params_t ext_scan_params = { }; const esp_ble_conn_params_t phy_1m_conn_params = { - .scan_interval = 0x40, - .scan_window = 0x40, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(40), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(40), .interval_min = 320, .interval_max = 320, .latency = 0, - .supervision_timeout = 600, + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), .min_ce_len = 0, .max_ce_len = 0, }; const esp_ble_conn_params_t phy_2m_conn_params = { - .scan_interval = 0x40, - .scan_window = 0x40, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(40), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(40), .interval_min = 320, .interval_max = 320, .latency = 0, - .supervision_timeout = 600, + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), .min_ce_len = 0, .max_ce_len = 0, }; const esp_ble_conn_params_t phy_coded_conn_params = { - .scan_interval = 0x40, - .scan_window = 0x40, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(40), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(40), .interval_min = 320, // 306-> 362Kbps .interval_max = 320, .latency = 0, - .supervision_timeout = 600, + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), .min_ce_len = 0, .max_ce_len = 0, }; diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c index e5727564e4..4fc1019724 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -41,9 +41,9 @@ static uint16_t profile_handle_table[HRS_IDX_NB]; static uint8_t ext_adv_raw_data[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, 0x03, 0x03, 0xab, 0xcd, - 0x11, 0X09, 'E', 'S', 'P', '_', 'B', 'L', 'E', '5', '0', '_', 'S', 'E', 'R', 'V', 'E', 'R', + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, + 0x02, ESP_BLE_AD_TYPE_TX_PWR, 0xeb, 0x03, ESP_BLE_AD_TYPE_16SRV_CMPL, 0xab, 0xcd, + 0x11, ESP_BLE_AD_TYPE_NAME_CMPL, 'E', 'S', 'P', '_', 'B', 'L', 'E', '5', '0', '_', 'S', 'E', 'R', 'V', 'E', 'R', }; static esp_ble_gap_ext_adv_t ext_adv[1] = { @@ -52,8 +52,8 @@ static esp_ble_gap_ext_adv_t ext_adv[1] = { esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE, - .interval_min = 0x20, - .interval_max = 0x20, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(20), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/main/example_ble_client_throughput.c b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/main/example_ble_client_throughput.c index 17c9a99d82..fb002f1e7e 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/main/example_ble_client_throughput.c +++ b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/main/example_ble_client_throughput.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -110,9 +110,9 @@ const esp_ble_conn_params_t phy_1m_conn_params = { .latency = 0, .max_ce_len = 0, .min_ce_len = 0, - .scan_interval = 0x40, - .scan_window = 0x40, - .supervision_timeout = 600, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(40), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(40), + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), }; const esp_ble_conn_params_t phy_2m_conn_params = { @@ -121,9 +121,9 @@ const esp_ble_conn_params_t phy_2m_conn_params = { .latency = 0, .max_ce_len = 0, .min_ce_len = 0, - .scan_interval = 0x40, - .scan_window = 0x40, - .supervision_timeout = 600, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(40), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(40), + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), }; const esp_ble_conn_params_t phy_coded_conn_params = { @@ -132,9 +132,9 @@ const esp_ble_conn_params_t phy_coded_conn_params = { .latency = 0, .max_ce_len = 0, .min_ce_len = 0, - .scan_interval = 0x40, - .scan_window = 0x40, - .supervision_timeout = 600, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(40), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(40), + .supervision_timeout = ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(6000), }; struct gattc_profile_inst { diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/main/example_ble_server_throughput.c b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/main/example_ble_server_throughput.c index d7d00133ed..b0174955ca 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/main/example_ble_server_throughput.c +++ b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/main/example_ble_server_throughput.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -98,12 +98,12 @@ static esp_attr_value_t gatts_demo_char1_val = }; static uint8_t ext_adv_raw_data[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x03, 0x03, 0xab, 0xcd, - 0x11, 0x07, 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, - 0x11, 0x07, 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, - 0x14, 0X09, 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'P', 'U', 'T', '_', 'P', 'H', 'Y', '_', 'D', 'E', 'M', 'O', + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, + 0x02, ESP_BLE_AD_TYPE_TX_PWR, 0xeb, + 0x03, ESP_BLE_AD_TYPE_16SRV_CMPL, 0xab, 0xcd, + 0x11, ESP_BLE_AD_TYPE_128SRV_CMPL, 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x11, ESP_BLE_AD_TYPE_128SRV_CMPL, 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x14, ESP_BLE_AD_TYPE_NAME_CMPL, 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'P', 'U', 'T', '_', 'P', 'H', 'Y', '_', 'D', 'E', 'M', 'O', }; static esp_ble_gap_ext_adv_t ext_adv[1] = { @@ -112,8 +112,8 @@ static esp_ble_gap_ext_adv_t ext_adv[1] = { esp_ble_gap_ext_adv_params_t ext_adv_params = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE, - .interval_min = 0x20, - .interval_max = 0x20, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(20), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, diff --git a/examples/bluetooth/bluedroid/ble_50/multi-adv/main/multi_adv_demo.c b/examples/bluetooth/bluedroid/ble_50/multi-adv/main/multi_adv_demo.c index db750ce70b..0addc23bec 100644 --- a/examples/bluetooth/bluedroid/ble_50/multi-adv/main/multi_adv_demo.c +++ b/examples/bluetooth/bluedroid/ble_50/multi-adv/main/multi_adv_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -49,8 +49,8 @@ static SemaphoreHandle_t test_sem = NULL; esp_ble_gap_ext_adv_params_t ext_adv_params_1M = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE, - .interval_min = 0x30, - .interval_max = 0x30, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(30), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(30), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, @@ -64,8 +64,8 @@ esp_ble_gap_ext_adv_params_t ext_adv_params_1M = { esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE, - .interval_min = 0x40, - .interval_max = 0x40, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(40), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, @@ -79,8 +79,8 @@ esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { esp_ble_gap_ext_adv_params_t legacy_adv_params = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND, - .interval_min = 0x45, - .interval_max = 0x45, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(43), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(43), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, @@ -94,8 +94,8 @@ esp_ble_gap_ext_adv_params_t legacy_adv_params = { esp_ble_gap_ext_adv_params_t ext_adv_params_coded = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE, - .interval_min = 0x50, - .interval_max = 0x50, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(50), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(50), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, @@ -108,37 +108,37 @@ esp_ble_gap_ext_adv_params_t ext_adv_params_coded = { }; static uint8_t raw_adv_data_1m[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x11, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, + 0x02, ESP_BLE_AD_TYPE_TX_PWR, 0xeb, + 0x11, ESP_BLE_AD_TYPE_NAME_CMPL, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', 'D', 'V', '_', '1', 'M' }; static uint8_t raw_scan_rsp_data_2m[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x11, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, + 0x02, ESP_BLE_AD_TYPE_TX_PWR, 0xeb, + 0x11, ESP_BLE_AD_TYPE_NAME_CMPL, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', 'D', 'V', '_', '2', 'M' }; static uint8_t legacy_adv_data[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x14, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, + 0x02, ESP_BLE_AD_TYPE_TX_PWR, 0xeb, + 0x14, ESP_BLE_AD_TYPE_NAME_CMPL, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', 'D', 'V', '_', 'C', 'O', 'D', 'E', 'D' }; static uint8_t legacy_scan_rsp_data[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x15, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, + 0x02, ESP_BLE_AD_TYPE_TX_PWR, 0xeb, + 0x15, ESP_BLE_AD_TYPE_NAME_CMPL, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', 'D', 'V', '_', 'L', 'E', 'G', 'A', 'C', 'Y' }; static uint8_t raw_scan_rsp_data_coded[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x14, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 0x02, ESP_BLE_AD_TYPE_FLAG, 0x06, + 0x02, ESP_BLE_AD_TYPE_TX_PWR, 0xeb, + 0x14, ESP_BLE_AD_TYPE_NAME_CMPL, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', 'D', 'V', '_', 'C', 'O', 'D', 'E', 'D' }; diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_adv/main/periodic_adv_demo.c b/examples/bluetooth/bluedroid/ble_50/periodic_adv/main/periodic_adv_demo.c index aa7ffdac2a..517c301e45 100644 --- a/examples/bluetooth/bluedroid/ble_50/periodic_adv/main/periodic_adv_demo.c +++ b/examples/bluetooth/bluedroid/ble_50/periodic_adv/main/periodic_adv_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -58,8 +58,8 @@ static SemaphoreHandle_t test_sem = NULL; esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED, - .interval_min = 0x30, - .interval_max = 0x30, + .interval_min = ESP_BLE_GAP_ADV_ITVL_MS(30), + .interval_max = ESP_BLE_GAP_ADV_ITVL_MS(30), .channel_map = ADV_CHNL_ALL, .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, .primary_phy = ESP_BLE_GAP_PHY_1M, @@ -72,8 +72,8 @@ esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { }; static esp_ble_gap_periodic_adv_params_t periodic_adv_params = { - .interval_min = 0x40, // 80 ms interval - .interval_max = 0x40, + .interval_min = ESP_BLE_GAP_PERIODIC_ADV_ITVL_MS(80), + .interval_max = ESP_BLE_GAP_PERIODIC_ADV_ITVL_MS(80), .properties = 0, // Do not include TX power }; diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/CMakeLists.txt deleted file mode 100644 index e68a065139..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register(SRCS "bt_app_av.c" - "bt_app_core.c" - "main.c" - PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf esp_driver_dac - INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/Kconfig.projbuild deleted file mode 100644 index e627e8b5d1..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/Kconfig.projbuild +++ /dev/null @@ -1,71 +0,0 @@ -menu "A2DP Example Configuration" - config EXAMPLE_A2DP_SINK_SSP_ENABLED - bool "Secure Simple Pairing" - depends on BT_CLASSIC_ENABLED - default y - help - This enables the Secure Simple Pairing. If disable this option, - Bluedroid will only support Legacy Pairing - - choice EXAMPLE_A2DP_SINK_OUTPUT - prompt "A2DP Sink Output" - default EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S - help - Select to use Internal DAC or external I2S driver - - config EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - bool "Internal DAC" - help - Select this to use Internal DAC sink output, - note that DAC_DMA_AUTO_16BIT_ALIGN should be turned off - because the audio data are already 16-bit width - - config EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S - bool "External I2S Codec" - help - Select this to use External I2S sink output - - endchoice - - config EXAMPLE_I2S_LRCK_PIN - int "I2S LRCK (WS) GPIO" - default 22 - depends on EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S - help - GPIO number to use for I2S LRCK(WS) Driver. - - config EXAMPLE_I2S_BCK_PIN - int "I2S BCK GPIO" - default 26 - depends on EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S - help - GPIO number to use for I2S BCK Driver. - - config EXAMPLE_I2S_DATA_PIN - int "I2S DATA GPIO" - default 25 - depends on EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S - help - GPIO number to use for I2S Data Driver. - - config EXAMPLE_LOCAL_DEVICE_NAME - string "Local Device Name" - default "ESP_SPEAKER" - help - Use this option to set local device name. - - config EXAMPLE_AVRCP_CT_COVER_ART_ENABLE - bool "Use AVRCP CT Cover Art Feature" - depends on BT_CLASSIC_ENABLED - default y - help - This enables the AVRCP Cover Art feature in example and try to get cover art image from peer device. - - config EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC - bool "Use External Codec Instead of Internal" - default n - select BT_A2DP_USE_EXTERNAL_CODEC - help - If enable, Bluedroid stack will not decode A2DP audio data, user need to decode it in application layer. - -endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c deleted file mode 100644 index a6601f624c..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#include -#include -#include -#include -#include -#include "esp_log.h" - -#include "bt_app_core.h" -#include "bt_app_av.h" -#include "esp_bt_main.h" -#include "esp_bt_device.h" -#include "esp_gap_bt_api.h" -#include "esp_a2dp_api.h" -#include "esp_avrc_api.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -#include "driver/dac_continuous.h" -#else -#include "driver/i2s_std.h" -#endif - -#include "sys/lock.h" - -/* AVRCP used transaction labels */ -#define APP_RC_CT_TL_GET_CAPS (0) -#define APP_RC_CT_TL_GET_META_DATA (1) -#define APP_RC_CT_TL_RN_TRACK_CHANGE (2) -#define APP_RC_CT_TL_RN_PLAYBACK_CHANGE (3) -#define APP_RC_CT_TL_RN_PLAY_POS_CHANGE (4) - -/* Application layer causes delay value */ -#define APP_DELAY_VALUE 50 // 5ms - -/******************************* - * STATIC FUNCTION DECLARATIONS - ******************************/ - -/* allocate new meta buffer */ -static void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t *param); -/* handler for new track is loaded */ -static void bt_av_new_track(void); -/* handler for track status change */ -static void bt_av_playback_changed(void); -/* handler for track playing position change */ -static void bt_av_play_pos_changed(void); -/* notification event handler */ -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter); -/* installation for i2s */ -static void bt_i2s_driver_install(void); -/* uninstallation for i2s */ -static void bt_i2s_driver_uninstall(void); -/* set volume by remote controller */ -static void volume_set_by_controller(uint8_t volume); -/* set volume by local host */ -static void volume_set_by_local_host(uint8_t volume); -/* simulation volume change */ -static void volume_change_simulation(void *arg); -/* a2dp event handler */ -static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param); -/* avrc controller event handler */ -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param); -/* avrc target event handler */ -static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param); - -/******************************* - * STATIC VARIABLE DEFINITIONS - ******************************/ - -static uint32_t s_pkt_cnt = 0; /* count for audio packet */ -static esp_a2d_audio_state_t s_audio_state = ESP_A2D_AUDIO_STATE_STOPPED; - /* audio stream datapath state */ -static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; - /* connection state in string */ -static const char *s_a2d_audio_state_str[] = {"Suspended", "Started"}; - /* audio stream datapath state in string */ -static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap; - /* AVRC target notification capability bit mask */ -static _lock_t s_volume_lock; -static TaskHandle_t s_vcs_task_hdl = NULL; /* handle for volume change simulation task */ -static uint8_t s_volume = 0; /* local volume value */ -static bool s_volume_notify; /* notify volume change or not */ -#ifndef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -i2s_chan_handle_t tx_chan = NULL; -#else -dac_continuous_handle_t tx_chan; -#endif - -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE -static bool cover_art_connected = false; -static bool cover_art_getting = false; -static uint32_t cover_art_image_size = 0; -static uint8_t image_handle_old[7]; -#endif - -/******************************** - * STATIC FUNCTION DEFINITIONS - *******************************/ - -static void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t *param) -{ - esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); - uint8_t *attr_text = (uint8_t *) malloc (rc->meta_rsp.attr_length + 1); - - memcpy(attr_text, rc->meta_rsp.attr_text, rc->meta_rsp.attr_length); - attr_text[rc->meta_rsp.attr_length] = 0; - rc->meta_rsp.attr_text = attr_text; -} - -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE -static bool image_handle_check(uint8_t *image_handle, int len) -{ - /* Image handle length must be 7 */ - if (len == 7 && memcmp(image_handle_old, image_handle, 7) != 0) { - memcpy(image_handle_old, image_handle, 7); - return true; - } - return false; -} -#endif - -static void bt_av_new_track(void) -{ - /* request metadata */ - uint8_t attr_mask = ESP_AVRC_MD_ATTR_TITLE | - ESP_AVRC_MD_ATTR_ARTIST | - ESP_AVRC_MD_ATTR_ALBUM | - ESP_AVRC_MD_ATTR_GENRE; -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE - if (cover_art_connected) { - attr_mask |= ESP_AVRC_MD_ATTR_COVER_ART; - } -#endif - esp_avrc_ct_send_metadata_cmd(APP_RC_CT_TL_GET_META_DATA, attr_mask); - - /* register notification if peer support the event_id */ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_TRACK_CHANGE)) { - esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_TRACK_CHANGE, - ESP_AVRC_RN_TRACK_CHANGE, 0); - } -} - -static void bt_av_playback_changed(void) -{ - /* register notification if peer support the event_id */ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_PLAY_STATUS_CHANGE)) { - esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_PLAYBACK_CHANGE, - ESP_AVRC_RN_PLAY_STATUS_CHANGE, 0); - } -} - -static void bt_av_play_pos_changed(void) -{ - /* register notification if peer support the event_id */ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_PLAY_POS_CHANGED)) { - esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_PLAY_POS_CHANGE, - ESP_AVRC_RN_PLAY_POS_CHANGED, 10); - } -} - -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter) -{ - switch (event_id) { - /* when new track is loaded, this event comes */ - case ESP_AVRC_RN_TRACK_CHANGE: - bt_av_new_track(); - break; - /* when track status changed, this event comes */ - case ESP_AVRC_RN_PLAY_STATUS_CHANGE: - ESP_LOGI(BT_AV_TAG, "Playback status changed: 0x%x", event_parameter->playback); - bt_av_playback_changed(); - break; - /* when track playing position changed, this event comes */ - case ESP_AVRC_RN_PLAY_POS_CHANGED: - ESP_LOGI(BT_AV_TAG, "Play position changed: %"PRIu32"-ms", event_parameter->play_pos); - bt_av_play_pos_changed(); - break; - /* others */ - default: - ESP_LOGI(BT_AV_TAG, "unhandled event: %d", event_id); - break; - } -} - -void bt_i2s_driver_install(void) -{ -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - dac_continuous_config_t cont_cfg = { - .chan_mask = DAC_CHANNEL_MASK_ALL, - .desc_num = 8, - .buf_size = 2048, - .freq_hz = 44100, - .offset = 127, - .clk_src = DAC_DIGI_CLK_SRC_DEFAULT, // Using APLL as clock source to get a wider frequency range - .chan_mode = DAC_CHANNEL_MODE_ALTER, - }; - /* Allocate continuous channels */ - ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &tx_chan)); - /* Enable the continuous channels */ - ESP_ERROR_CHECK(dac_continuous_enable(tx_chan)); -#else - i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); - chan_cfg.auto_clear = true; - i2s_std_config_t std_cfg = { - .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = CONFIG_EXAMPLE_I2S_BCK_PIN, - .ws = CONFIG_EXAMPLE_I2S_LRCK_PIN, - .dout = CONFIG_EXAMPLE_I2S_DATA_PIN, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - }, - }, - }; - /* enable I2S */ - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, NULL)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_enable(tx_chan)); -#endif -} - -void bt_i2s_driver_uninstall(void) -{ -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - ESP_ERROR_CHECK(dac_continuous_disable(tx_chan)); - ESP_ERROR_CHECK(dac_continuous_del_channels(tx_chan)); -#else - ESP_ERROR_CHECK(i2s_channel_disable(tx_chan)); - ESP_ERROR_CHECK(i2s_del_channel(tx_chan)); -#endif -} - -static void volume_set_by_controller(uint8_t volume) -{ - ESP_LOGI(BT_RC_TG_TAG, "Volume is set by remote controller to: %"PRIu32"%%", (uint32_t)volume * 100 / 0x7f); - /* set the volume in protection of lock */ - _lock_acquire(&s_volume_lock); - s_volume = volume; - _lock_release(&s_volume_lock); -} - -static void volume_set_by_local_host(uint8_t volume) -{ - ESP_LOGI(BT_RC_TG_TAG, "Volume is set locally to: %"PRIu32"%%", (uint32_t)volume * 100 / 0x7f); - /* set the volume in protection of lock */ - _lock_acquire(&s_volume_lock); - s_volume = volume; - _lock_release(&s_volume_lock); - - /* send notification response to remote AVRCP controller */ - if (s_volume_notify) { - esp_avrc_rn_param_t rn_param; - rn_param.volume = s_volume; - esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_CHANGED, &rn_param); - s_volume_notify = false; - } -} - -static void volume_change_simulation(void *arg) -{ - ESP_LOGI(BT_RC_TG_TAG, "start volume change simulation"); - - for (;;) { - /* volume up locally every 10 seconds */ - vTaskDelay(10000 / portTICK_PERIOD_MS); - uint8_t volume = (s_volume + 5) & 0x7f; - volume_set_by_local_host(volume); - } -} - -static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) -{ - ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); - - esp_a2d_cb_param_t *a2d = NULL; - - switch (event) { - /* when connection state changed, this event comes */ - case ESP_A2D_CONNECTION_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - uint8_t *bda = a2d->conn_stat.remote_bda; - ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", - s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { - esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); - bt_i2s_driver_uninstall(); - bt_i2s_task_shut_down(); - } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){ - esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); - bt_i2s_task_start_up(); - } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTING) { - bt_i2s_driver_install(); - } - break; - } - /* when audio stream transmission state changed, this event comes */ - case ESP_A2D_AUDIO_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]); - s_audio_state = a2d->audio_stat.state; - if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { - s_pkt_cnt = 0; - } - break; - } - /* when audio codec is configured, this event comes */ - case ESP_A2D_AUDIO_CFG_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - esp_a2d_mcc_t *p_mcc = &a2d->audio_cfg.mcc; - ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, codec type: %d", p_mcc->type); - /* for now only SBC stream is supported */ - if (p_mcc->type == ESP_A2D_MCT_SBC) { - int sample_rate = 16000; - int ch_count = 2; - if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_32K) { - sample_rate = 32000; - } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_44K) { - sample_rate = 44100; - } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_48K) { - sample_rate = 48000; - } - - if (p_mcc->cie.sbc_info.ch_mode & ESP_A2D_SBC_CIE_CH_MODE_MONO) { - ch_count = 1; - } - #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - dac_continuous_disable(tx_chan); - dac_continuous_del_channels(tx_chan); - dac_continuous_config_t cont_cfg = { - .chan_mask = DAC_CHANNEL_MASK_ALL, - .desc_num = 8, - .buf_size = 2048, - .freq_hz = sample_rate, - .offset = 127, - .clk_src = DAC_DIGI_CLK_SRC_DEFAULT, // Using APLL as clock source to get a wider frequency range - .chan_mode = (ch_count == 1) ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER, - }; - /* Allocate continuous channels */ - dac_continuous_new_channels(&cont_cfg, &tx_chan); - /* Enable the continuous channels */ - dac_continuous_enable(tx_chan); - #else - i2s_channel_disable(tx_chan); - i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(sample_rate); - i2s_std_slot_config_t slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, ch_count); - i2s_channel_reconfig_std_clock(tx_chan, &clk_cfg); - i2s_channel_reconfig_std_slot(tx_chan, &slot_cfg); - i2s_channel_enable(tx_chan); - #endif - ESP_LOGI(BT_AV_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", - p_mcc->cie.sbc_info.samp_freq, - p_mcc->cie.sbc_info.ch_mode, - p_mcc->cie.sbc_info.block_len, - p_mcc->cie.sbc_info.num_subbands, - p_mcc->cie.sbc_info.alloc_mthd, - p_mcc->cie.sbc_info.min_bitpool, - p_mcc->cie.sbc_info.max_bitpool); - ESP_LOGI(BT_AV_TAG, "Audio player configured, sample rate: %d", sample_rate); - } - break; - } - /* when a2dp init or deinit completed, this event comes */ - case ESP_A2D_PROF_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { - ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); - } else { - ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); - } - break; - } - /* when using external codec, after sep registration done, this event comes */ - case ESP_A2D_SEP_REG_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - if (a2d->a2d_sep_reg_stat.reg_state == ESP_A2D_SEP_REG_SUCCESS) { - ESP_LOGI(BT_AV_TAG, "A2DP register SEP success, seid: %d", a2d->a2d_sep_reg_stat.seid); - } - else { - ESP_LOGI(BT_AV_TAG, "A2DP register SEP fail, seid: %d, state: %d", a2d->a2d_sep_reg_stat.seid, a2d->a2d_sep_reg_stat.reg_state); - } - break; - } - /* When protocol service capabilities configured, this event comes */ - case ESP_A2D_SNK_PSC_CFG_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - ESP_LOGI(BT_AV_TAG, "protocol service capabilities configured: 0x%x ", a2d->a2d_psc_cfg_stat.psc_mask); - if (a2d->a2d_psc_cfg_stat.psc_mask & ESP_A2D_PSC_DELAY_RPT) { - ESP_LOGI(BT_AV_TAG, "Peer device support delay reporting"); - } else { - ESP_LOGI(BT_AV_TAG, "Peer device unsupported delay reporting"); - } - break; - } - /* when set delay value completed, this event comes */ - case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - if (ESP_A2D_SET_INVALID_PARAMS == a2d->a2d_set_delay_value_stat.set_state) { - ESP_LOGI(BT_AV_TAG, "Set delay report value: fail"); - } else { - ESP_LOGI(BT_AV_TAG, "Set delay report value: success, delay_value: %u * 1/10 ms", a2d->a2d_set_delay_value_stat.delay_value); - } - break; - } - /* when get delay value completed, this event comes */ - case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - ESP_LOGI(BT_AV_TAG, "Get delay report value: delay_value: %u * 1/10 ms", a2d->a2d_get_delay_value_stat.delay_value); - /* Default delay value plus delay caused by application layer */ - esp_a2d_sink_set_delay_value(a2d->a2d_get_delay_value_stat.delay_value + APP_DELAY_VALUE); - break; - } - /* others */ - default: - ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); - break; - } -} - -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) -{ - ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event); - - esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param); - - switch (event) { - /* when connection state changed, this event comes */ - case ESP_AVRC_CT_CONNECTION_STATE_EVT: { - uint8_t *bda = rc->conn_stat.remote_bda; - ESP_LOGI(BT_RC_CT_TAG, "AVRC conn_state event: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", - rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - - if (rc->conn_stat.connected) { - /* get remote supported event_ids of peer AVRCP Target */ - esp_avrc_ct_send_get_rn_capabilities_cmd(APP_RC_CT_TL_GET_CAPS); - } else { - /* clear peer notification capability record */ - s_avrc_peer_rn_cap.bits = 0; - } - break; - } - /* when passthrough response, this event comes */ - case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC passthrough rsp: key_code 0x%x, key_state %d, rsp_code %d", rc->psth_rsp.key_code, - rc->psth_rsp.key_state, rc->psth_rsp.rsp_code); - break; - } - /* when metadata response, this event comes */ - case ESP_AVRC_CT_METADATA_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE - if(rc->meta_rsp.attr_id == 0x80 && cover_art_connected && cover_art_getting == false) { - /* check image handle is valid and different with last one, wo dont want to get an image repeatedly */ - if(image_handle_check(rc->meta_rsp.attr_text, rc->meta_rsp.attr_length)) { - esp_avrc_ct_cover_art_get_linked_thumbnail(rc->meta_rsp.attr_text); - cover_art_getting = true; - } - } -#endif - free(rc->meta_rsp.attr_text); - break; - } - /* when notified, this event comes */ - case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id); - bt_av_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter); - break; - } - /* when feature of remote device indicated, this event comes */ - case ESP_AVRC_CT_REMOTE_FEATURES_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC remote features %"PRIx32", TG features %x", rc->rmt_feats.feat_mask, rc->rmt_feats.tg_feat_flag); -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE - if ((rc->rmt_feats.tg_feat_flag & ESP_AVRC_FEAT_FLAG_TG_COVER_ART) && !cover_art_connected) { - ESP_LOGW(BT_RC_CT_TAG, "Peer support Cover Art feature, start connection..."); - /* set mtu to zero to use a default value */ - esp_avrc_ct_cover_art_connect(0); - } -#endif - break; - } - /* when notification capability of peer device got, this event comes */ - case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, - rc->get_rn_caps_rsp.evt_set.bits); - s_avrc_peer_rn_cap.bits = rc->get_rn_caps_rsp.evt_set.bits; - bt_av_new_track(); - bt_av_playback_changed(); - bt_av_play_pos_changed(); - break; - } - case ESP_AVRC_CT_COVER_ART_STATE_EVT: { -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE - if (rc->cover_art_state.state == ESP_AVRC_COVER_ART_CONNECTED) { - cover_art_connected = true; - ESP_LOGW(BT_RC_CT_TAG, "Cover Art Client connected"); - } - else { - cover_art_connected = false; - ESP_LOGW(BT_RC_CT_TAG, "Cover Art Client disconnected, reason:%d", rc->cover_art_state.reason); - } -#endif - break; - } - case ESP_AVRC_CT_COVER_ART_DATA_EVT: { -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE - /* when rc->cover_art_data.final is true, it means we have received the entire image or get operation failed */ - if (rc->cover_art_data.final) { - if(rc->cover_art_data.status == ESP_BT_STATUS_SUCCESS) { - ESP_LOGI(BT_RC_CT_TAG, "Cover Art Client final data event, image size: %lu bytes", cover_art_image_size); - } - else { - ESP_LOGE(BT_RC_CT_TAG, "Cover Art Client get operation failed"); - } - cover_art_image_size = 0; - /* set the getting state to false, we can get next image now */ - cover_art_getting = false; - } -#endif - break; - } - /* when avrcp controller init or deinit completed, this event comes */ - case ESP_AVRC_CT_PROF_STATE_EVT: { - if (ESP_AVRC_INIT_SUCCESS == rc->avrc_ct_init_stat.state) { - ESP_LOGI(BT_RC_CT_TAG, "AVRCP CT STATE: Init Complete"); - } else if (ESP_AVRC_DEINIT_SUCCESS == rc->avrc_ct_init_stat.state) { - ESP_LOGI(BT_RC_CT_TAG, "AVRCP CT STATE: Deinit Complete"); - } else { - ESP_LOGE(BT_RC_CT_TAG, "AVRCP CT STATE error: %d", rc->avrc_ct_init_stat.state); - } - break; - } - /* others */ - default: - ESP_LOGE(BT_RC_CT_TAG, "%s unhandled event: %d", __func__, event); - break; - } -} - -static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param) -{ - ESP_LOGD(BT_RC_TG_TAG, "%s event: %d", __func__, event); - - esp_avrc_tg_cb_param_t *rc = (esp_avrc_tg_cb_param_t *)(p_param); - - switch (event) { - /* when connection state changed, this event comes */ - case ESP_AVRC_TG_CONNECTION_STATE_EVT: { - uint8_t *bda = rc->conn_stat.remote_bda; - ESP_LOGI(BT_RC_TG_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", - rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - if (rc->conn_stat.connected) { - /* create task to simulate volume change */ - xTaskCreate(volume_change_simulation, "vcsTask", 2048, NULL, 5, &s_vcs_task_hdl); - } else { - vTaskDelete(s_vcs_task_hdl); - ESP_LOGI(BT_RC_TG_TAG, "Stop volume change simulation"); - } - break; - } - /* when passthrough commanded, this event comes */ - case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC passthrough cmd: key_code 0x%x, key_state %d", rc->psth_cmd.key_code, rc->psth_cmd.key_state); - break; - } - /* when absolute volume command from remote device set, this event comes */ - case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC set absolute volume: %d%%", (int)rc->set_abs_vol.volume * 100 / 0x7f); - volume_set_by_controller(rc->set_abs_vol.volume); - break; - } - /* when notification registered, this event comes */ - case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC register event notification: %d, param: 0x%"PRIx32, rc->reg_ntf.event_id, rc->reg_ntf.event_parameter); - if (rc->reg_ntf.event_id == ESP_AVRC_RN_VOLUME_CHANGE) { - s_volume_notify = true; - esp_avrc_rn_param_t rn_param; - rn_param.volume = s_volume; - esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_INTERIM, &rn_param); - } - break; - } - /* when feature of remote device indicated, this event comes */ - case ESP_AVRC_TG_REMOTE_FEATURES_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC remote features: %"PRIx32", CT features: %x", rc->rmt_feats.feat_mask, rc->rmt_feats.ct_feat_flag); - break; - } - /* when avrcp target init or deinit completed, this event comes */ - case ESP_AVRC_TG_PROF_STATE_EVT: { - if (ESP_AVRC_INIT_SUCCESS == rc->avrc_tg_init_stat.state) { - ESP_LOGI(BT_RC_CT_TAG, "AVRCP TG STATE: Init Complete"); - } else if (ESP_AVRC_DEINIT_SUCCESS == rc->avrc_tg_init_stat.state) { - ESP_LOGI(BT_RC_CT_TAG, "AVRCP TG STATE: Deinit Complete"); - } else { - ESP_LOGE(BT_RC_CT_TAG, "AVRCP TG STATE error: %d", rc->avrc_tg_init_stat.state); - } - break; - } - /* others */ - default: - ESP_LOGE(BT_RC_TG_TAG, "%s unhandled event: %d", __func__, event); - break; - } -} - -/******************************** - * EXTERNAL FUNCTION DEFINITIONS - *******************************/ - -void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) -{ - switch (event) { - case ESP_A2D_CONNECTION_STATE_EVT: - case ESP_A2D_AUDIO_STATE_EVT: - case ESP_A2D_AUDIO_CFG_EVT: - case ESP_A2D_PROF_STATE_EVT: - case ESP_A2D_SEP_REG_STATE_EVT: - case ESP_A2D_SNK_PSC_CFG_EVT: - case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: - case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - bt_app_work_dispatch(bt_av_hdl_a2d_evt, event, param, sizeof(esp_a2d_cb_param_t), NULL); - break; - } - default: - ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event); - break; - } -} - -#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE - -void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) -{ - write_ringbuf(data, len); - - /* log the number every 100 packets */ - if (++s_pkt_cnt % 100 == 0) { - ESP_LOGI(BT_AV_TAG, "Audio packet count: %"PRIu32, s_pkt_cnt); - } -} - -#else - -void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) -{ - ESP_LOGI(BT_AV_TAG, "data_len: %d, number_frame: %d, ts: %lu", audio_buf->data_len, audio_buf->number_frame, audio_buf->timestamp); - - /* - * Normally, user should send the audio_buf to other task, decode and free audio buff, - * But the codec component is not merge into IDF now, so we just free audio data here - */ - esp_a2d_audio_buff_free(audio_buf); -} - -#endif - -void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) -{ -#if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE - /* we must handle ESP_AVRC_CT_COVER_ART_DATA_EVT in this callback, copy image data to other buff before return if need */ - if (event == ESP_AVRC_CT_COVER_ART_DATA_EVT && param->cover_art_data.status == ESP_BT_STATUS_SUCCESS) { - cover_art_image_size += param->cover_art_data.data_len; - /* copy image data to other place */ - /* memcpy(p_buf, param->cover_art_data.p_data, param->cover_art_data.data_len); */ - } -#endif - switch (event) { - case ESP_AVRC_CT_METADATA_RSP_EVT: - bt_app_alloc_meta_buffer(param); - /* fall through */ - case ESP_AVRC_CT_CONNECTION_STATE_EVT: - case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: - case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: - case ESP_AVRC_CT_REMOTE_FEATURES_EVT: - case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: - case ESP_AVRC_CT_COVER_ART_STATE_EVT: - case ESP_AVRC_CT_COVER_ART_DATA_EVT: - case ESP_AVRC_CT_PROF_STATE_EVT: { - bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); - break; - } - default: - ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); - break; - } -} - -void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param) -{ - switch (event) { - case ESP_AVRC_TG_CONNECTION_STATE_EVT: - case ESP_AVRC_TG_REMOTE_FEATURES_EVT: - case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: - case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: - case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: - case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: - case ESP_AVRC_TG_PROF_STATE_EVT: - bt_app_work_dispatch(bt_av_hdl_avrc_tg_evt, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); - break; - default: - ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event); - break; - } -} diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_core.c deleted file mode 100644 index 29c915e893..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_core.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#include -#include -#include -#include "freertos/FreeRTOSConfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "bt_app_core.h" -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -#include "driver/dac_continuous.h" -#else -#include "driver/i2s_std.h" -#endif -#include "freertos/ringbuf.h" - - -#define RINGBUF_HIGHEST_WATER_LEVEL (32 * 1024) -#define RINGBUF_PREFETCH_WATER_LEVEL (20 * 1024) - -enum { - RINGBUFFER_MODE_PROCESSING, /* ringbuffer is buffering incoming audio data, I2S is working */ - RINGBUFFER_MODE_PREFETCHING, /* ringbuffer is buffering incoming audio data, I2S is waiting */ - RINGBUFFER_MODE_DROPPING /* ringbuffer is not buffering (dropping) incoming audio data, I2S is working */ -}; - -/******************************* - * STATIC FUNCTION DECLARATIONS - ******************************/ - -/* handler for application task */ -static void bt_app_task_handler(void *arg); -/* handler for I2S task */ -static void bt_i2s_task_handler(void *arg); -/* message sender */ -static bool bt_app_send_msg(bt_app_msg_t *msg); -/* handle dispatched messages */ -static void bt_app_work_dispatched(bt_app_msg_t *msg); - -/******************************* - * STATIC VARIABLE DEFINITIONS - ******************************/ - -static QueueHandle_t s_bt_app_task_queue = NULL; /* handle of work queue */ -static TaskHandle_t s_bt_app_task_handle = NULL; /* handle of application task */ -static TaskHandle_t s_bt_i2s_task_handle = NULL; /* handle of I2S task */ -static RingbufHandle_t s_ringbuf_i2s = NULL; /* handle of ringbuffer for I2S */ -static SemaphoreHandle_t s_i2s_write_semaphore = NULL; -static uint16_t ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; - -/********************************* - * EXTERNAL FUNCTION DECLARATIONS - ********************************/ -#ifndef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -extern i2s_chan_handle_t tx_chan; -#else -extern dac_continuous_handle_t tx_chan; -#endif - -/******************************* - * STATIC FUNCTION DEFINITIONS - ******************************/ - -static bool bt_app_send_msg(bt_app_msg_t *msg) -{ - if (msg == NULL) { - return false; - } - - /* send the message to work queue */ - if (xQueueSend(s_bt_app_task_queue, msg, 10 / portTICK_PERIOD_MS) != pdTRUE) { - ESP_LOGE(BT_APP_CORE_TAG, "%s xQueue send failed", __func__); - return false; - } - return true; -} - -static void bt_app_work_dispatched(bt_app_msg_t *msg) -{ - if (msg->cb) { - msg->cb(msg->event, msg->param); - } -} - -static void bt_app_task_handler(void *arg) -{ - bt_app_msg_t msg; - - for (;;) { - /* receive message from work queue and handle it */ - if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, (TickType_t)portMAX_DELAY)) { - ESP_LOGD(BT_APP_CORE_TAG, "%s, signal: 0x%x, event: 0x%x", __func__, msg.sig, msg.event); - - switch (msg.sig) { - case BT_APP_SIG_WORK_DISPATCH: - bt_app_work_dispatched(&msg); - break; - default: - ESP_LOGW(BT_APP_CORE_TAG, "%s, unhandled signal: %d", __func__, msg.sig); - break; - } /* switch (msg.sig) */ - - if (msg.param) { - free(msg.param); - } - } - } -} - -static void bt_i2s_task_handler(void *arg) -{ - uint8_t *data = NULL; - size_t item_size = 0; - /** - * The total length of DMA buffer of I2S is: - * `dma_frame_num * dma_desc_num * i2s_channel_num * i2s_data_bit_width / 8`. - * Transmit `dma_frame_num * dma_desc_num` bytes to DMA is trade-off. - */ - const size_t item_size_upto = 240 * 6; - size_t bytes_written = 0; - - for (;;) { - if (pdTRUE == xSemaphoreTake(s_i2s_write_semaphore, portMAX_DELAY)) { - for (;;) { - item_size = 0; - /* receive data from ringbuffer and write it to I2S DMA transmit buffer */ - data = (uint8_t *)xRingbufferReceiveUpTo(s_ringbuf_i2s, &item_size, (TickType_t)pdMS_TO_TICKS(20), item_size_upto); - if (item_size == 0) { - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer underflowed! mode changed: RINGBUFFER_MODE_PREFETCHING"); - ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; - break; - } - - #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - dac_continuous_write(tx_chan, data, item_size, &bytes_written, -1); - #else - i2s_channel_write(tx_chan, data, item_size, &bytes_written, portMAX_DELAY); - #endif - vRingbufferReturnItem(s_ringbuf_i2s, (void *)data); - } - } - } -} - -/******************************** - * EXTERNAL FUNCTION DEFINITIONS - *******************************/ - -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) -{ - ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len); - - bt_app_msg_t msg; - memset(&msg, 0, sizeof(bt_app_msg_t)); - - msg.sig = BT_APP_SIG_WORK_DISPATCH; - msg.event = event; - msg.cb = p_cback; - - if (param_len == 0) { - return bt_app_send_msg(&msg); - } else if (p_params && param_len > 0) { - if ((msg.param = malloc(param_len)) != NULL) { - memcpy(msg.param, p_params, param_len); - /* check if caller has provided a copy callback to do the deep copy */ - if (p_copy_cback) { - p_copy_cback(msg.param, p_params, param_len); - } - return bt_app_send_msg(&msg); - } - } - - return false; -} - -void bt_app_task_start_up(void) -{ - s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); - xTaskCreate(bt_app_task_handler, "BtAppTask", 3072, NULL, 10, &s_bt_app_task_handle); -} - -void bt_app_task_shut_down(void) -{ - if (s_bt_app_task_handle) { - vTaskDelete(s_bt_app_task_handle); - s_bt_app_task_handle = NULL; - } - if (s_bt_app_task_queue) { - vQueueDelete(s_bt_app_task_queue); - s_bt_app_task_queue = NULL; - } -} - -void bt_i2s_task_start_up(void) -{ - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data empty! mode changed: RINGBUFFER_MODE_PREFETCHING"); - ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; - if ((s_i2s_write_semaphore = xSemaphoreCreateBinary()) == NULL) { - ESP_LOGE(BT_APP_CORE_TAG, "%s, Semaphore create failed", __func__); - return; - } - if ((s_ringbuf_i2s = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) { - ESP_LOGE(BT_APP_CORE_TAG, "%s, ringbuffer create failed", __func__); - return; - } - xTaskCreate(bt_i2s_task_handler, "BtI2STask", 2048, NULL, configMAX_PRIORITIES - 3, &s_bt_i2s_task_handle); -} - -void bt_i2s_task_shut_down(void) -{ - if (s_bt_i2s_task_handle) { - vTaskDelete(s_bt_i2s_task_handle); - s_bt_i2s_task_handle = NULL; - } - if (s_ringbuf_i2s) { - vRingbufferDelete(s_ringbuf_i2s); - s_ringbuf_i2s = NULL; - } - if (s_i2s_write_semaphore) { - vSemaphoreDelete(s_i2s_write_semaphore); - s_i2s_write_semaphore = NULL; - } -} - -size_t write_ringbuf(const uint8_t *data, size_t size) -{ - size_t item_size = 0; - BaseType_t done = pdFALSE; - - if (ringbuffer_mode == RINGBUFFER_MODE_DROPPING) { - ESP_LOGW(BT_APP_CORE_TAG, "ringbuffer is full, drop this packet!"); - vRingbufferGetInfo(s_ringbuf_i2s, NULL, NULL, NULL, NULL, &item_size); - if (item_size <= RINGBUF_PREFETCH_WATER_LEVEL) { - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data decreased! mode changed: RINGBUFFER_MODE_PROCESSING"); - ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; - } - return 0; - } - - done = xRingbufferSend(s_ringbuf_i2s, (void *)data, size, (TickType_t)0); - - if (!done) { - ESP_LOGW(BT_APP_CORE_TAG, "ringbuffer overflowed, ready to decrease data! mode changed: RINGBUFFER_MODE_DROPPING"); - ringbuffer_mode = RINGBUFFER_MODE_DROPPING; - } - - if (ringbuffer_mode == RINGBUFFER_MODE_PREFETCHING) { - vRingbufferGetInfo(s_ringbuf_i2s, NULL, NULL, NULL, NULL, &item_size); - if (item_size >= RINGBUF_PREFETCH_WATER_LEVEL) { - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data increased! mode changed: RINGBUFFER_MODE_PROCESSING"); - ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; - if (pdFALSE == xSemaphoreGive(s_i2s_write_semaphore)) { - ESP_LOGE(BT_APP_CORE_TAG, "semphore give failed"); - } - } - } - - return done ? size : 0; -} diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/main.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/main.c deleted file mode 100644 index 8393b3e40f..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/main.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#include -#include -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "nvs.h" -#include "nvs_flash.h" -#include "esp_system.h" -#include "esp_log.h" - -#include "esp_bt.h" -#include "bt_app_core.h" -#include "bt_app_av.h" -#include "esp_bt_main.h" -#include "esp_bt_device.h" -#include "esp_gap_bt_api.h" -#include "esp_a2dp_api.h" -#include "esp_avrc_api.h" - -/* device name */ -static const char local_device_name[] = CONFIG_EXAMPLE_LOCAL_DEVICE_NAME; - -/* event for stack up */ -enum { - BT_APP_EVT_STACK_UP = 0, -}; - -/******************************** - * STATIC FUNCTION DECLARATIONS - *******************************/ - -/* Device callback function */ -static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param); -/* GAP callback function */ -static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); -/* handler for bluetooth stack enabled events */ -static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); - -/******************************* - * STATIC FUNCTION DEFINITIONS - ******************************/ -static char *bda2str(uint8_t * bda, char *str, size_t size) -{ - if (bda == NULL || str == NULL || size < 18) { - return NULL; - } - - uint8_t *p = bda; - sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", - p[0], p[1], p[2], p[3], p[4], p[5]); - return str; -} - -static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param) -{ - switch (event) { - case ESP_BT_DEV_NAME_RES_EVT: { - if (param->name_res.status == ESP_BT_STATUS_SUCCESS) { - ESP_LOGI(BT_AV_TAG, "Get local device name success: %s", param->name_res.name); - } else { - ESP_LOGE(BT_AV_TAG, "Get local device name failed, status: %d", param->name_res.status); - } - break; - } - default: { - ESP_LOGI(BT_AV_TAG, "event: %d", event); - break; - } - } -} - -static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) -{ - uint8_t *bda = NULL; - - switch (event) { - /* when authentication completed, this event comes */ - case ESP_BT_GAP_AUTH_CMPL_EVT: { - if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { - ESP_LOGI(BT_AV_TAG, "authentication success: %s", param->auth_cmpl.device_name); - ESP_LOG_BUFFER_HEX(BT_AV_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); - } else { - ESP_LOGE(BT_AV_TAG, "authentication failed, status: %d", param->auth_cmpl.stat); - } - ESP_LOGI(BT_AV_TAG, "link key type of current link is: %d", param->auth_cmpl.lk_type); - break; - } - case ESP_BT_GAP_ENC_CHG_EVT: { - char *str_enc[3] = {"OFF", "E0", "AES"}; - bda = (uint8_t *)param->enc_chg.bda; - ESP_LOGI(BT_AV_TAG, "Encryption mode to [%02x:%02x:%02x:%02x:%02x:%02x] changed to %s", - bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], str_enc[param->enc_chg.enc_mode]); - break; - } - -#if (CONFIG_EXAMPLE_A2DP_SINK_SSP_ENABLED == true) - /* when Security Simple Pairing user confirmation requested, this event comes */ - case ESP_BT_GAP_CFM_REQ_EVT: - ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %06"PRIu32, param->cfm_req.num_val); - esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); - break; - /* when Security Simple Pairing passkey notified, this event comes */ - case ESP_BT_GAP_KEY_NOTIF_EVT: - ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey: %06"PRIu32, param->key_notif.passkey); - break; - /* when Security Simple Pairing passkey requested, this event comes */ - case ESP_BT_GAP_KEY_REQ_EVT: - ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); - break; -#endif - - /* when GAP mode changed, this event comes */ - case ESP_BT_GAP_MODE_CHG_EVT: - ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_MODE_CHG_EVT mode: %d, interval: %.2f ms", - param->mode_chg.mode, param->mode_chg.interval * 0.625); - break; - /* when ACL connection completed, this event comes */ - case ESP_BT_GAP_ACL_CONN_CMPL_STAT_EVT: - bda = (uint8_t *)param->acl_conn_cmpl_stat.bda; - ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_ACL_CONN_CMPL_STAT_EVT Connected to [%02x:%02x:%02x:%02x:%02x:%02x], status: 0x%x", - bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], param->acl_conn_cmpl_stat.stat); - break; - /* when ACL disconnection completed, this event comes */ - case ESP_BT_GAP_ACL_DISCONN_CMPL_STAT_EVT: - bda = (uint8_t *)param->acl_disconn_cmpl_stat.bda; - ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_ACL_DISC_CMPL_STAT_EVT Disconnected from [%02x:%02x:%02x:%02x:%02x:%02x], reason: 0x%x", - bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], param->acl_disconn_cmpl_stat.reason); - break; - /* others */ - default: { - ESP_LOGI(BT_AV_TAG, "event: %d", event); - break; - } - } -} - -static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) -{ - ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); - - switch (event) { - /* when do the stack up, this event comes */ - case BT_APP_EVT_STACK_UP: { - esp_bt_gap_set_device_name(local_device_name); - esp_bt_dev_register_callback(bt_app_dev_cb); - esp_bt_gap_register_callback(bt_app_gap_cb); - - esp_avrc_ct_register_callback(bt_app_rc_ct_cb); - assert(esp_avrc_ct_init() == ESP_OK); - esp_avrc_tg_register_callback(bt_app_rc_tg_cb); - assert(esp_avrc_tg_init() == ESP_OK); - - esp_avrc_rn_evt_cap_mask_t evt_set = {0}; - esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE); - assert(esp_avrc_tg_set_rn_evt_cap(&evt_set) == ESP_OK); - - esp_a2d_register_callback(&bt_app_a2d_cb); - assert(esp_a2d_sink_init() == ESP_OK); - -#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE - esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); -#else - esp_a2d_mcc_t mcc = {0}; - mcc.type = ESP_A2D_MCT_SBC; - mcc.cie.sbc_info.samp_freq = 0xf; - mcc.cie.sbc_info.ch_mode = 0xf; - mcc.cie.sbc_info.block_len = 0xf; - mcc.cie.sbc_info.num_subbands = 0x3; - mcc.cie.sbc_info.alloc_mthd = 0x3; - mcc.cie.sbc_info.max_bitpool = 250; - mcc.cie.sbc_info.min_bitpool = 2; - /* register stream end point, only support mSBC currently */ - esp_a2d_sink_register_stream_endpoint(0, &mcc); - esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); -#endif - /* Get the default value of the delay value */ - esp_a2d_sink_get_delay_value(); - /* Get local device name */ - esp_bt_gap_get_device_name(); - - /* set discoverable and connectable mode, wait to be connected */ - esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); - break; - } - /* others */ - default: - ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); - break; - } -} - -/******************************* - * MAIN ENTRY POINT - ******************************/ - -void app_main(void) -{ - char bda_str[18] = {0}; - /* initialize NVS — it is used to store PHY calibration data */ - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK(err); - - /* - * This example only uses the functions of Classical Bluetooth. - * So release the controller memory for Bluetooth Low Energy. - */ - ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); - - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { - ESP_LOGE(BT_AV_TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(err)); - return; - } - if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { - ESP_LOGE(BT_AV_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(err)); - return; - } - - esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT(); -#if (CONFIG_EXAMPLE_A2DP_SINK_SSP_ENABLED == false) - bluedroid_cfg.ssp_en = false; -#endif - if ((err = esp_bluedroid_init_with_cfg(&bluedroid_cfg)) != ESP_OK) { - ESP_LOGE(BT_AV_TAG, "%s initialize bluedroid failed: %s", __func__, esp_err_to_name(err)); - return; - } - - if ((err = esp_bluedroid_enable()) != ESP_OK) { - ESP_LOGE(BT_AV_TAG, "%s enable bluedroid failed: %s", __func__, esp_err_to_name(err)); - return; - } - -#if (CONFIG_EXAMPLE_A2DP_SINK_SSP_ENABLED == true) - /* set default parameters for Secure Simple Pairing */ - esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; - esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; - esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); -#endif - - /* set default parameters for Legacy Pairing (use fixed pin code 1234) */ - esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_FIXED; - esp_bt_pin_code_t pin_code; - pin_code[0] = '1'; - pin_code[1] = '2'; - pin_code[2] = '3'; - pin_code[3] = '4'; - esp_bt_gap_set_pin(pin_type, 4, pin_code); - - ESP_LOGI(BT_AV_TAG, "Own address:[%s]", bda2str((uint8_t *)esp_bt_dev_get_address(), bda_str, sizeof(bda_str))); - bt_app_task_start_up(); - /* bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); -} diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/CMakeLists.txt similarity index 93% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/CMakeLists.txt rename to examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/CMakeLists.txt index 1d31e07835..4fd485ef82 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/CMakeLists.txt +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/CMakeLists.txt @@ -5,4 +5,4 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) # "Trim" the build. Include the minimal set of components, main, and anything it depends on. idf_build_set_property(MINIMAL_BUILD ON) -project(a2dp_sink) +project(a2dp_sink_stream) diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/README.md b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/README.md similarity index 73% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/README.md rename to examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/README.md index 072cacd12c..c21418d203 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/README.md @@ -1,16 +1,34 @@ | Supported Targets | ESP32 | | ----------------- | ----- | -A2DP-SINK EXAMPLE +A2DP-SINK-STREAM EXAMPLE ====================== Example of A2DP audio sink role This is the example of API implementing Advanced Audio Distribution Profile to receive an audio stream. -This example involves the use of Bluetooth legacy profile A2DP for audio stream reception, AVRCP for media information notifications, and I2S for audio stream output interface. +This example involves the use of Bluetooth legacy profile A2DP for audio stream reception and I2S for audio stream output interface. -Applications such as bluetooth speakers can take advantage of this example as a reference of basic functionalities. +## Required components + +- [bt_app_core_utils](../common/bt_app_core_utils) +- [bredr_app_common_utils](../common/bredr_app_common_utils) +- [a2dp_sink_common_utils](../common/a2dp_utils/a2dp_sink_common_utils) +- [a2dp_sink_int_codec_utils](../common/a2dp_utils/a2dp_sink_int_codec_utils) +- [a2dp_sink_ext_codec_utils](../common/a2dp_utils/a2dp_sink_ext_codec_utils) + +``` ++-------------------------+-------------------------+---------------------+ +|a2dp_sink_int_codec_utils|a2dp_sink_ext_codec_utils| | ++-------------------------+-------------------------+ | +| a2dp_sink_common_utils | bt_app_core_utils | ++---------------------------------------------------+ | +| bredr_app_common_utils | | ++---------------------------------------------------+---------------------+ +``` + +Detailed information can be viewed through the [../common/README.md](../common/README.md). ## How to use this example @@ -22,7 +40,7 @@ For the I2S codec, pick whatever chip or board works for you; this code was writ | ESP pin | I2S signal | | :-------- | :----------- | -| GPIO22 | LRCK | +| GPIO27 | LRCK | | GPIO25 | DATA | | GPIO26 | BCK | @@ -34,9 +52,7 @@ If the internal DAC is selected, analog audio will be available on GPIO25 and GP idf.py menuconfig ``` -* Choose external I2S codec or internal DAC for audio output, and configure the output PINs under A2DP Example Configuration - -* For AVRCP CT Cover Art feature, is enabled by default, we can disable it by unselecting menuconfig option `Component config --> Bluetooth --> Bluedroid Options --> Classic Bluetooth --> AVRCP Features --> AVRCP CT Cover Art`. This example will try to use AVRCP CT Cover Art feature, get cover art image and count the image size if peer device support, this can be disable in `A2DP Example Configuration --> Use AVRCP CT Cover Art Feature`. +* Choose external I2S codec or internal DAC for audio output, and configure the output PINs under A2DP Sink Internal Codec Example Configuration. ### Build and Flash @@ -68,13 +84,6 @@ I (126697) BT_AV: Audio packet count 300 I (128697) BT_AV: Audio packet count 400 ``` -The output when receiving a cover art image: - -``` -I (53349) RC_CT: AVRC metadata rsp: attribute id 0x80, 1000748 -I (53639) RC_CT: Cover Art Client final data event, image size: 14118 bytes -``` - Also, the sound will be heard if a loudspeaker is connected and possible external I2S codec is correctly configured. For ESP32 A2DP source example, the sound is noise as the audio source generates the samples with a random sequence. ## Troubleshooting diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/CMakeLists.txt new file mode 100644 index 0000000000..6b20ae1360 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/CMakeLists.txt @@ -0,0 +1,10 @@ +if(CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC) + set(EXTRA_COMPONENTS a2dp_sink_ext_codec_utils) +else() + set(EXTRA_COMPONENTS a2dp_sink_int_codec_utils) +endif() + +idf_component_register(SRCS "main.c" + PRIV_REQUIRES bt bt_app_core_utils bredr_app_common_utils a2dp_sink_common_utils + PRIV_REQUIRES ${EXTRA_COMPONENTS} + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/Kconfig.projbuild new file mode 100644 index 0000000000..605249c797 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/Kconfig.projbuild @@ -0,0 +1,15 @@ +menu "A2DP Example Configuration" + config EXAMPLE_LOCAL_DEVICE_NAME + string "Local Device Name" + default "ESP_SPEAKER" + help + Use this option to set local device name. + + config EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC + bool "Use External Codec Instead of Internal" + default n + select BT_A2DP_USE_EXTERNAL_CODEC + help + If enable, Bluedroid stack will not decode A2DP audio data, user need to decode it in application layer. + +endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/idf_component.yml b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/idf_component.yml new file mode 100644 index 0000000000..17c8a5daae --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/idf_component.yml @@ -0,0 +1,11 @@ +dependencies: + bt_app_core_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils + bredr_app_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils + a2dp_sink_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils + a2dp_sink_int_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils + a2dp_sink_ext_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/main.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/main.c new file mode 100644 index 0000000000..680d13ad13 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/main.c @@ -0,0 +1,177 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include + +#include "esp_log.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" + +#include "bt_app_core_utils.h" +#include "bredr_app_common_utils.h" +#include "a2dp_sink_common_utils.h" +#include "a2dp_utils_tags.h" +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +#include "a2dp_sink_int_codec_utils.h" +#else +#include "a2dp_sink_ext_codec_utils.h" +#endif + +/* device name */ +static const char local_device_name[] = CONFIG_EXAMPLE_LOCAL_DEVICE_NAME; + +/* event for stack up */ +enum { + BT_APP_EVT_STACK_UP = 0, +}; + +/******************************** + * STATIC FUNCTION DECLARATIONS + *******************************/ + +/* Device callback function */ +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param); + +/* GAP callback function */ +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); + +/* callback function for A2DP sink */ +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); + +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +/* callback function for A2DP sink audio data stream */ +static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len); +#else +/* callback function for A2DP sink undecoded audio data */ +static void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); +#endif + +/* handler for bluetooth stack enabled events */ +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param) +{ + bredr_app_dev_evt_def_hdl(event, param); +} + +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + bredr_app_gap_evt_def_hdl(event, param); +} + +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) +{ + switch (event) { + case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_SNK_PSC_CFG_EVT: + case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: + case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + break; + } + case ESP_A2D_CONNECTION_STATE_EVT: + case ESP_A2D_AUDIO_STATE_EVT: + case ESP_A2D_AUDIO_CFG_EVT: + case ESP_A2D_SEP_REG_STATE_EVT: { +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#else + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#endif + break; + } + default: + ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event); + break; + } +} + +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) +{ + bt_a2d_data_hdl(data, len); +} +#else +static void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ + bt_a2d_audio_data_hdl(conn_hdl, audio_buf); +} +#endif + +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); + + switch (event) { + /* when do the stack up, this event comes */ + case BT_APP_EVT_STACK_UP: { + esp_bt_gap_set_device_name(local_device_name); + esp_bt_dev_register_callback(bt_app_dev_cb); + esp_bt_gap_register_callback(bt_app_gap_cb); + + esp_a2d_register_callback(&bt_app_a2d_cb); + assert(esp_a2d_sink_init() == ESP_OK); + +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); +#else + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + /* register stream end point, only support SBC currently */ + esp_a2d_sink_register_stream_endpoint(0, &mcc); + esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); +#endif + + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + /* Get local device name */ + esp_bt_gap_get_device_name(); + + /* set discoverable and connectable mode, wait to be connected */ + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +/******************************* + * MAIN ENTRY POINT + ******************************/ + +void app_main(void) +{ + ESP_ERROR_CHECK(bredr_app_common_init()); + + bt_app_task_start_up(); + /* bluetooth device name, connection mode and profile set up */ + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.ci.ca_dis b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.ci.ca_dis similarity index 75% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.ci.ca_dis rename to examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.ci.ca_dis index 1c6372a1b3..9d5c2a060d 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.ci.ca_dis +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.ci.ca_dis @@ -1,12 +1,9 @@ # Override some defaults so BT stack is enabled and # Classic BT is enabled and BT_DRAM_RELEASE is disabled CONFIG_BT_ENABLED=y -CONFIG_BTDM_CTRL_MODE_BLE_ONLY=n CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y -CONFIG_BTDM_CTRL_MODE_BTDM=n CONFIG_BT_BLUEDROID_ENABLED=y CONFIG_BT_CLASSIC_ENABLED=y CONFIG_BT_A2DP_ENABLE=y CONFIG_BT_AVRCP_CT_COVER_ART_ENABLED=n -CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE=n CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=n diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.ci.test b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.ci.test similarity index 100% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.ci.test rename to examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.ci.test diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.defaults new file mode 100644 index 0000000000..2b93a51a0e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/sdkconfig.defaults @@ -0,0 +1,8 @@ +# Override some defaults so BT stack is enabled and +# Classic BT is enabled and BT_DRAM_RELEASE is disabled +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y +CONFIG_BT_BLUEDROID_ENABLED=y +CONFIG_BT_CLASSIC_ENABLED=y +CONFIG_BT_A2DP_ENABLE=y +CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=n diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/tutorial/Example_A2DP_Sink.md b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/tutorial/Example_A2DP_Sink.md similarity index 51% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/tutorial/Example_A2DP_Sink.md rename to examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/tutorial/Example_A2DP_Sink.md index 510077b9aa..72b06ad89e 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/tutorial/Example_A2DP_Sink.md +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/tutorial/Example_A2DP_Sink.md @@ -4,36 +4,19 @@ In this tutorial, the A2DP sink example code is reviewed. The code implements an A2DP sink role, which receives audio stream from A2DP source devices. -## File Tree - -The file tree of this example is shown below. The [main](../main) folder contains the main files of this example including audio and video related files, program core files, main function file, etc. The [tutorial](../tutorial) folder contains this guidance document. - -```c -└── a2dp_sink -    ├── CMakeLists.txt -    ├── main -    │   ├── bt_app_av.c -    │   ├── bt_app_av.h -    │   ├── bt_app_core.c -    │   ├── bt_app_core.h -    │   ├── CMakeLists.txt -    │   ├── Kconfig.projbuild -    │   └── main.c -    ├── README.md -    ├── sdkconfig.defaults -    └── tutorial -    └── Example_A2DP_Sink.md - -2 directories, 11 files -``` - ## Main Entry Point -This example is located in the examples folder of the ESP-IDF under the [bluetooth/bluedroid/classic_bt/a2dp_sink](../). The entry point of this program is `app_main()` which contained in [main/main.c](../main/main.c). +This example is located in the examples folder of the ESP-IDF under the [bluetooth/bluedroid/classic_bt/a2dp_sink_stream](../). The entry point of this program is `app_main()` which contained in [main/main.c](../main/main.c). -### NVS Initialization +The main function first initializes through `bredr_app_common_init()`, and then calls `bt_app_task_start_up()` and `bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL)` to create and execute the task. -The main function starts by initializing the non-volatile storage library. This library allows to save key-value pairs in flash memory and is used by some components such as the Wi-Fi library to save the SSID and password: +### Classic Bluetooth Initialization + +Initialize the Classic Bluetooth by calling `bredr_app_common_init()`. + +#### NVS Initialization + +The `bredr_app_common_init()` starts by initializing the non-volatile storage library. This library allows to save key-value pairs in flash memory and is used by some components such as the Wi-Fi library to save the SSID and password: ```c /* initialize NVS — it is used to store PHY calibration */ @@ -45,9 +28,9 @@ if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(ret); ``` -### Bluetooth Controller and Stack Initialization +#### Bluetooth Controller and Stack Initialization -The main function also initializes the Bluetooth Controller with default settings. The Bluetooth Controller is invisible to the user applications and deals with the lower layers of the Bluetooth Stack. Next, the controller is enabled in Classic Bluetooth Mode. +The `bredr_app_common_init()` also initializes the Bluetooth Controller with default settings. The Bluetooth Controller is invisible to the user applications and deals with the lower layers of the Bluetooth Stack. Next, the controller is enabled in Classic Bluetooth Mode. ```c /* initialize Bluetooth Controller with default configuration */ @@ -86,58 +69,9 @@ The Classic Bluetooth uses an asynchronous programming paradigm. The entire Blue For example, after executing `esp_bt_gap_start_discovery()`, an event of `ESP_BT_GAP_DISC_STATE_CHANGED_EVT` occurs to inform that the discovery state has been changed. Application can do some processing at this time. -### I2S Installation +#### Paring Parameter Settings -The main function installs I2S to play the audio. A loudspeaker, additional ADC or hardware requirements and possibly an external I2S codec may be needed. - -```c - #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - /* I2S configuration parameters */ - i2s_config_t i2s_config = { - .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, - .sample_rate = 44100, - .bits_per_sample = 16, - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, /* 2-channels */ - .communication_format = I2S_COMM_FORMAT_STAND_MSB, - .dma_buf_count = 6, - .dma_buf_len = 60, - .intr_alloc_flags = 0, /* default interrupt priority */ - .tx_desc_auto_clear = true /* auto clear tx descriptor on underflow */ - }; - - /* enable I2S */ - ESP_ERROR_CHECK(i2s_driver_install(0, &i2s_config, 0, NULL)); - ESP_ERROR_CHECK(i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN)); - ESP_ERROR_CHECK(i2s_set_pin(0, NULL)); - #else - i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); - chan_cfg.auto_clear = true; - i2s_std_config_t std_cfg = { - .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = CONFIG_EXAMPLE_I2S_BCK_PIN, - .ws = CONFIG_EXAMPLE_I2S_LRCK_PIN, - .dout = CONFIG_EXAMPLE_I2S_DATA_PIN, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - }, - }, - }; - /* enable I2S */ - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, NULL)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_enable(tx_chan)); - #endif -``` - -### Paring Parameter Settings - -The main function continues to set up paring parameters including Secure Simple Pairing and Legacy Pairing. +The `bredr_app_common_init()` continues to set up paring parameters including Secure Simple Pairing and Legacy Pairing. ```c #if (CONFIG_EXAMPLE_A2DP_SINK_SSP_ENABLED == true) diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/README.md b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/README.md index ed7db5d1bc..5d095f6c88 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/README.md @@ -12,7 +12,7 @@ This is the example of using Advanced Audio Distribution Profile (A2DP) APIs to ### Hardware Required -This example is able to run on any commonly available ESP32 development board, and is supposed to connect to [A2DP sink example](../a2dp_sink) in ESP-IDF. +This example is able to run on any commonly available ESP32 development board, and is supposed to connect to [A2DP sink example](../a2dp_sink_stream) in ESP-IDF. ### Configure the project diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/CMakeLists.txt new file mode 100644 index 0000000000..a693a301aa --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) +project(avrcp_absolute_volume) diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/README.md b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/README.md new file mode 100644 index 0000000000..c8080e5eff --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/README.md @@ -0,0 +1,70 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | + +AVRCP-ABSOLUTE-VOLUME EXAMPLE +====================== + +This is the example of API implementing Audio/Video Remote Control Profile to control absolute volume. + +## Required components + +- [bt_app_core_utils](../common/bt_app_core_utils) +- [bredr_app_common_utils](../common/bredr_app_common_utils) +- [a2dp_sink_common_utils](../common/a2dp_utils/a2dp_sink_common_utils) +- [a2dp_sink_int_codec_utils](../common/a2dp_utils/a2dp_sink_int_codec_utils) +- [a2dp_sink_ext_codec_utils](../common/a2dp_utils/a2dp_sink_ext_codec_utils) +- [avrcp_common_utils](../common/avrcp_utils/avrcp_common_utils) +- [avrcp_abs_vol_utils](../common/avrcp_utils/avrcp_abs_vol_utils) + +``` ++---------------------------------------------------+---------------------+ +| avrcp_abs_vol_utils | | ++---------------------------------------------------+ | +| avrcp_common_utils | | ++-------------------------+-------------------------+ | +|a2dp_sink_int_codec_utils|a2dp_sink_ext_codec_utils| bt_app_core_utils | ++-------------------------+-------------------------+ | +| a2dp_sink_common_utils | | ++---------------------------------------------------+ | +| bredr_app_common_utils | | ++---------------------------------------------------+---------------------+ +``` + +Detailed information can be viewed through the [../common/README.md](../common/README.md). + +## How to use this example + +### Configure the project + +``` +idf.py menuconfig +``` + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output. + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +## Example Output + +The output when the connection is established: + +``` +I (56320) RC_VC_SRV: Volume is set locally to: 3% +I (57160) RC_TG: AVRC register event notification: 13, param: 0x0 +I (66320) RC_VC_SRV: Volume is set locally to: 7% +I (67160) RC_TG: AVRC register event notification: 13, param: 0x0 +I (76320) RC_VC_SRV: Volume is set locally to: 11% +I (77160) RC_TG: AVRC register event notification: 13, param: 0x0 +I (86320) RC_VC_SRV: Volume is set locally to: 15% +I (87160) RC_TG: AVRC register event notification: 13, param: 0x0 +``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/CMakeLists.txt new file mode 100644 index 0000000000..d6ae771f4b --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/CMakeLists.txt @@ -0,0 +1,12 @@ +if(CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE) + if(CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC) + set(EXTRA_COMPONENTS a2dp_sink_ext_codec_utils) + else() + set(EXTRA_COMPONENTS a2dp_sink_int_codec_utils) + endif() +endif() + +idf_component_register(SRCS "main.c" + PRIV_REQUIRES bt bt_app_core_utils bredr_app_common_utils a2dp_sink_common_utils + PRIV_REQUIRES ${EXTRA_COMPONENTS} avrcp_common_utils avrcp_abs_vol_utils + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/Kconfig.projbuild new file mode 100644 index 0000000000..2a4dfc0176 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/Kconfig.projbuild @@ -0,0 +1,23 @@ +menu "AVRCP Example Configuration" + config EXAMPLE_LOCAL_DEVICE_NAME + string "Local Device Name" + default "ESP_SPEAKER" + help + Use this option to set local device name. + + config EXAMPLE_A2DP_SINK_STREAM_ENABLE + bool "Enable A2DP Sink Stream" + default y + help + This enables the A2DP sink stream. If disable this option, + audio data will not be transmitted + + config EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC + bool "Use External Codec Instead of Internal" + depends on EXAMPLE_A2DP_SINK_STREAM_ENABLE + default n + select BT_A2DP_USE_EXTERNAL_CODEC + help + If enable, Bluedroid stack will not decode A2DP audio data, user need to decode it in application layer. + +endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/idf_component.yml b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/idf_component.yml new file mode 100644 index 0000000000..5e5b34e4b4 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/idf_component.yml @@ -0,0 +1,15 @@ +dependencies: + bt_app_core_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils + bredr_app_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils + a2dp_sink_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils + a2dp_sink_int_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils + a2dp_sink_ext_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils + avrcp_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils + avrcp_abs_vol_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/main.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/main.c new file mode 100644 index 0000000000..a5c45d0e43 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/main.c @@ -0,0 +1,251 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include + +#include "esp_log.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" +#include "esp_avrc_api.h" + +#include "bt_app_core_utils.h" +#include "bredr_app_common_utils.h" +#include "a2dp_utils_tags.h" +#include "a2dp_sink_common_utils.h" +#include "avrcp_utils_tags.h" +#include "avrcp_common_utils.h" +#include "avrcp_abs_vol_utils.h" +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +#include "a2dp_sink_int_codec_utils.h" +#else +#include "a2dp_sink_ext_codec_utils.h" +#endif +#endif + +/* device name */ +static const char local_device_name[] = CONFIG_EXAMPLE_LOCAL_DEVICE_NAME; + +/* event for stack up */ +enum { + BT_APP_EVT_STACK_UP = 0, +}; + +/******************************** + * STATIC FUNCTION DECLARATIONS + *******************************/ + +/* Device callback function */ +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param); + +/* GAP callback function */ +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); + +/* callback function for A2DP sink */ +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +/* callback function for A2DP sink audio data stream */ +static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len); +#else +/* callback function for A2DP sink undecoded audio data */ +static void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); +#endif +#endif + +/* callback function for AVRCP controller */ +static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param); + +/* callback function for AVRCP target */ +static void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param); + +/* handler for bluetooth stack enabled events */ +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param) +{ + bredr_app_dev_evt_def_hdl(event, param); +} + +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + bredr_app_gap_evt_def_hdl(event, param); +} + +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) +{ + switch (event) { + case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_SNK_PSC_CFG_EVT: + case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: + case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + break; + } + case ESP_A2D_CONNECTION_STATE_EVT: + case ESP_A2D_AUDIO_STATE_EVT: + case ESP_A2D_AUDIO_CFG_EVT: + case ESP_A2D_SEP_REG_STATE_EVT: { +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#else + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#endif +#else + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#endif + break; + } + default: + ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event); + break; + } +} + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) +{ + bt_a2d_data_hdl(data, len); +} +#else +static void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ + bt_a2d_audio_data_hdl(conn_hdl, audio_buf); +} +#endif +#endif + +static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) +{ + switch (event) { + case ESP_AVRC_CT_METADATA_RSP_EVT: + case ESP_AVRC_CT_CONNECTION_STATE_EVT: + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: + case ESP_AVRC_CT_COVER_ART_STATE_EVT: + case ESP_AVRC_CT_COVER_ART_DATA_EVT: + case ESP_AVRC_CT_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_avrc_common_ct_evt_def_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + break; + } + default: + ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +static void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param) +{ + switch (event) { + case ESP_AVRC_TG_REMOTE_FEATURES_EVT: + case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: + case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: + case ESP_AVRC_TG_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + break; + } + case ESP_AVRC_TG_CONNECTION_STATE_EVT: + case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: + case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { + bt_app_work_dispatch(bt_avrc_avc_tg_evt_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + break; + } + default: + ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); + + switch (event) { + /* when do the stack up, this event comes */ + case BT_APP_EVT_STACK_UP: { + esp_bt_gap_set_device_name(local_device_name); + esp_bt_dev_register_callback(bt_app_dev_cb); + esp_bt_gap_register_callback(bt_app_gap_cb); + + esp_avrc_ct_register_callback(bt_app_rc_ct_cb); + assert(esp_avrc_ct_init() == ESP_OK); + esp_avrc_tg_register_callback(bt_app_rc_tg_cb); + assert(esp_avrc_tg_init() == ESP_OK); + + esp_avrc_rn_evt_cap_mask_t evt_set = {0}; + esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE); + assert(esp_avrc_tg_set_rn_evt_cap(&evt_set) == ESP_OK); + + esp_a2d_register_callback(&bt_app_a2d_cb); + assert(esp_a2d_sink_init() == ESP_OK); + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); +#else + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + /* register stream end point, only support SBC currently */ + esp_a2d_sink_register_stream_endpoint(0, &mcc); + esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); +#endif +#endif + + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + /* Get local device name */ + esp_bt_gap_get_device_name(); + + /* set discoverable and connectable mode, wait to be connected */ + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +/******************************* + * MAIN ENTRY POINT + ******************************/ + +void app_main(void) +{ + ESP_ERROR_CHECK(bredr_app_common_init()); + + bt_app_task_start_up(); + /* bluetooth device name, connection mode and profile set up */ + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/sdkconfig.ci.test b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/sdkconfig.ci.test new file mode 100644 index 0000000000..79e4f555d6 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/sdkconfig.ci.test @@ -0,0 +1 @@ +CONFIG_EXAMPLE_LOCAL_DEVICE_NAME="${CI_PIPELINE_ID}_A2DP_SINK" diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/sdkconfig.defaults new file mode 100644 index 0000000000..2b93a51a0e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/sdkconfig.defaults @@ -0,0 +1,8 @@ +# Override some defaults so BT stack is enabled and +# Classic BT is enabled and BT_DRAM_RELEASE is disabled +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y +CONFIG_BT_BLUEDROID_ENABLED=y +CONFIG_BT_CLASSIC_ENABLED=y +CONFIG_BT_A2DP_ENABLE=y +CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=n diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/CMakeLists.txt new file mode 100644 index 0000000000..d09bd51b21 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) +project(avrcp_ct_cover_art) diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/README.md b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/README.md new file mode 100644 index 0000000000..509db09502 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/README.md @@ -0,0 +1,121 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | + +AVRCP-CT-COVER-ART EXAMPLE +====================== + +This is an example demonstrating the API for implementing Audio/Video Remote Control Profile to get and display cover art image. + +## Required components + +- [bt_app_core_utils](../common/bt_app_core_utils) +- [bredr_app_common_utils](../common/bredr_app_common_utils) +- [a2dp_sink_common_utils](../common/a2dp_utils/a2dp_sink_common_utils) +- [a2dp_sink_int_codec_utils](../common/a2dp_utils/a2dp_sink_int_codec_utils) +- [a2dp_sink_ext_codec_utils](../common/a2dp_utils/a2dp_sink_ext_codec_utils) +- [avrcp_common_utils](../common/avrcp_utils/avrcp_common_utils) +- [avrcp_metadata_utils](../common/avrcp_utils/avrcp_metadata_utils) +- [avrcp_cover_art_utils](../common/avrcp_utils/avrcp_cover_art_utils) + +``` ++---------------------------------------------------+---------------------+ +| avrcp_cover_art_utils | | ++---------------------------------------------------+ | +| avrcp_metadata_utils | | ++---------------------------------------------------+ | +| avrcp_common_utils | | ++-------------------------+-------------------------+ bt_app_core_utils | +|a2dp_sink_int_codec_utils|a2dp_sink_ext_codec_utils| | ++-------------------------+-------------------------+ | +| a2dp_sink_common_utils | | ++---------------------------------------------------+ | +| bredr_app_common_utils | | ++---------------------------------------------------+---------------------+ +``` + +Detailed information can be viewed through the [../common/README.md](../common/README.md). + +## How to use this example + +### Hardware Required + +* An ESP32 development board +* A SPI-interfaced LCD +* A USB cable for power supply and programming + +### Hardware Connection + +The connection between ESP32 Board and the LCD is as follows: + +``` + ESP32 Board LCD Screen + +---------+ +---------------------------------+ + | | | | + | 3V3 +--------------+ VCC +----------------------+ | + | | | | | | + | GND +--------------+ GND | | | + | | | | | | + | DATA0 +--------------+ MOSI | | | + | | | | | | + | PCLK +--------------+ SCK | | | + | | | | | | + | CS +--------------+ CS | | | + | | | | | | + | D/C +--------------+ D/C | | | + | | | | | | + | RST +--------------+ RST | | | + | | | | | | + |BK_LIGHT +--------------+ BCKL +----------------------+ | + | | | | + +---------+ +---------------------------------+ +``` + +The GPIO number used by this example can be changed in [avrcp_cover_art_service.c](../common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c), where: + +| GPIO number | LCD pin | +| ------------------------ | ------- | +| EXAMPLE_PIN_NUM_PCLK | SCK | +| EXAMPLE_PIN_NUM_CS | CS | +| EXAMPLE_PIN_NUM_DC | DC | +| EXAMPLE_PIN_NUM_RST | RST | +| EXAMPLE_PIN_NUM_DATA0 | MOSI | +| EXAMPLE_PIN_NUM_BK_LIGHT | BCKL | + +Note that the level used to turn on the LCD backlight may vary: some LCD modules need a low level to turn it on, while others require a high level. You can change the backlight level macro `EXAMPLE_LCD_BK_LIGHT_ON_LEVEL` in [avrcp_cover_art_service.c](../common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c). + +### Configure the project + +``` +idf.py menuconfig +``` + +* The AVRCP CT Cover Art feature is enabled by default. We can disable it by unselecting the menuconfig option `Component config --> Bluetooth --> Bluedroid Options --> Classic Bluetooth --> AVRCP Features --> AVRCP CT Cover Art`. This example will try to use the AVRCP CT Cover Art feature to get the cover art image, count the image size, and display it if the peer device supports it. +* **Memory Configuration**: To ensure that the A2DP sink stream and the display of AVRCP cover art on the LCD can run simultaneously, the following configurations are required and have been set in `sdkconfig.defaults`: + * `CONFIG_SPIRAM=y`: Enables external SPI RAM (PSRAM) support. This provides additional memory space needed for buffering audio data during A2DP streaming while simultaneously handling cover art image decoding and display operations. Without this, the application may run out of internal RAM when processing both audio streams and image data. + * `CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y`: Selects the single large app partition table scheme, which allocates more space for the application binary. This is necessary because the example application includes multiple Bluetooth profiles (A2DP, AVRCP), image decoding libraries, and LCD display drivers, requiring a larger application partition than the default partition table provides. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output. + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +## Example Output + +The output when receiving a cover art image: + +``` +I (31579) RC_CT: AVRC metadata rsp: attribute id 0x80, 1000526 +I (32039) RC_CA_SRV: Cover Art Client final data event, image size: 12315 bytes +I (32119) RC_CA_SRV: JPEG image decoded! Size of the decoded image is: 200px x 200px. +``` + +And then, the LCD screen will display the cover art image. + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/CMakeLists.txt new file mode 100644 index 0000000000..6cb6aebf26 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/CMakeLists.txt @@ -0,0 +1,13 @@ +if(CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE) + if(CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC) + set(EXTRA_COMPONENTS a2dp_sink_ext_codec_utils) + else() + set(EXTRA_COMPONENTS a2dp_sink_int_codec_utils) + endif() +endif() + +idf_component_register(SRCS "bt_app_av.c" + "main.c" + PRIV_REQUIRES bt bt_app_core_utils bredr_app_common_utils a2dp_sink_common_utils + PRIV_REQUIRES ${EXTRA_COMPONENTS} avrcp_common_utils avrcp_metadata_utils avrcp_cover_art_utils + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/Kconfig.projbuild new file mode 100644 index 0000000000..2a4dfc0176 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/Kconfig.projbuild @@ -0,0 +1,23 @@ +menu "AVRCP Example Configuration" + config EXAMPLE_LOCAL_DEVICE_NAME + string "Local Device Name" + default "ESP_SPEAKER" + help + Use this option to set local device name. + + config EXAMPLE_A2DP_SINK_STREAM_ENABLE + bool "Enable A2DP Sink Stream" + default y + help + This enables the A2DP sink stream. If disable this option, + audio data will not be transmitted + + config EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC + bool "Use External Codec Instead of Internal" + depends on EXAMPLE_A2DP_SINK_STREAM_ENABLE + default n + select BT_A2DP_USE_EXTERNAL_CODEC + help + If enable, Bluedroid stack will not decode A2DP audio data, user need to decode it in application layer. + +endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.c new file mode 100644 index 0000000000..6683dc9306 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.c @@ -0,0 +1,206 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_avrc_api.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "bt_app_core_utils.h" +#include "bt_app_av.h" +#include "avrcp_utils_tags.h" +#include "avrcp_common_utils.h" +#include "avrcp_metadata_service.h" +#include "avrcp_metadata_utils.h" +#include "a2dp_utils_tags.h" +#include "a2dp_sink_common_utils.h" +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +#include "a2dp_sink_int_codec_utils.h" +#else +#include "a2dp_sink_ext_codec_utils.h" +#endif +#endif +#include "avrcp_cover_art_service.h" +#include "avrcp_cover_art_utils.h" + +/******************************** + * STATIC FUNCTION DEFINITIONS + *******************************/ + +static void bt_app_avrc_ct_evt_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event); + + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); + + switch (event) { + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: + case ESP_AVRC_CT_PROF_STATE_EVT: { + bt_avrc_common_ct_evt_def_hdl(event, param); + break; + } + case ESP_AVRC_CT_CONNECTION_STATE_EVT: { + bt_avrc_md_ct_evt_hdl(event, param); + bt_avrc_ca_ct_evt_hdl(event, param); + if (rc->conn_stat.connected) { + /* get remote supported event_ids of peer AVRCP Target */ + bt_avrc_common_ct_get_peer_rn_cap(); + } else { + /* clear peer notification capability record */ + bt_avrc_common_ct_set_peer_rn_cap(0); + } + break; + } + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { + bt_avrc_md_ct_evt_hdl(event, param); + bt_avrc_ca_ct_evt_hdl(event, param); + bt_avrc_common_ct_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter); + break; + } + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { + /* set peer notification capability record */ + bt_avrc_common_ct_set_peer_rn_cap(rc->get_rn_caps_rsp.evt_set.bits); + bt_avrc_common_ct_rn_track_changed(); + bt_avrc_common_ct_rn_play_status_changed(); + bt_avrc_common_ct_rn_play_pos_changed(); + + bt_avrc_md_ct_evt_hdl(event, param); + bt_avrc_ca_ct_evt_hdl(event, param); + break; + } + case ESP_AVRC_CT_METADATA_RSP_EVT: { + if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_COVER_ART) { + bt_avrc_ca_ct_evt_hdl(event, param); + } else { + bt_avrc_md_ct_evt_hdl(event, param); + } + break; + } + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: { + bt_avrc_ca_ct_evt_hdl(event, param); + break; + } + case ESP_AVRC_CT_COVER_ART_STATE_EVT: + case ESP_AVRC_CT_COVER_ART_DATA_EVT: { + bt_avrc_ca_ct_evt_hdl(event, param); + break; + } + default: + ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) +{ + switch (event) { + case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_SNK_PSC_CFG_EVT: + case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: + case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + break; + } + case ESP_A2D_CONNECTION_STATE_EVT: + case ESP_A2D_AUDIO_STATE_EVT: + case ESP_A2D_AUDIO_CFG_EVT: + case ESP_A2D_SEP_REG_STATE_EVT: { +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#else + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#endif +#else + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#endif + break; + } + default: + ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event); + break; + } +} + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) +{ + bt_a2d_data_hdl(data, len); +} +#else +void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ + bt_a2d_audio_data_hdl(conn_hdl, audio_buf); +} +#endif +#endif + +void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) +{ + switch (event) { + case ESP_AVRC_CT_METADATA_RSP_EVT: { + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), bt_avrc_common_copy_metadata); + break; + } + case ESP_AVRC_CT_COVER_ART_DATA_EVT: { + /* we must handle ESP_AVRC_CT_COVER_ART_DATA_EVT in avrcp controller callback, */ + /* copy image data to other buff before return if need */ + if (param->cover_art_data.status == ESP_BT_STATUS_SUCCESS) { + avrc_cover_art_srv_save_image_data(param->cover_art_data.p_data, param->cover_art_data.data_len); + } else { + ESP_LOGE(BT_RC_CT_TAG, "Cover Art Client get operation failed"); + break; + } + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + break; + } + case ESP_AVRC_CT_CONNECTION_STATE_EVT: + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: + case ESP_AVRC_CT_COVER_ART_STATE_EVT: + case ESP_AVRC_CT_PROF_STATE_EVT: + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + break; + default: + ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param) +{ + switch (event) { + case ESP_AVRC_TG_CONNECTION_STATE_EVT: + case ESP_AVRC_TG_REMOTE_FEATURES_EVT: + case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: + case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: + case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: + case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: + case ESP_AVRC_TG_PROF_STATE_EVT: + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + break; + default: + ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event); + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.h b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.h similarity index 87% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.h rename to examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.h index 50a2116627..5669ad6fca 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.h +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -11,11 +11,6 @@ #include "esp_a2dp_api.h" #include "esp_avrc_api.h" -/* log tags */ -#define BT_AV_TAG "BT_AV" -#define BT_RC_TG_TAG "RC_TG" -#define BT_RC_CT_TAG "RC_CT" - /** * @brief callback function for A2DP sink * diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/idf_component.yml b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/idf_component.yml new file mode 100644 index 0000000000..39b2c44fae --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/idf_component.yml @@ -0,0 +1,17 @@ +dependencies: + bt_app_core_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils + bredr_app_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils + a2dp_sink_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils + a2dp_sink_int_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils + a2dp_sink_ext_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils + avrcp_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils + avrcp_metadata_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils + avrcp_cover_art_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/main.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/main.c new file mode 100644 index 0000000000..00b2f538f1 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/main.c @@ -0,0 +1,133 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include + +#include "esp_log.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" +#include "esp_avrc_api.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "bt_app_av.h" +#include "bt_app_core_utils.h" +#include "bredr_app_common_utils.h" +#include "a2dp_utils_tags.h" + +/* device name */ +static const char local_device_name[] = CONFIG_EXAMPLE_LOCAL_DEVICE_NAME; + +/* event for stack up */ +enum { + BT_APP_EVT_STACK_UP = 0, +}; + +/******************************** + * STATIC FUNCTION DECLARATIONS + *******************************/ + +/* Device callback function */ +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param); + +/* GAP callback function */ +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); + +/* handler for bluetooth stack enabled events */ +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param) +{ + bredr_app_dev_evt_def_hdl(event, param); +} + +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + bredr_app_gap_evt_def_hdl(event, param); +} + +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); + + switch (event) { + /* when do the stack up, this event comes */ + case BT_APP_EVT_STACK_UP: { + esp_bt_gap_set_device_name(local_device_name); + esp_bt_dev_register_callback(bt_app_dev_cb); + esp_bt_gap_register_callback(bt_app_gap_cb); + + esp_avrc_ct_register_callback(bt_app_rc_ct_cb); + assert(esp_avrc_ct_init() == ESP_OK); + esp_avrc_tg_register_callback(bt_app_rc_tg_cb); + assert(esp_avrc_tg_init() == ESP_OK); + + esp_a2d_register_callback(&bt_app_a2d_cb); + assert(esp_a2d_sink_init() == ESP_OK); + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); +#else + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + /* register stream end point, only support SBC currently */ + esp_a2d_sink_register_stream_endpoint(0, &mcc); + esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); +#endif +#endif + + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + /* Get local device name */ + esp_bt_gap_get_device_name(); + + /* set discoverable and connectable mode, wait to be connected */ + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +/******************************* + * MAIN ENTRY POINT + ******************************/ + +void app_main(void) +{ + ESP_ERROR_CHECK(bredr_app_common_init()); + + bt_app_task_start_up(); + /* bluetooth device name, connection mode and profile set up */ + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py new file mode 100644 index 0000000000..8e141cafac --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/pytest_classic_bt_cover_art_test.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + + +@pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_bt_avrcp_cover_art(dut: Dut) -> None: + dut.expect(r'AVRCP (CT|TG) STATE: Init Complete', timeout=30) + dut.expect(r'AVRCP (CT|TG) STATE: Init Complete', timeout=30) diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/sdkconfig.defaults similarity index 83% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.defaults rename to examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/sdkconfig.defaults index 3d17667a4c..cde91dde57 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/sdkconfig.defaults @@ -1,11 +1,11 @@ # Override some defaults so BT stack is enabled and # Classic BT is enabled and BT_DRAM_RELEASE is disabled CONFIG_BT_ENABLED=y -CONFIG_BTDM_CTRL_MODE_BLE_ONLY=n CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y -CONFIG_BTDM_CTRL_MODE_BTDM=n CONFIG_BT_BLUEDROID_ENABLED=y CONFIG_BT_CLASSIC_ENABLED=y CONFIG_BT_A2DP_ENABLE=y CONFIG_BT_AVRCP_CT_COVER_ART_ENABLED=y CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=n +CONFIG_SPIRAM=y +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/CMakeLists.txt new file mode 100644 index 0000000000..4c2312939a --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) +project(avrcp_ct_metadata) diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/README.md b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/README.md new file mode 100644 index 0000000000..5a02564951 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/README.md @@ -0,0 +1,67 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | + +AVRCP-CT-METADATA EXAMPLE +====================== + +This is the example of API implementing Audio/Video Remote Control Profile to get metadata. + +## Required components + +- [bt_app_core_utils](../common/bt_app_core_utils) +- [bredr_app_common_utils](../common/bredr_app_common_utils) +- [a2dp_sink_common_utils](../common/a2dp_utils/a2dp_sink_common_utils) +- [a2dp_sink_int_codec_utils](../common/a2dp_utils/a2dp_sink_int_codec_utils) +- [a2dp_sink_ext_codec_utils](../common/a2dp_utils/a2dp_sink_ext_codec_utils) +- [avrcp_common_utils](../common/avrcp_utils/avrcp_common_utils) +- [avrcp_metadata_utils](../common/avrcp_utils/avrcp_metadata_utils) + +``` ++---------------------------------------------------+---------------------+ +| avrcp_metadata_utils | | ++---------------------------------------------------+ | +| avrcp_common_utils | | ++-------------------------+-------------------------+ | +|a2dp_sink_int_codec_utils|a2dp_sink_ext_codec_utils| bt_app_core_utils | ++-------------------------+-------------------------+ | +| a2dp_sink_common_utils | | ++---------------------------------------------------+ | +| bredr_app_common_utils | | ++---------------------------------------------------+---------------------+ +``` + +Detailed information can be viewed through the [../common/README.md](../common/README.md). + +## How to use this example + +### Configure the project + +``` +idf.py menuconfig +``` + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output. + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +## Example Output + +The output when receiving metadata: + +``` +I (81700) RC_CT: AVRC event notification: 2 +I (81740) RC_CT: AVRC metadata rsp: attribute id 0x1, +I (81740) RC_CT: AVRC metadata rsp: attribute id 0x2, +I (81740) RC_CT: AVRC metadata rsp: attribute id 0x4, +I (81750) RC_CT: AVRC metadata rsp: attribute id 0x20, +``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/CMakeLists.txt new file mode 100644 index 0000000000..9807f92c7c --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/CMakeLists.txt @@ -0,0 +1,12 @@ +if(CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE) + if(CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC) + set(EXTRA_COMPONENTS a2dp_sink_ext_codec_utils) + else() + set(EXTRA_COMPONENTS a2dp_sink_int_codec_utils) + endif() +endif() + +idf_component_register(SRCS "main.c" + PRIV_REQUIRES bt bt_app_core_utils bredr_app_common_utils a2dp_sink_common_utils + PRIV_REQUIRES ${EXTRA_COMPONENTS} avrcp_common_utils avrcp_metadata_utils + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/Kconfig.projbuild new file mode 100644 index 0000000000..2a4dfc0176 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/Kconfig.projbuild @@ -0,0 +1,23 @@ +menu "AVRCP Example Configuration" + config EXAMPLE_LOCAL_DEVICE_NAME + string "Local Device Name" + default "ESP_SPEAKER" + help + Use this option to set local device name. + + config EXAMPLE_A2DP_SINK_STREAM_ENABLE + bool "Enable A2DP Sink Stream" + default y + help + This enables the A2DP sink stream. If disable this option, + audio data will not be transmitted + + config EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC + bool "Use External Codec Instead of Internal" + depends on EXAMPLE_A2DP_SINK_STREAM_ENABLE + default n + select BT_A2DP_USE_EXTERNAL_CODEC + help + If enable, Bluedroid stack will not decode A2DP audio data, user need to decode it in application layer. + +endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/idf_component.yml b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/idf_component.yml new file mode 100644 index 0000000000..bedf3538c1 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/idf_component.yml @@ -0,0 +1,15 @@ +dependencies: + bt_app_core_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils + bredr_app_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils + a2dp_sink_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils + a2dp_sink_int_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils + a2dp_sink_ext_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils + avrcp_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils + avrcp_metadata_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/main.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/main.c new file mode 100644 index 0000000000..92f7f5f7b4 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/main.c @@ -0,0 +1,295 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include + +#include "esp_log.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" +#include "esp_avrc_api.h" + +#include "bt_app_core_utils.h" +#include "bredr_app_common_utils.h" +#include "a2dp_utils_tags.h" +#include "a2dp_sink_common_utils.h" +#include "avrcp_utils_tags.h" +#include "avrcp_common_utils.h" +#include "avrcp_metadata_utils.h" +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +#include "a2dp_sink_int_codec_utils.h" +#else +#include "a2dp_sink_ext_codec_utils.h" +#endif +#endif + +/* device name */ +static const char local_device_name[] = CONFIG_EXAMPLE_LOCAL_DEVICE_NAME; + +/* event for stack up */ +enum { + BT_APP_EVT_STACK_UP = 0, +}; + +/******************************** + * STATIC FUNCTION DECLARATIONS + *******************************/ + +/* Device callback function */ +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param); + +/* GAP callback function */ +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); + +/* callback function for A2DP sink */ +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +/* callback function for A2DP sink audio data stream */ +static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len); +#else +/* callback function for A2DP sink undecoded audio data */ +static void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); +#endif +#endif + +/* handler for AVRCP controller events */ +static void bt_app_avrc_ct_evt_hdl(uint16_t event, void *param); + +/* callback function for AVRCP controller */ +static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param); + +/* callback function for AVRCP target */ +static void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param); + +/* handler for bluetooth stack enabled events */ +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param) +{ + bredr_app_dev_evt_def_hdl(event, param); +} + +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + bredr_app_gap_evt_def_hdl(event, param); +} + +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) +{ + switch (event) { + case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_SNK_PSC_CFG_EVT: + case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: + case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + break; + } + case ESP_A2D_CONNECTION_STATE_EVT: + case ESP_A2D_AUDIO_STATE_EVT: + case ESP_A2D_AUDIO_CFG_EVT: + case ESP_A2D_SEP_REG_STATE_EVT: { +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#else + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#endif +#else + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); +#endif + break; + } + default: + ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event); + break; + } +} + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE +static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) +{ + bt_a2d_data_hdl(data, len); +} +#else +static void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ + bt_a2d_audio_data_hdl(conn_hdl, audio_buf); +} +#endif +#endif + +static void bt_app_avrc_ct_evt_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event); + + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); + + switch (event) { + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: + case ESP_AVRC_CT_PROF_STATE_EVT: { + bt_avrc_common_ct_evt_def_hdl(event, param); + break; + } + case ESP_AVRC_CT_CONNECTION_STATE_EVT: { + bt_avrc_md_ct_evt_hdl(event, param); + if (rc->conn_stat.connected) { + /* get remote supported event_ids of peer AVRCP Target */ + bt_avrc_common_ct_get_peer_rn_cap(); + } else { + /* clear peer notification capability record */ + bt_avrc_common_ct_set_peer_rn_cap(0); + } + break; + } + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { + bt_avrc_md_ct_evt_hdl(event, param); + bt_avrc_common_ct_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter); + break; + } + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { + /* set peer notification capability record */ + bt_avrc_common_ct_set_peer_rn_cap(rc->get_rn_caps_rsp.evt_set.bits); + bt_avrc_common_ct_rn_track_changed(); + bt_avrc_common_ct_rn_play_status_changed(); + bt_avrc_common_ct_rn_play_pos_changed(); + + bt_avrc_md_ct_evt_hdl(event, param); + break; + } + case ESP_AVRC_CT_METADATA_RSP_EVT: { + bt_avrc_md_ct_evt_hdl(event, param); + break; + } + default: + ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) +{ + switch (event) { + case ESP_AVRC_CT_METADATA_RSP_EVT: { + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), bt_avrc_common_copy_metadata); + break; + } + case ESP_AVRC_CT_CONNECTION_STATE_EVT: + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: + case ESP_AVRC_CT_PROF_STATE_EVT: + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + break; + default: + ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +static void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param) +{ + switch (event) { + case ESP_AVRC_TG_CONNECTION_STATE_EVT: + case ESP_AVRC_TG_REMOTE_FEATURES_EVT: + case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: + case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: + case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: + case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: + case ESP_AVRC_TG_PROF_STATE_EVT: + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + break; + default: + ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); + + switch (event) { + /* when do the stack up, this event comes */ + case BT_APP_EVT_STACK_UP: { + esp_bt_gap_set_device_name(local_device_name); + esp_bt_dev_register_callback(bt_app_dev_cb); + esp_bt_gap_register_callback(bt_app_gap_cb); + + esp_avrc_ct_register_callback(bt_app_rc_ct_cb); + assert(esp_avrc_ct_init() == ESP_OK); + esp_avrc_tg_register_callback(bt_app_rc_tg_cb); + assert(esp_avrc_tg_init() == ESP_OK); + + esp_a2d_register_callback(&bt_app_a2d_cb); + assert(esp_a2d_sink_init() == ESP_OK); + +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); +#else + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + /* register stream end point, only support SBC currently */ + esp_a2d_sink_register_stream_endpoint(0, &mcc); + esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); +#endif +#endif + + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + /* Get local device name */ + esp_bt_gap_get_device_name(); + + /* set discoverable and connectable mode, wait to be connected */ + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +/******************************* + * MAIN ENTRY POINT + ******************************/ + +void app_main(void) +{ + ESP_ERROR_CHECK(bredr_app_common_init()); + + bt_app_task_start_up(); + /* bluetooth device name, connection mode and profile set up */ + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py new file mode 100644 index 0000000000..1c01e7fff8 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/pytest_classic_bt_metadata_test.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + + +@pytest.mark.generic +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_bt_avrcp_metadata(dut: Dut) -> None: + dut.expect(r'AVRCP (CT|TG) STATE: Init Complete', timeout=30) + dut.expect(r'AVRCP (CT|TG) STATE: Init Complete', timeout=30) diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/sdkconfig.defaults new file mode 100644 index 0000000000..2b93a51a0e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/sdkconfig.defaults @@ -0,0 +1,8 @@ +# Override some defaults so BT stack is enabled and +# Classic BT is enabled and BT_DRAM_RELEASE is disabled +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y +CONFIG_BT_BLUEDROID_ENABLED=y +CONFIG_BT_CLASSIC_ENABLED=y +CONFIG_BT_A2DP_ENABLE=y +CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=n diff --git a/examples/bluetooth/bluedroid/classic_bt/common/README.md b/examples/bluetooth/bluedroid/classic_bt/common/README.md new file mode 100644 index 0000000000..e830d23d75 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/README.md @@ -0,0 +1,44 @@ +COMMON CODE +====================== + +This folder provides the universal code for classic Bluetooth applications, and corresponding functions can be achieved by combining different parts. + +## File Tree + +The file tree of this folder is shown below. +- The [a2dp_utils](./a2dp_utils) folder contains the files of A2DP including `a2dp_sink_common_utils`, `a2dp_sink_ext_codec_utils` and `a2dp_sink_int_codec_utils` related files. The [a2dp_sink_common_utils](./a2dp_utils/a2dp_sink_common_utils) folder is about common handle function for A2DP sink event. The [a2dp_sink_ext_codec_utils](./a2dp_utils/a2dp_sink_ext_codec_utils) folder is about external codec of audio data. The [a2dp_sink_int_codec_utils](./a2dp_utils/a2dp_sink_int_codec_utils) folder is about internal codec of audio data. +- The [avrcp_utils](./avrcp_utils) folder contains the files of AVRCP including `avrcp_abs_vol_utils`, `avrcp_common_utils`, `avrcp_cover_art_utils` and `avrcp_metadata_utils` related files. The [avrcp_abs_vol_utils](./avrcp_utils/avrcp_abs_vol_utils) folder is about AVRCP absolute volume control event. The [avrcp_common_utils](./avrcp_utils/avrcp_common_utils) folder is about common handle function for AVRCP event. The [avrcp_cover_art_utils](./avrcp_utils/avrcp_cover_art_utils) folder is about AVRCP cover art event. The [avrcp_metadata_utils](./avrcp_utils/avrcp_metadata_utils) folder is about AVRCP metadata event. +- The [bredr_app_common_utils](./bredr_app_common_utils) folder contains the files of Classic Bluetooth common code including Classic Bluetooth common initialization and handle function about GAP and device. +- The [bt_app_core_utils](./bt_app_core_utils) folder contains the program core files. + +``` +└── common +    ├── a2dp_utils +    │   ├── a2dp_sink_common_utils +    │   ├── a2dp_sink_ext_codec_utils +    │   └── a2dp_sink_int_codec_utils +    ├── avrcp_utils +   │   ├── avrcp_abs_vol_utils +    │   ├── avrcp_common_utils +    │   ├── avrcp_cover_art_utils +    │   └── avrcp_metadata_utils +    ├── bredr_app_common_utils +    ├── bt_app_core_utils +    └── README.md +``` + +## How to use + +The functional framework diagram is shown below. The `bt_app_core_utils` is responsible for all event scheduling. Specific functions can be implemented by general code combined with unique code. For instance, the internal decoding audio output of A2DP sink can be achieved through components such as `bredr_app_common_utils`, `a2dp_sink_common_utils`, and `a2dp_sink_int_codec_utils`. On this basis, adding the code `avrcp_common_utils` and `avrcp_abs_vol_utils` can enable volume adjustment, or incorporating `avrcp_common_utils` and `avrcp_metadata_utils` can facilitate the transmission of metadata. + +``` ++---------------------------------------------------+---------------------+ +| AVRCP feature(avrcp_utils/unique code) | | ++-------------------------+-------------------------+ | +|a2dp_sink_int_codec_utils|a2dp_sink_ext_codec_utils| | ++-------------------------+-------------------------+ bt_app_core_utils | +| a2dp_sink_common_utils | | ++---------------------------------------------------+ | +| bredr_app_common_utils | | ++---------------------------------------------------+---------------------+ +``` diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/CMakeLists.txt new file mode 100644 index 0000000000..f45a66c150 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "a2dp_sink_common_utils.c" + PRIV_REQUIRES bt + INCLUDE_DIRS "." "../include") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/a2dp_sink_common_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/a2dp_sink_common_utils.c new file mode 100644 index 0000000000..e5c886dd14 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/a2dp_sink_common_utils.c @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "a2dp_sink_common_utils.h" +#include "a2dp_utils_tags.h" + +/* Application layer causes delay value */ +#define APP_DELAY_VALUE 50 // 5ms + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* connection state in string */ +static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; +/* audio stream datapath state in string */ +static const char *s_a2d_audio_state_str[] = {"Suspended", "Started"}; + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void bt_a2d_evt_def_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); + + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_A2D_CONNECTION_STATE_EVT: { + uint8_t *bda = a2d->conn_stat.remote_bda; + ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", + s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED) { + esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); + } + break; + } + /* when audio stream transmission state changed, this event comes */ + case ESP_A2D_AUDIO_STATE_EVT: { + ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]); + break; + } + /* when audio codec is configured, this event comes */ + case ESP_A2D_AUDIO_CFG_EVT: { + esp_a2d_mcc_t *p_mcc = &a2d->audio_cfg.mcc; + ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, codec type: %d", p_mcc->type); + break; + } + /* when a2dp init or deinit completed, this event comes */ + case ESP_A2D_PROF_STATE_EVT: { + if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); + } + break; + } + /* when using external codec, after sep registration done, this event comes */ + case ESP_A2D_SEP_REG_STATE_EVT: { + if (a2d->a2d_sep_reg_stat.reg_state == ESP_A2D_SEP_REG_SUCCESS) { + ESP_LOGI(BT_AV_TAG, "A2DP register SEP success, seid: %d", a2d->a2d_sep_reg_stat.seid); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP register SEP fail, seid: %d, state: %d", a2d->a2d_sep_reg_stat.seid, a2d->a2d_sep_reg_stat.reg_state); + } + break; + } + /* When protocol service capabilities configured, this event comes */ + case ESP_A2D_SNK_PSC_CFG_EVT: { + ESP_LOGI(BT_AV_TAG, "protocol service capabilities configured: 0x%x ", a2d->a2d_psc_cfg_stat.psc_mask); + if (a2d->a2d_psc_cfg_stat.psc_mask & ESP_A2D_PSC_DELAY_RPT) { + ESP_LOGI(BT_AV_TAG, "Peer device support delay reporting"); + } else { + ESP_LOGI(BT_AV_TAG, "Peer device unsupported delay reporting"); + } + break; + } + /* when set delay value completed, this event comes */ + case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: { + if (ESP_A2D_SET_INVALID_PARAMS == a2d->a2d_set_delay_value_stat.set_state) { + ESP_LOGI(BT_AV_TAG, "Set delay report value: fail"); + } else { + ESP_LOGI(BT_AV_TAG, "Set delay report value: success, delay_value: %u * 1/10 ms", a2d->a2d_set_delay_value_stat.delay_value); + } + break; + } + /* when get delay value completed, this event comes */ + case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { + ESP_LOGI(BT_AV_TAG, "Get delay report value: delay_value: %u * 1/10 ms", a2d->a2d_get_delay_value_stat.delay_value); + /* Default delay value plus delay caused by application layer */ + esp_a2d_sink_set_delay_value(a2d->a2d_get_delay_value_stat.delay_value + APP_DELAY_VALUE); + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/a2dp_sink_common_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/a2dp_sink_common_utils.h new file mode 100644 index 0000000000..8a09368a94 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils/a2dp_sink_common_utils.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __A2DP_SINK_COMMON_UTILS_H__ +#define __A2DP_SINK_COMMON_UTILS_H__ + +#include + +/** + * @brief default handle function for A2DP sink event + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_a2d_evt_def_hdl(uint16_t event, void *param); + +#endif /* __A2DP_SINK_COMMON_UTILS_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/CMakeLists.txt new file mode 100644 index 0000000000..229a18af0e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "a2dp_sink_ext_codec_utils.c" + PRIV_REQUIRES bt + INCLUDE_DIRS "." "../include") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/a2dp_sink_ext_codec_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/a2dp_sink_ext_codec_utils.c new file mode 100644 index 0000000000..e19ca2d95d --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/a2dp_sink_ext_codec_utils.c @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" + +#include "a2dp_sink_ext_codec_utils.h" +#include "a2dp_utils_tags.h" + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* count for audio packet */ +static uint32_t s_pkt_cnt = 0; +/* connection state in string */ +static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; +/* audio stream datapath state in string */ +static const char *s_a2d_audio_state_str[] = {"Suspended", "Started"}; + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void bt_a2d_evt_ext_codec_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); + + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_A2D_CONNECTION_STATE_EVT: { + uint8_t *bda = a2d->conn_stat.remote_bda; + ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", + s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED) { + esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); + } + break; + } + /* when audio stream transmission state changed, this event comes */ + case ESP_A2D_AUDIO_STATE_EVT: { + ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]); + if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { + s_pkt_cnt = 0; + } + break; + } + /* when audio codec is configured, this event comes */ + case ESP_A2D_AUDIO_CFG_EVT: { + esp_a2d_mcc_t *p_mcc = &a2d->audio_cfg.mcc; + ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, codec type: %d", p_mcc->type); + /* for now only SBC stream is supported */ + if (p_mcc->type == ESP_A2D_MCT_SBC) { + int sample_rate = 16000; + if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_32K) { + sample_rate = 32000; + } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_44K) { + sample_rate = 44100; + } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_48K) { + sample_rate = 48000; + } + ESP_LOGI(BT_AV_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", + p_mcc->cie.sbc_info.samp_freq, + p_mcc->cie.sbc_info.ch_mode, + p_mcc->cie.sbc_info.block_len, + p_mcc->cie.sbc_info.num_subbands, + p_mcc->cie.sbc_info.alloc_mthd, + p_mcc->cie.sbc_info.min_bitpool, + p_mcc->cie.sbc_info.max_bitpool); + ESP_LOGI(BT_AV_TAG, "Audio player configured, sample rate: %d", sample_rate); + } + break; + } + /* when using external codec, after sep registration done, this event comes */ + case ESP_A2D_SEP_REG_STATE_EVT: { + if (a2d->a2d_sep_reg_stat.reg_state == ESP_A2D_SEP_REG_SUCCESS) { + ESP_LOGI(BT_AV_TAG, "A2DP register SEP success, seid: %d", a2d->a2d_sep_reg_stat.seid); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP register SEP fail, seid: %d, state: %d", a2d->a2d_sep_reg_stat.seid, a2d->a2d_sep_reg_stat.reg_state); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +void bt_a2d_audio_data_hdl(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ + /* log the number every 100 packets */ + if (++s_pkt_cnt % 100 == 0) { + ESP_LOGI(BT_AV_TAG, "Undecoded audio package count: %"PRIu32, s_pkt_cnt); + } + + /* + * Normally, user should send the audio_buf to other task, decode and free audio buff, + * But the codec component is not merge into IDF now, so we just free audio data here + */ + esp_a2d_audio_buff_free(audio_buf); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/a2dp_sink_ext_codec_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/a2dp_sink_ext_codec_utils.h new file mode 100644 index 0000000000..400b7ab376 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_ext_codec_utils/a2dp_sink_ext_codec_utils.h @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __A2DP_SINK_EXT_CODEC_UTILS_H__ +#define __A2DP_SINK_EXT_CODEC_UTILS_H__ + +#include +#include "esp_a2dp_api.h" + +/** + * @brief handle function for A2DP sink external codec + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_a2d_evt_ext_codec_hdl(uint16_t event, void *param); + +/** + * @brief handle function for A2DP sink undecoded audio data + * + * @param [in] conn_hdl connection handle + * @param [in] audio_buf pointer to audio buff + */ +void bt_a2d_audio_data_hdl(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); + +#endif /* __A2DP_SINK_EXT_CODEC_UTILS_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/CMakeLists.txt new file mode 100644 index 0000000000..4e39651fff --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register(SRCS "a2dp_sink_int_codec_utils.c" + "audio_sink_service_idle.c" + "audio_sink_service_i2s.c" + "audio_sink_service_dac.c" + PRIV_REQUIRES esp_driver_i2s bt esp_ringbuf esp_driver_dac + INCLUDE_DIRS "." "../include") diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/Kconfig.projbuild similarity index 79% rename from examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/Kconfig.projbuild rename to examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/Kconfig.projbuild index ce29dd6c03..cd16bd351a 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/Kconfig.projbuild +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/Kconfig.projbuild @@ -1,12 +1,4 @@ -menu "A2DP Example Configuration" - config EXAMPLE_A2DP_SINK_SSP_ENABLED - bool "Secure Simple Pairing" - depends on BT_CLASSIC_ENABLED - default y - help - This enables the Secure Simple Pairing. If disable this option, - Bluedroid will only support Legacy Pairing - +menu "A2DP Sink Internal Codec Example Configuration" choice EXAMPLE_A2DP_SINK_OUTPUT prompt "A2DP Sink Output" default EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S @@ -25,11 +17,16 @@ menu "A2DP Example Configuration" help Select this to use External I2S sink output + config EXAMPLE_A2DP_SINK_OUTPUT_IDLE + bool "Idle Output" + help + Select this to discard a2dp sink data + endchoice config EXAMPLE_I2S_LRCK_PIN int "I2S LRCK (WS) GPIO" - default 22 + default 27 depends on EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S help GPIO number to use for I2S LRCK(WS) Driver. diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/a2dp_sink_int_codec_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/a2dp_sink_int_codec_utils.c new file mode 100644 index 0000000000..105b0070ae --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/a2dp_sink_int_codec_utils.c @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" + +#include "audio_sink_service.h" +#include "a2dp_sink_int_codec_utils.h" +#include "a2dp_utils_tags.h" + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* count for audio packet */ +static uint32_t s_pkt_cnt = 0; +/* connection state in string */ +static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; +/* audio stream datapath state in string */ +static const char *s_a2d_audio_state_str[] = {"Suspended", "Started"}; + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void bt_a2d_evt_int_codec_hdl(uint16_t event, void *param) +{ + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_A2D_CONNECTION_STATE_EVT: { + uint8_t *bda = a2d->conn_stat.remote_bda; + ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", + s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + audio_sink_srv_stop(); + audio_sink_srv_close(); + } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED) { + esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); + audio_sink_srv_start(); + } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTING) { + audio_sink_srv_open(); + } + break; + } + /* when audio stream transmission state changed, this event comes */ + case ESP_A2D_AUDIO_STATE_EVT: { + ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]); + if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { + s_pkt_cnt = 0; + } + break; + } + /* when audio codec is configured, this event comes */ + case ESP_A2D_AUDIO_CFG_EVT: { + audio_sink_srv_codec_info_update(&a2d->audio_cfg.mcc); + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +void bt_a2d_data_hdl(const uint8_t *data, uint32_t len) +{ + audio_sink_srv_data_output(data, len); + + /* log the number every 100 packets */ + if (++s_pkt_cnt % 100 == 0) { + ESP_LOGI(BT_AV_TAG, "Audio packet count: %"PRIu32, s_pkt_cnt); + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/a2dp_sink_int_codec_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/a2dp_sink_int_codec_utils.h new file mode 100644 index 0000000000..7a3f44e28f --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/a2dp_sink_int_codec_utils.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __A2DP_SINK_INT_CODEC_UTILS_H__ +#define __A2DP_SINK_INT_CODEC_UTILS_H__ + +#include + +/** + * @brief handle function for A2DP sink internal codec + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_a2d_evt_int_codec_hdl(uint16_t event, void *param); + +/** + * @brief handle function for A2DP sink audio data stream + * + * @param [out] data data stream written by application task + * @param [in] len length of data stream in byte + */ +void bt_a2d_data_hdl(const uint8_t *data, uint32_t len); + +#endif /* __A2DP_SINK_INT_CODEC_UTILS_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service.h b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service.h new file mode 100644 index 0000000000..0aaa7aa991 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AUDIO_SINK_SERVICE_H__ +#define __AUDIO_SINK_SERVICE_H__ + +#include +#include +#include "esp_a2dp_api.h" + +#define RINGBUF_HIGHEST_WATER_LEVEL (32 * 1024) +#define RINGBUF_PREFETCH_WATER_LEVEL (20 * 1024) + +typedef enum { + RINGBUFFER_MODE_PROCESSING, /* ringbuffer is buffering incoming audio data */ + RINGBUFFER_MODE_PREFETCHING, /* ringbuffer is buffering incoming audio data */ + RINGBUFFER_MODE_DROPPING /* ringbuffer is not buffering (dropping) incoming audio data */ +} audio_sink_ringbuffer_mode_t; + +typedef enum { + CHANNEL_STATUS_IDLE, + CHANNEL_STATUS_OPENED, + CHANNEL_STATUS_ENABLED +} audio_sink_chan_st_t; + +/** + * @brief open audio sink service + */ +void audio_sink_srv_open(void); + +/** + * @brief close audio sink service + */ +void audio_sink_srv_close(void); + +/** + * @brief start audio sink service + */ +void audio_sink_srv_start(void); + +/** + * @brief stop audio sink service + */ +void audio_sink_srv_stop(void); + +/** + * @brief update codec information + * + * @param [in] mcc codec information + */ +void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc); + +/** + * @brief write data to ringbuffer + * + * @param [in] data pointer to data stream + * @param [in] size data length in byte + * + * @return size if written ringbuffer successfully, 0 others + */ +size_t audio_sink_srv_data_output(const uint8_t *data, size_t size); + +#endif /* __AUDIO_SINK_SERVICE_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_dac.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_dac.c new file mode 100644 index 0000000000..0e5e377c4c --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_dac.c @@ -0,0 +1,229 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "esp_log.h" +#include "esp_a2dp_api.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "freertos/ringbuf.h" +#include "driver/dac_continuous.h" +#include "audio_sink_service.h" + +#if defined(CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC) + +/* log tag */ +#define AUDIO_SNK_SRV_DAC_TAG "SNK_SRV_DAC" + +typedef struct { + dac_continuous_handle_t tx_chan; /* handle of dac continuous channel */ + audio_sink_chan_st_t chan_st; /* dac channel status */ + TaskHandle_t write_task_handle; /* handle of writing task */ + RingbufHandle_t ringbuf; /* handle of ringbuffer */ + SemaphoreHandle_t write_semaphore; /* handle of write semaphore */ + uint16_t ringbuffer_mode; /* ringbuffer mode */ +} audio_sink_srv_dac_cb_t; + +/******************************* + * STATIC FUNCTION DECLARATIONS + ******************************/ + +/* task handler for writing data to dac */ +static void audio_sink_srv_dac_task_handler(void *arg); + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* audio sink service for dac control block */ +static audio_sink_srv_dac_cb_t s_dac_cb; + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static void audio_sink_srv_dac_task_handler(void *arg) +{ + uint8_t *data = NULL; + size_t item_size = 0; + const size_t item_size_upto = 240 * 6; + size_t bytes_written = 0; + + for (;;) { + if (pdTRUE == xSemaphoreTake(s_dac_cb.write_semaphore, portMAX_DELAY)) { + for (;;) { + item_size = 0; + /* receive data from ringbuffer and write it to DAC DMA transmit buffer */ + data = (uint8_t *)xRingbufferReceiveUpTo(s_dac_cb.ringbuf, &item_size, (TickType_t)pdMS_TO_TICKS(20), item_size_upto); + if (item_size == 0) { + ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer underflowed! mode changed: RINGBUFFER_MODE_PREFETCHING"); + s_dac_cb.ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; + break; + } + + dac_continuous_write(s_dac_cb.tx_chan, data, item_size, &bytes_written, -1); + vRingbufferReturnItem(s_dac_cb.ringbuf, (void *)data); + } + } + } +} + +/******************************* + * EXTERNAL FUNCTION DEFINITIONS + ******************************/ + +void audio_sink_srv_open(void) +{ + memset(&s_dac_cb, 0, sizeof(audio_sink_srv_dac_cb_t)); + dac_continuous_config_t cont_cfg = { + .chan_mask = DAC_CHANNEL_MASK_ALL, + .desc_num = 8, + .buf_size = 2048, + .freq_hz = 44100, + .offset = 127, + .clk_src = DAC_DIGI_CLK_SRC_DEFAULT, // Using APLL as clock source to get a wider frequency range + .chan_mode = DAC_CHANNEL_MODE_ALTER, + }; + /* Allocate continuous channels */ + ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &s_dac_cb.tx_chan)); + s_dac_cb.chan_st = CHANNEL_STATUS_OPENED; +} + +void audio_sink_srv_close(void) +{ + audio_sink_srv_stop(); + + if (s_dac_cb.chan_st == CHANNEL_STATUS_OPENED) { + ESP_ERROR_CHECK(dac_continuous_del_channels(s_dac_cb.tx_chan)); + s_dac_cb.chan_st = CHANNEL_STATUS_IDLE; + } + if (s_dac_cb.write_task_handle) { + vTaskDelete(s_dac_cb.write_task_handle); + s_dac_cb.write_task_handle = NULL; + } + if (s_dac_cb.ringbuf) { + vRingbufferDelete(s_dac_cb.ringbuf); + s_dac_cb.ringbuf = NULL; + } + if (s_dac_cb.write_semaphore) { + vSemaphoreDelete(s_dac_cb.write_semaphore); + s_dac_cb.write_semaphore = NULL; + } + memset(&s_dac_cb, 0, sizeof(audio_sink_srv_dac_cb_t)); +} + +void audio_sink_srv_start(void) +{ + if (s_dac_cb.chan_st != CHANNEL_STATUS_OPENED) { + ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "%s, TX channel wrong state: %d", __func__, s_dac_cb.chan_st); + return; + } + ESP_ERROR_CHECK(dac_continuous_enable(s_dac_cb.tx_chan)); + s_dac_cb.chan_st = CHANNEL_STATUS_ENABLED; + + ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer data empty! mode changed: RINGBUFFER_MODE_PREFETCHING"); + s_dac_cb.ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; + if ((s_dac_cb.write_semaphore = xSemaphoreCreateBinary()) == NULL) { + ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "%s, Semaphore create failed", __func__); + return; + } + if ((s_dac_cb.ringbuf = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) { + ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "%s, ringbuffer create failed", __func__); + return; + } + xTaskCreate(audio_sink_srv_dac_task_handler, "BtDACTask", 4 * 1024, NULL, configMAX_PRIORITIES - 3, &s_dac_cb.write_task_handle); +} + +void audio_sink_srv_stop(void) +{ + if (s_dac_cb.chan_st == CHANNEL_STATUS_ENABLED) { + ESP_ERROR_CHECK(dac_continuous_disable(s_dac_cb.tx_chan)); + s_dac_cb.chan_st = CHANNEL_STATUS_OPENED; + } +} + +void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) +{ + ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "A2DP audio stream configuration, codec type: %d", mcc->type); + /* for now only SBC stream is supported */ + if (mcc->type == ESP_A2D_MCT_SBC) { + int sample_rate = 16000; + int ch_count = 2; + if (mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_32K) { + sample_rate = 32000; + } else if (mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_44K) { + sample_rate = 44100; + } else if (mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_48K) { + sample_rate = 48000; + } + + if (mcc->cie.sbc_info.ch_mode & ESP_A2D_SBC_CIE_CH_MODE_MONO) { + ch_count = 1; + } + dac_continuous_del_channels(s_dac_cb.tx_chan); + dac_continuous_config_t cont_cfg = { + .chan_mask = DAC_CHANNEL_MASK_ALL, + .desc_num = 8, + .buf_size = 2048, + .freq_hz = sample_rate, + .offset = 127, + .clk_src = DAC_DIGI_CLK_SRC_DEFAULT, // Using APLL as clock source to get a wider frequency range + .chan_mode = (ch_count == 1) ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER, + }; + /* Allocate continuous channels */ + dac_continuous_new_channels(&cont_cfg, &s_dac_cb.tx_chan); + ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", + mcc->cie.sbc_info.samp_freq, + mcc->cie.sbc_info.ch_mode, + mcc->cie.sbc_info.block_len, + mcc->cie.sbc_info.num_subbands, + mcc->cie.sbc_info.alloc_mthd, + mcc->cie.sbc_info.min_bitpool, + mcc->cie.sbc_info.max_bitpool); + ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "Audio player configured, sample rate: %d", sample_rate); + } +} + +size_t audio_sink_srv_data_output(const uint8_t *data, size_t size) +{ + size_t item_size = 0; + BaseType_t done = pdFALSE; + + if (s_dac_cb.ringbuffer_mode == RINGBUFFER_MODE_DROPPING) { + ESP_LOGW(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer is full, drop this packet!"); + vRingbufferGetInfo(s_dac_cb.ringbuf, NULL, NULL, NULL, NULL, &item_size); + if (item_size <= RINGBUF_PREFETCH_WATER_LEVEL) { + ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer data decreased! mode changed: RINGBUFFER_MODE_PROCESSING"); + s_dac_cb.ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; + } + return 0; + } + + done = xRingbufferSend(s_dac_cb.ringbuf, (void *)data, size, (TickType_t)0); + + if (!done) { + ESP_LOGW(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer overflowed, ready to decrease data! mode changed: RINGBUFFER_MODE_DROPPING"); + s_dac_cb.ringbuffer_mode = RINGBUFFER_MODE_DROPPING; + } + + if (s_dac_cb.ringbuffer_mode == RINGBUFFER_MODE_PREFETCHING) { + vRingbufferGetInfo(s_dac_cb.ringbuf, NULL, NULL, NULL, NULL, &item_size); + if (item_size >= RINGBUF_PREFETCH_WATER_LEVEL) { + ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer data increased! mode changed: RINGBUFFER_MODE_PROCESSING"); + s_dac_cb.ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; + if (pdFALSE == xSemaphoreGive(s_dac_cb.write_semaphore)) { + ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "semaphore give failed"); + } + } + } + + return done ? size : 0; +} + +#endif /* defined(CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC) */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_i2s.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_i2s.c new file mode 100644 index 0000000000..dc53afe2b1 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_i2s.c @@ -0,0 +1,236 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "esp_log.h" +#include "esp_a2dp_api.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "freertos/ringbuf.h" +#include "driver/i2s_std.h" +#include "audio_sink_service.h" + +#if defined(CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S) + +/* log tag */ +#define AUDIO_SNK_SRV_I2S_TAG "SNK_SRV_I2S" + +typedef struct { + i2s_chan_handle_t tx_chan; /* handle of i2s channel */ + audio_sink_chan_st_t chan_st; /* i2s channel status */ + TaskHandle_t write_task_handle; /* handle of writing task */ + RingbufHandle_t ringbuf; /* handle of ringbuffer */ + SemaphoreHandle_t write_semaphore;/* handle of write semaphore */ + uint16_t ringbuffer_mode; /* ringbuffer mode */ +} audio_sink_srv_i2s_cb_t; + +/******************************* + * STATIC FUNCTION DECLARATIONS + ******************************/ + +/* task handler for writing data to i2s */ +static void audio_sink_srv_i2s_task_handler(void *arg); + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* audio sink service for i2s control block */ +static audio_sink_srv_i2s_cb_t s_i2s_cb; + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static void audio_sink_srv_i2s_task_handler(void *arg) +{ + uint8_t *data = NULL; + size_t item_size = 0; + /** + * The total length of DMA buffer of I2S is: + * `dma_frame_num * dma_desc_num * i2s_channel_num * i2s_data_bit_width / 8`. + * Transmit `dma_frame_num * dma_desc_num` bytes to DMA is trade-off. + */ + const size_t item_size_upto = 240 * 6; + size_t bytes_written = 0; + + for (;;) { + if (pdTRUE == xSemaphoreTake(s_i2s_cb.write_semaphore, portMAX_DELAY)) { + for (;;) { + item_size = 0; + /* receive data from ringbuffer and write it to I2S DMA transmit buffer */ + data = (uint8_t *)xRingbufferReceiveUpTo(s_i2s_cb.ringbuf, &item_size, (TickType_t)pdMS_TO_TICKS(20), item_size_upto); + if (item_size == 0) { + ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer underflowed! mode changed: RINGBUFFER_MODE_PREFETCHING"); + s_i2s_cb.ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; + break; + } + + i2s_channel_write(s_i2s_cb.tx_chan, data, item_size, &bytes_written, portMAX_DELAY); + vRingbufferReturnItem(s_i2s_cb.ringbuf, (void *)data); + } + } + } +} + +/******************************* + * EXTERNAL FUNCTION DEFINITIONS + ******************************/ + +void audio_sink_srv_open(void) +{ + memset(&s_i2s_cb, 0, sizeof(audio_sink_srv_i2s_cb_t)); + i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); + chan_cfg.auto_clear = true; + i2s_std_config_t std_cfg = { + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100), + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = CONFIG_EXAMPLE_I2S_BCK_PIN, + .ws = CONFIG_EXAMPLE_I2S_LRCK_PIN, + .dout = CONFIG_EXAMPLE_I2S_DATA_PIN, + .din = I2S_GPIO_UNUSED, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + /* initialize I2S channel */ + ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &s_i2s_cb.tx_chan, NULL)); + ESP_ERROR_CHECK(i2s_channel_init_std_mode(s_i2s_cb.tx_chan, &std_cfg)); + s_i2s_cb.chan_st = CHANNEL_STATUS_OPENED; +} + +void audio_sink_srv_close(void) +{ + audio_sink_srv_stop(); + + if (s_i2s_cb.chan_st == CHANNEL_STATUS_OPENED) { + ESP_ERROR_CHECK(i2s_del_channel(s_i2s_cb.tx_chan)); + s_i2s_cb.chan_st = CHANNEL_STATUS_IDLE; + } + if (s_i2s_cb.write_task_handle) { + vTaskDelete(s_i2s_cb.write_task_handle); + s_i2s_cb.write_task_handle = NULL; + } + if (s_i2s_cb.ringbuf) { + vRingbufferDelete(s_i2s_cb.ringbuf); + s_i2s_cb.ringbuf = NULL; + } + if (s_i2s_cb.write_semaphore) { + vSemaphoreDelete(s_i2s_cb.write_semaphore); + s_i2s_cb.write_semaphore = NULL; + } + memset(&s_i2s_cb, 0, sizeof(audio_sink_srv_i2s_cb_t)); +} + +void audio_sink_srv_start(void) +{ + if (s_i2s_cb.chan_st != CHANNEL_STATUS_OPENED) { + ESP_LOGE(AUDIO_SNK_SRV_I2S_TAG, "%s, TX channel wrong state: %d", __func__, s_i2s_cb.chan_st); + return; + } + ESP_ERROR_CHECK(i2s_channel_enable(s_i2s_cb.tx_chan)); + s_i2s_cb.chan_st = CHANNEL_STATUS_ENABLED; + + ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer data empty! mode changed: RINGBUFFER_MODE_PREFETCHING"); + s_i2s_cb.ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; + if ((s_i2s_cb.write_semaphore = xSemaphoreCreateBinary()) == NULL) { + ESP_LOGE(AUDIO_SNK_SRV_I2S_TAG, "%s, Semaphore create failed", __func__); + return; + } + if ((s_i2s_cb.ringbuf = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) { + ESP_LOGE(AUDIO_SNK_SRV_I2S_TAG, "%s, ringbuffer create failed", __func__); + return; + } + xTaskCreate(audio_sink_srv_i2s_task_handler, "BtI2STask", 4 * 1024, NULL, configMAX_PRIORITIES - 3, &s_i2s_cb.write_task_handle); +} + +void audio_sink_srv_stop(void) +{ + if (s_i2s_cb.chan_st == CHANNEL_STATUS_ENABLED) { + ESP_ERROR_CHECK(i2s_channel_disable(s_i2s_cb.tx_chan)); + s_i2s_cb.chan_st = CHANNEL_STATUS_OPENED; + } +} + +void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) +{ + ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "A2DP audio stream configuration, codec type: %d", mcc->type); + /* for now only SBC stream is supported */ + if (mcc->type == ESP_A2D_MCT_SBC) { + int sample_rate = 16000; + int ch_count = 2; + if (mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_32K) { + sample_rate = 32000; + } else if (mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_44K) { + sample_rate = 44100; + } else if (mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_48K) { + sample_rate = 48000; + } + + if (mcc->cie.sbc_info.ch_mode & ESP_A2D_SBC_CIE_CH_MODE_MONO) { + ch_count = 1; + } + i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(sample_rate); + i2s_std_slot_config_t slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, ch_count); + i2s_channel_reconfig_std_clock(s_i2s_cb.tx_chan, &clk_cfg); + i2s_channel_reconfig_std_slot(s_i2s_cb.tx_chan, &slot_cfg); + ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", + mcc->cie.sbc_info.samp_freq, + mcc->cie.sbc_info.ch_mode, + mcc->cie.sbc_info.block_len, + mcc->cie.sbc_info.num_subbands, + mcc->cie.sbc_info.alloc_mthd, + mcc->cie.sbc_info.min_bitpool, + mcc->cie.sbc_info.max_bitpool); + ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "Audio player configured, sample rate: %d", sample_rate); + } +} + +size_t audio_sink_srv_data_output(const uint8_t *data, size_t size) +{ + size_t item_size = 0; + BaseType_t done = pdFALSE; + + if (s_i2s_cb.ringbuffer_mode == RINGBUFFER_MODE_DROPPING) { + ESP_LOGW(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer is full, drop this packet!"); + vRingbufferGetInfo(s_i2s_cb.ringbuf, NULL, NULL, NULL, NULL, &item_size); + if (item_size <= RINGBUF_PREFETCH_WATER_LEVEL) { + ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer data decreased! mode changed: RINGBUFFER_MODE_PROCESSING"); + s_i2s_cb.ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; + } + return 0; + } + + done = xRingbufferSend(s_i2s_cb.ringbuf, (void *)data, size, (TickType_t)0); + + if (!done) { + ESP_LOGW(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer overflowed, ready to decrease data! mode changed: RINGBUFFER_MODE_DROPPING"); + s_i2s_cb.ringbuffer_mode = RINGBUFFER_MODE_DROPPING; + } + + if (s_i2s_cb.ringbuffer_mode == RINGBUFFER_MODE_PREFETCHING) { + vRingbufferGetInfo(s_i2s_cb.ringbuf, NULL, NULL, NULL, NULL, &item_size); + if (item_size >= RINGBUF_PREFETCH_WATER_LEVEL) { + ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer data increased! mode changed: RINGBUFFER_MODE_PROCESSING"); + s_i2s_cb.ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; + if (pdFALSE == xSemaphoreGive(s_i2s_cb.write_semaphore)) { + ESP_LOGE(AUDIO_SNK_SRV_I2S_TAG, "semaphore give failed"); + } + } + } + + return done ? size : 0; +} + +#endif /* defined(CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_EXTERNAL_I2S) */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_idle.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_idle.c new file mode 100644 index 0000000000..85a1526c28 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_idle.c @@ -0,0 +1,49 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "audio_sink_service.h" + +#if defined(CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_IDLE) + +/******************************* + * EXTERNAL FUNCTION DEFINITIONS + ******************************/ + +void audio_sink_srv_open(void) +{ + // do nothing +} + +void audio_sink_srv_close(void) +{ + // do nothing +} + +void audio_sink_srv_start(void) +{ + // do nothing +} + +void audio_sink_srv_stop(void) +{ + // do nothing +} + +void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) +{ + // do nothing + (void)mcc; +} + +size_t audio_sink_srv_data_output(const uint8_t *data, size_t size) +{ + // do nothing + (void)data; + (void)size; + return 0; +} + +#endif /* defined(CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_IDLE) */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/include/a2dp_utils_tags.h b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/include/a2dp_utils_tags.h new file mode 100644 index 0000000000..6ab3d8e6c4 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/include/a2dp_utils_tags.h @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __A2DP_UTILS_TAGS_H__ +#define __A2DP_UTILS_TAGS_H__ + +/* log tags */ +#define BT_AV_TAG "BT_AV" + +#endif /* __A2DP_UTILS_TAGS_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/CMakeLists.txt new file mode 100644 index 0000000000..8c16db1f68 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "avrcp_abs_vol_utils.c" + "avrcp_abs_vol_service.c" + PRIV_REQUIRES bt + INCLUDE_DIRS "." "../include") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.c new file mode 100644 index 0000000000..889b265111 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.c @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include "sys/lock.h" +#include "esp_log.h" +#include "esp_avrc_api.h" +#include "avrcp_abs_vol_service.h" + +/* tags */ +#define RC_VC_SRV_TAG "RC_VC_SRV" + +typedef struct { + _lock_t volume_lock; /* lock local volume value */ + uint8_t volume; /* local volume value */ + bool volume_notify; /* notify volume change or not */ +} avrc_abs_vol_srv_cb_t; + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* AVRCP absolute volume service control block */ +static avrc_abs_vol_srv_cb_t s_avrc_abs_vol_srv_cb; + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void avrc_abs_vol_srv_open(void) +{ + memset(&s_avrc_abs_vol_srv_cb, 0, sizeof(avrc_abs_vol_srv_cb_t)); +} + +void avrc_abs_vol_srv_close(void) +{ + memset(&s_avrc_abs_vol_srv_cb, 0, sizeof(avrc_abs_vol_srv_cb_t)); +} + +uint8_t avrc_abs_vol_srv_get_volume(void) +{ + return s_avrc_abs_vol_srv_cb.volume; +} + +void avrc_abs_vol_srv_set_volume(avrc_volume_set_t vol_set_t, uint8_t volume) +{ + switch (vol_set_t) { + case VOLUME_SET_BY_CONTROLLER: { + ESP_LOGI(RC_VC_SRV_TAG, "Volume is set by remote controller to: %"PRIu32"%%", (uint32_t)volume * 100 / 0x7f); + /* set the volume in protection of lock */ + _lock_acquire(&s_avrc_abs_vol_srv_cb.volume_lock); + s_avrc_abs_vol_srv_cb.volume = volume; + _lock_release(&s_avrc_abs_vol_srv_cb.volume_lock); + break; + } + case VOLUME_SET_BY_LOCAL_HOST: { + ESP_LOGI(RC_VC_SRV_TAG, "Volume is set locally to: %"PRIu32"%%", (uint32_t)volume * 100 / 0x7f); + /* set the volume in protection of lock */ + _lock_acquire(&s_avrc_abs_vol_srv_cb.volume_lock); + s_avrc_abs_vol_srv_cb.volume = volume; + _lock_release(&s_avrc_abs_vol_srv_cb.volume_lock); + + /* send notification response to remote AVRCP controller */ + if (s_avrc_abs_vol_srv_cb.volume_notify) { + esp_avrc_rn_param_t rn_param; + rn_param.volume = s_avrc_abs_vol_srv_cb.volume; + esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_CHANGED, &rn_param); + s_avrc_abs_vol_srv_cb.volume_notify = false; + } + break; + } + default: + ESP_LOGE(RC_VC_SRV_TAG, "Invalid volume setting type"); + break; + } +} + +void avrc_abs_vol_srv_rn_volume_change(void) +{ + s_avrc_abs_vol_srv_cb.volume_notify = true; + esp_avrc_rn_param_t rn_param; + rn_param.volume = s_avrc_abs_vol_srv_cb.volume; + esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_INTERIM, &rn_param); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.h new file mode 100644 index 0000000000..d21c21ec58 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_ABS_VOL_SERVICE_H__ +#define __AVRCP_ABS_VOL_SERVICE_H__ + +#include +#include "esp_avrc_api.h" + +typedef enum { + VOLUME_SET_BY_CONTROLLER = 0, /*!< volume is set by controller */ + VOLUME_SET_BY_LOCAL_HOST, /*!< volume is set by local host */ +} avrc_volume_set_t; + +/** + * @brief open AVRCP absolute volume service + */ +void avrc_abs_vol_srv_open(void); + +/** + * @brief close AVRCP absolute volume service + */ +void avrc_abs_vol_srv_close(void); + +/** + * @brief get local volume value + * + * @return local volume value + */ +uint8_t avrc_abs_vol_srv_get_volume(void); + +/** + * @brief set volume value + * + * @param [in] vol_set_t volume setting type + * @param [in] volume volume value to be set + */ +void avrc_abs_vol_srv_set_volume(avrc_volume_set_t vol_set_t, uint8_t volume); + +/** + * @brief register notification of volume change + */ +void avrc_abs_vol_srv_rn_volume_change(void); + +#endif /* __AVRCP_ABS_VOL_SERVICE_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.c new file mode 100644 index 0000000000..0a41ae063a --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.c @@ -0,0 +1,103 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include + +#include "sys/lock.h" + +#include "esp_log.h" +#include "esp_avrc_api.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "avrcp_abs_vol_utils.h" +#include "avrcp_utils_tags.h" +#include "avrcp_abs_vol_service.h" + +/******************************* + * STATIC FUNCTION DECLARATIONS + ******************************/ + +/* simulation volume change */ +static void volume_change_simulation(void *arg); + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +static TaskHandle_t s_vcs_task_hdl = NULL; /* handle for volume change simulation task */ + +/******************************** + * STATIC FUNCTION DEFINITIONS + *******************************/ + +static void volume_change_simulation(void *arg) +{ + ESP_LOGI(BT_RC_TG_TAG, "start volume change simulation"); + + for (;;) { + /* volume up locally every 10 seconds */ + vTaskDelay(10000 / portTICK_PERIOD_MS); + uint8_t volume = (avrc_abs_vol_srv_get_volume() + 5) & 0x7f; + avrc_abs_vol_srv_set_volume(VOLUME_SET_BY_LOCAL_HOST, volume); + } +} + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void bt_avrc_avc_tg_evt_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_RC_TG_TAG, "%s event: %d", __func__, event); + + esp_avrc_tg_cb_param_t *rc = (esp_avrc_tg_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_AVRC_TG_CONNECTION_STATE_EVT: { + uint8_t *bda = rc->conn_stat.remote_bda; + ESP_LOGI(BT_RC_TG_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", + rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + if (rc->conn_stat.connected) { + /* create task to simulate volume change */ + avrc_abs_vol_srv_open(); + xTaskCreate(volume_change_simulation, "vcsTask", 4 * 1024, NULL, 5, &s_vcs_task_hdl); + } else { + avrc_abs_vol_srv_close(); + if (s_vcs_task_hdl) { + vTaskDelete(s_vcs_task_hdl); + s_vcs_task_hdl = NULL; + } + ESP_LOGI(BT_RC_TG_TAG, "Stop volume change simulation"); + } + break; + } + /* when absolute volume command from remote device set, this event comes */ + case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: { + ESP_LOGI(BT_RC_TG_TAG, "AVRC set absolute volume: %d%%", (int)rc->set_abs_vol.volume * 100 / 0x7f); + avrc_abs_vol_srv_set_volume(VOLUME_SET_BY_CONTROLLER, rc->set_abs_vol.volume); + break; + } + /* when notification registered, this event comes */ + case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { + ESP_LOGI(BT_RC_TG_TAG, "AVRC register event notification: %d, param: 0x%"PRIx32, rc->reg_ntf.event_id, rc->reg_ntf.event_parameter); + if (rc->reg_ntf.event_id == ESP_AVRC_RN_VOLUME_CHANGE) { + avrc_abs_vol_srv_rn_volume_change(); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_RC_TG_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.h new file mode 100644 index 0000000000..c10594049c --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_ABS_VOL_UTILS_H__ +#define __AVRCP_ABS_VOL_UTILS_H__ + +#include + +/** + * @brief handle function for AVRCP target absolute volume control event + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_avrc_avc_tg_evt_hdl(uint16_t event, void *param); + +#endif /* __AVRCP_ABS_VOL_UTILS_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/CMakeLists.txt new file mode 100644 index 0000000000..6d95f6fac3 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "avrcp_common_utils.c" + PRIV_REQUIRES bt + INCLUDE_DIRS "." "../include") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.c new file mode 100644 index 0000000000..6f3ae6801e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.c @@ -0,0 +1,228 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_bt_main.h" +#include "esp_avrc_api.h" + +#include "avrcp_common_utils.h" +#include "avrcp_utils_tags.h" + +typedef struct { + uint8_t tl; /* AVRCP transaction labels */ + esp_avrc_rn_evt_cap_mask_t peer_rn_cap; /* AVRCP target notification capability bit mask */ +} avrc_common_cb_t; + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +static avrc_common_cb_t s_avrc_common_cb; + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void bt_avrc_common_ct_evt_def_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event); + + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_AVRC_CT_CONNECTION_STATE_EVT: { + uint8_t *bda = rc->conn_stat.remote_bda; + ESP_LOGI(BT_RC_CT_TAG, "AVRC conn_state event: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", + rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + break; + } + /* when passthrough response, this event comes */ + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC passthrough rsp: key_code 0x%x, key_state %d, rsp_code %d", rc->psth_rsp.key_code, + rc->psth_rsp.key_state, rc->psth_rsp.rsp_code); + break; + } + /* when metadata response, this event comes */ + case ESP_AVRC_CT_METADATA_RSP_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + break; + } + /* when notified, this event comes */ + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id); + break; + } + /* when feature of remote device indicated, this event comes */ + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC remote features %"PRIx32", TG features %x", rc->rmt_feats.feat_mask, rc->rmt_feats.tg_feat_flag); + break; + } + /* when notification capability of peer device got, this event comes */ + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, + rc->get_rn_caps_rsp.evt_set.bits); + break; + } + /* when avrcp controller init or deinit completed, this event comes */ + case ESP_AVRC_CT_PROF_STATE_EVT: { + if (ESP_AVRC_INIT_SUCCESS == rc->avrc_ct_init_stat.state) { + ESP_LOGI(BT_RC_CT_TAG, "AVRCP CT STATE: Init Complete"); + } else if (ESP_AVRC_DEINIT_SUCCESS == rc->avrc_ct_init_stat.state) { + ESP_LOGI(BT_RC_CT_TAG, "AVRCP CT STATE: Deinit Complete"); + } else { + ESP_LOGE(BT_RC_CT_TAG, "AVRCP CT STATE error: %d", rc->avrc_ct_init_stat.state); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_RC_CT_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +void bt_avrc_common_tg_evt_def_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_RC_TG_TAG, "%s event: %d", __func__, event); + + esp_avrc_tg_cb_param_t *rc = (esp_avrc_tg_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_AVRC_TG_CONNECTION_STATE_EVT: { + uint8_t *bda = rc->conn_stat.remote_bda; + ESP_LOGI(BT_RC_TG_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", + rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + break; + } + /* when passthrough commanded, this event comes */ + case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: { + ESP_LOGI(BT_RC_TG_TAG, "AVRC passthrough cmd: key_code 0x%x, key_state %d", rc->psth_cmd.key_code, rc->psth_cmd.key_state); + break; + } + /* when absolute volume command from remote device set, this event comes */ + case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: { + ESP_LOGI(BT_RC_TG_TAG, "AVRC set absolute volume: %d%%", (int)rc->set_abs_vol.volume * 100 / 0x7f); + break; + } + /* when notification registered, this event comes */ + case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { + ESP_LOGI(BT_RC_TG_TAG, "AVRC register event notification: %d, param: 0x%"PRIx32, rc->reg_ntf.event_id, rc->reg_ntf.event_parameter); + break; + } + /* when feature of remote device indicated, this event comes */ + case ESP_AVRC_TG_REMOTE_FEATURES_EVT: { + ESP_LOGI(BT_RC_TG_TAG, "AVRC remote features: %"PRIx32", CT features: %x", rc->rmt_feats.feat_mask, rc->rmt_feats.ct_feat_flag); + break; + } + /* when avrcp target init or deinit completed, this event comes */ + case ESP_AVRC_TG_PROF_STATE_EVT: { + if (ESP_AVRC_INIT_SUCCESS == rc->avrc_tg_init_stat.state) { + ESP_LOGI(BT_RC_TG_TAG, "AVRCP TG STATE: Init Complete"); + } else if (ESP_AVRC_DEINIT_SUCCESS == rc->avrc_tg_init_stat.state) { + ESP_LOGI(BT_RC_TG_TAG, "AVRCP TG STATE: Deinit Complete"); + } else { + ESP_LOGE(BT_RC_TG_TAG, "AVRCP TG STATE error: %d", rc->avrc_tg_init_stat.state); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_RC_TG_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + +uint8_t bt_avrc_common_alloc_tl(void) +{ + if (s_avrc_common_cb.tl > ESP_AVRC_TRANS_LABEL_MAX) { + s_avrc_common_cb.tl = 0; + } + + return s_avrc_common_cb.tl++; +} + +void bt_avrc_common_copy_metadata(void *p_dest, void *p_src, int len) +{ + esp_avrc_ct_cb_param_t *p_dest_rc = (esp_avrc_ct_cb_param_t *)(p_dest); + esp_avrc_ct_cb_param_t *p_src_rc = (esp_avrc_ct_cb_param_t *)(p_src); + + p_dest_rc->meta_rsp.attr_id = p_src_rc->meta_rsp.attr_id; + p_dest_rc->meta_rsp.attr_length = p_src_rc->meta_rsp.attr_length; + + p_dest_rc->meta_rsp.attr_text = (uint8_t *) malloc(p_dest_rc->meta_rsp.attr_length + 1); + memcpy(p_dest_rc->meta_rsp.attr_text, p_src_rc->meta_rsp.attr_text, p_dest_rc->meta_rsp.attr_length); + p_dest_rc->meta_rsp.attr_text[p_dest_rc->meta_rsp.attr_length] = 0; +} + +void bt_avrc_common_ct_get_peer_rn_cap(void) +{ + esp_avrc_ct_send_get_rn_capabilities_cmd(bt_avrc_common_alloc_tl()); +} + +void bt_avrc_common_ct_set_peer_rn_cap(uint16_t peer_rn_cap_t) +{ + s_avrc_common_cb.peer_rn_cap.bits = peer_rn_cap_t; +} + +void bt_avrc_common_ct_rn_track_changed(void) +{ + /* register notification if peer support the event_id */ + if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_common_cb.peer_rn_cap, + ESP_AVRC_RN_TRACK_CHANGE)) { + esp_avrc_ct_send_register_notification_cmd(bt_avrc_common_alloc_tl(), ESP_AVRC_RN_TRACK_CHANGE, 0); + } +} + +void bt_avrc_common_ct_rn_play_status_changed(void) +{ + /* register notification if peer support the event_id */ + if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_common_cb.peer_rn_cap, + ESP_AVRC_RN_PLAY_STATUS_CHANGE)) { + esp_avrc_ct_send_register_notification_cmd(bt_avrc_common_alloc_tl(), ESP_AVRC_RN_PLAY_STATUS_CHANGE, 0); + } +} + +void bt_avrc_common_ct_rn_play_pos_changed(void) +{ + /* register notification if peer support the event_id */ + if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_common_cb.peer_rn_cap, + ESP_AVRC_RN_PLAY_POS_CHANGED)) { + esp_avrc_ct_send_register_notification_cmd(bt_avrc_common_alloc_tl(), ESP_AVRC_RN_PLAY_POS_CHANGED, 10); + } +} + +void bt_avrc_common_ct_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter) +{ + switch (event_id) { + /* when new track is loaded, this event comes */ + case ESP_AVRC_RN_TRACK_CHANGE: + ESP_LOGI(BT_RC_CT_TAG, "New track loaded"); + bt_avrc_common_ct_rn_track_changed(); + break; + /* when track status changed, this event comes */ + case ESP_AVRC_RN_PLAY_STATUS_CHANGE: + ESP_LOGI(BT_RC_CT_TAG, "Playback status changed: 0x%x", event_parameter->playback); + bt_avrc_common_ct_rn_play_status_changed(); + break; + /* when track playing position changed, this event comes */ + case ESP_AVRC_RN_PLAY_POS_CHANGED: + ESP_LOGI(BT_RC_CT_TAG, "Play position changed: %"PRIu32"-ms", event_parameter->play_pos); + bt_avrc_common_ct_rn_play_pos_changed(); + break; + /* others */ + default: + ESP_LOGI(BT_RC_CT_TAG, "unhandled event: %d", event_id); + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.h new file mode 100644 index 0000000000..e7d4c00fb8 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.h @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_COMMON_UTILS_H__ +#define __AVRCP_COMMON_UTILS_H__ + +#include +#include "esp_avrc_api.h" + +/** + * @brief default handle function for AVRCP controller event + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_avrc_common_ct_evt_def_hdl(uint16_t event, void *param); + +/** + * @brief default handle function for AVRCP target event + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_avrc_common_tg_evt_def_hdl(uint16_t event, void *param); + +/** + * @brief AVRCP transaction labels allocation + * + * @param [out] tl transaction label + * + * @return transaction label + */ +uint8_t bt_avrc_common_alloc_tl(void); + +/** + * @brief AVRCP deep copy function + * + * @param [in] p_dest pointer to destination data + * @param [in] p_src pointer to source data + * @param [in] len data length in byte + */ +void bt_avrc_common_copy_metadata(void *p_dest, void *p_src, int len); + +/** + * @brief AVRCP controller get notification capabilities command + */ +void bt_avrc_common_ct_get_peer_rn_cap(void); + +/** + * @brief AVRCP controller set notification capabilities command + * + * @param [in] peer_rn_cap_t register notification capabilities of peer in bits + */ +void bt_avrc_common_ct_set_peer_rn_cap(uint16_t peer_rn_cap_t); + +/** + * @brief AVRCP controller track changed notification command + */ +void bt_avrc_common_ct_rn_track_changed(void); + +/** + * @brief AVRCP controller play status changed notification command + */ +void bt_avrc_common_ct_rn_play_status_changed(void); + +/** + * @brief AVRCP controller play position changed notification command + */ +void bt_avrc_common_ct_rn_play_pos_changed(void); + +/** + * @brief AVRCP controller notification event handler + * + * @param [in] event_id event id + * @param [in] event_parameter event parameter + */ +void bt_avrc_common_ct_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter); + +#endif /* __AVRCP_COMMON_UTILS_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/CMakeLists.txt new file mode 100644 index 0000000000..bcd7cd6879 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "avrcp_cover_art_utils.c" + "avrcp_cover_art_service.c" + PRIV_REQUIRES bt esp_lcd avrcp_common_utils + INCLUDE_DIRS "." "../include") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/Kconfig.projbuild new file mode 100644 index 0000000000..78035b2618 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/Kconfig.projbuild @@ -0,0 +1,8 @@ +menu "AVRCP Cover Art Example Configuration" + config EXAMPLE_LCD_FLUSH_PARALLEL_LINES + int "LCD flush parallel lines" + default 16 + help + To speed up transfers, every SPI transfer sends a bunch of lines. + +endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c new file mode 100644 index 0000000000..bd837329f6 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c @@ -0,0 +1,347 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "driver/spi_master.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_vendor.h" +#include "esp_lcd_panel_ops.h" +#include "jpeg_decoder.h" +#include "avrcp_common_utils.h" +#include "avrcp_cover_art_service.h" + +/* tags*/ +#define RC_CA_SRV_TAG "RC_CA_SRV" + +//Define the height and width of the jpeg file. Make sure this matches the actual jpeg +//dimensions. +#define IMAGE_W 200 +#define IMAGE_H 200 + +// Using SPI2 in the example, as it also supports octal modes on some targets +#define LCD_HOST SPI2_HOST +// To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. +// More means more memory use, but less overhead for setting up / finishing transfers. Make sure 240 +// is dividable by this. +#define PARALLEL_LINES CONFIG_EXAMPLE_LCD_FLUSH_PARALLEL_LINES + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// Please update the following configuration according to your LCD spec ////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) +#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 0 +#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL +#define EXAMPLE_PIN_NUM_DATA0 23 /*!< for 1-line SPI, this also referred as MOSI */ +#define EXAMPLE_PIN_NUM_PCLK 19 +#define EXAMPLE_PIN_NUM_CS 22 +#define EXAMPLE_PIN_NUM_DC 21 +#define EXAMPLE_PIN_NUM_RST 18 +#define EXAMPLE_PIN_NUM_BK_LIGHT 5 + +// The pixel number in horizontal and vertical +#define EXAMPLE_LCD_H_RES 200 +#define EXAMPLE_LCD_V_RES 200 +// Bit number used to represent command and parameter +#define EXAMPLE_LCD_CMD_BITS 8 +#define EXAMPLE_LCD_PARAM_BITS 8 + +/** + * @brief AVRCP cover art service control block structure + */ +typedef struct { + bool connected; /* Connection status flag */ + bool getting; /* Flag indicating if image is being retrieved */ + /* Related to the image */ + uint8_t image_hdl_old[7]; /* Previous image handle, used to detect image changes */ + uint32_t image_size; /* Size of the image data in bytes */ + uint8_t *image_data; /* Pointer to the image data buffer */ + bool image_final; /* Indicate whether the image reception has been completed */ + uint16_t *pixels; /* Pointer to decoded pixel data */ + esp_lcd_panel_io_handle_t io_handle; /* LCD panel IO handle */ + esp_lcd_panel_handle_t panel_handle; /* LCD panel handle */ +} avrc_cover_art_srv_cb_t; + +/******************************* + * STATIC FUNCTION DECLARATIONS + ******************************/ + +/* image handle check */ +static bool avrc_cover_art_srv_image_handle_check(uint8_t *image_handle, int len); +/* free image data */ +static void avrc_cover_art_srv_free_image_data(void); +/* initialize display (currently supports LCD only) */ +static void avrc_cover_art_srv_init_display(void); +/* deinitialize display (currently supports LCD only) */ +static void avrc_cover_art_srv_deinit_display(void); +/* free pixels */ +static void avrc_cover_art_srv_free_pixels(void); +/* decode image */ +static esp_err_t avrc_cover_art_srv_decode_image(void); +/* display image */ +static void avrc_cover_art_srv_display_image(void); + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* avrcp cover art service control block */ +static avrc_cover_art_srv_cb_t s_avrc_cover_art_srv_cb; + +/******************************** + * STATIC FUNCTION DEFINITIONS + *******************************/ + +static bool avrc_cover_art_srv_image_handle_check(uint8_t *image_handle, int len) +{ + /* Image handle length must be 7 */ + if (len == 7 && memcmp(s_avrc_cover_art_srv_cb.image_hdl_old, image_handle, 7) != 0) { + memcpy(s_avrc_cover_art_srv_cb.image_hdl_old, image_handle, 7); + return true; + } + return false; +} + +static void avrc_cover_art_srv_free_image_data(void) +{ + if (s_avrc_cover_art_srv_cb.image_data) { + free(s_avrc_cover_art_srv_cb.image_data); + s_avrc_cover_art_srv_cb.image_data = NULL; + } + s_avrc_cover_art_srv_cb.image_size = 0; +} + +static void avrc_cover_art_srv_init_display(void) +{ + gpio_config_t bk_gpio_config = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT + }; + /* Initialize the GPIO of backlight */ + ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); + + spi_bus_config_t buscfg = { + .sclk_io_num = EXAMPLE_PIN_NUM_PCLK, + .mosi_io_num = EXAMPLE_PIN_NUM_DATA0, + .miso_io_num = -1, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = PARALLEL_LINES * EXAMPLE_LCD_H_RES * 2 + 8 + }; + /* Initialize the SPI bus */ + ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO)); + + esp_lcd_panel_io_spi_config_t io_config = { + .dc_gpio_num = EXAMPLE_PIN_NUM_DC, + .cs_gpio_num = EXAMPLE_PIN_NUM_CS, + .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, + .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS, + .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS, + .spi_mode = 0, + .trans_queue_depth = 10, + }; + /* Attach the LCD to the SPI bus */ + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &s_avrc_cover_art_srv_cb.io_handle)); + + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = EXAMPLE_PIN_NUM_RST, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = 16, + }; + /* Initialize the LCD configuration */ + ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(s_avrc_cover_art_srv_cb.io_handle, &panel_config, &s_avrc_cover_art_srv_cb.panel_handle)); + + /* Turn off backlight to avoid unpredictable display on the LCD screen while initializing + * the LCD panel driver. (Different LCD screens may need different levels) */ + ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL)); + + /* Reset the display */ + ESP_ERROR_CHECK(esp_lcd_panel_reset(s_avrc_cover_art_srv_cb.panel_handle)); + + /* Initialize LCD panel */ + ESP_ERROR_CHECK(esp_lcd_panel_init(s_avrc_cover_art_srv_cb.panel_handle)); + + /* Turn on the screen */ + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(s_avrc_cover_art_srv_cb.panel_handle, true)); + ESP_ERROR_CHECK(esp_lcd_panel_invert_color(s_avrc_cover_art_srv_cb.panel_handle, true)); + + /* Swap x and y axis (Different LCD screens may need different options) */ + ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(s_avrc_cover_art_srv_cb.panel_handle, true)); + + /* Turn on backlight (Different LCD screens may need different levels) */ + ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL)); +} + +static void avrc_cover_art_srv_deinit_display(void) +{ + /* Turn off backlight first */ + ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL)); + + /* Turn off the display */ + if (s_avrc_cover_art_srv_cb.panel_handle) { + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(s_avrc_cover_art_srv_cb.panel_handle, false)); + /* Delete the LCD panel */ + ESP_ERROR_CHECK(esp_lcd_panel_del(s_avrc_cover_art_srv_cb.panel_handle)); + s_avrc_cover_art_srv_cb.panel_handle = NULL; + } + + /* Delete the LCD panel IO */ + if (s_avrc_cover_art_srv_cb.io_handle) { + ESP_ERROR_CHECK(esp_lcd_panel_io_del(s_avrc_cover_art_srv_cb.io_handle)); + s_avrc_cover_art_srv_cb.io_handle = NULL; + } + + /* Free the SPI bus */ + ESP_ERROR_CHECK(spi_bus_free(LCD_HOST)); + + /* Reset backlight GPIO */ + ESP_ERROR_CHECK(gpio_reset_pin(EXAMPLE_PIN_NUM_BK_LIGHT)); +} + +static void avrc_cover_art_srv_free_pixels(void) +{ + if (s_avrc_cover_art_srv_cb.pixels) { + free(s_avrc_cover_art_srv_cb.pixels); + s_avrc_cover_art_srv_cb.pixels = NULL; + } +} + +static esp_err_t avrc_cover_art_srv_decode_image(void) +{ + esp_err_t ret = ESP_OK; + + avrc_cover_art_srv_free_pixels(); + + /* Allocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `s_avrc_cover_art_srv_cb.pixels` array itself contains pointers to these lines. */ + s_avrc_cover_art_srv_cb.pixels = calloc(IMAGE_H * IMAGE_W, sizeof(uint16_t)); + + ESP_GOTO_ON_FALSE(s_avrc_cover_art_srv_cb.pixels, ESP_ERR_NO_MEM, err, RC_CA_SRV_TAG, "Error allocating memory for lines"); + + /* JPEG decode config */ + esp_jpeg_image_cfg_t jpeg_cfg = { + .indata = (uint8_t *)s_avrc_cover_art_srv_cb.image_data, + .indata_size = s_avrc_cover_art_srv_cb.image_size, + .outbuf = (uint8_t*)(s_avrc_cover_art_srv_cb.pixels), + .outbuf_size = IMAGE_W * IMAGE_H * sizeof(uint16_t), + .out_format = JPEG_IMAGE_FORMAT_RGB565, + .out_scale = JPEG_IMAGE_SCALE_0, + .flags = { + .swap_color_bytes = 1, + } + }; + + /* JPEG decode */ + esp_jpeg_image_output_t outimg; + ret = esp_jpeg_decode(&jpeg_cfg, &outimg); + + ESP_LOGI(RC_CA_SRV_TAG, "JPEG image decoded! Size of the decoded image is: %dpx x %dpx.", outimg.width, outimg.height); + + return ret; +err: + /* Something went wrong! Exit cleanly, de-allocating everything we allocated. */ + avrc_cover_art_srv_free_pixels(); + return ret; +} + +static void avrc_cover_art_srv_display_image(void) +{ + if (s_avrc_cover_art_srv_cb.panel_handle && s_avrc_cover_art_srv_cb.pixels) { + esp_lcd_panel_draw_bitmap(s_avrc_cover_art_srv_cb.panel_handle, 0, 0, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, s_avrc_cover_art_srv_cb.pixels); + } +} + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void avrc_cover_art_srv_open(void) +{ + memset(&s_avrc_cover_art_srv_cb, 0, sizeof(avrc_cover_art_srv_cb_t)); + /* initialize the display */ + avrc_cover_art_srv_init_display(); +} + +void avrc_cover_art_srv_close(void) +{ + /* deinitialize the display */ + avrc_cover_art_srv_deinit_display(); + + avrc_cover_art_srv_free_image_data(); + avrc_cover_art_srv_free_pixels(); + + memset(&s_avrc_cover_art_srv_cb, 0, sizeof(avrc_cover_art_srv_cb_t)); +} + +void avrc_cover_art_srv_connect(uint16_t mtu) +{ + if (!s_avrc_cover_art_srv_cb.connected) { + ESP_LOGW(RC_CA_SRV_TAG, "Start cover art connection..."); + /* start the cover art connection */ + esp_avrc_ct_cover_art_connect(mtu); + } +} + +void avrc_cover_art_srv_set_image_final(bool final) +{ + s_avrc_cover_art_srv_cb.image_final = final; + if (s_avrc_cover_art_srv_cb.image_final) { + ESP_LOGI(RC_CA_SRV_TAG, "Cover Art Client final data event, image size: %lu bytes", s_avrc_cover_art_srv_cb.image_size); + + /* decode and display the image */ + avrc_cover_art_srv_decode_image(); + /* display the image */ + avrc_cover_art_srv_display_image(); + /* set the getting state to false, we can get next image now */ + s_avrc_cover_art_srv_cb.getting = false; + } +} + +void avrc_cover_art_srv_set_connected(bool connected) +{ + s_avrc_cover_art_srv_cb.connected = connected; +} + +void avrc_cover_art_srv_ca_req(void) +{ + /* request cover art */ + if (s_avrc_cover_art_srv_cb.connected) { + uint8_t attr_mask = ESP_AVRC_MD_ATTR_COVER_ART; + + esp_avrc_ct_send_metadata_cmd(bt_avrc_common_alloc_tl(), attr_mask); + } +} + +void avrc_cover_art_srv_save_image_data(uint8_t *p_data, uint16_t data_len) +{ + s_avrc_cover_art_srv_cb.image_size += data_len; + + uint8_t *p_buf = (uint8_t *)realloc(s_avrc_cover_art_srv_cb.image_data, s_avrc_cover_art_srv_cb.image_size * sizeof(uint8_t)); + if (!p_buf) { + ESP_LOGE(RC_CA_SRV_TAG, "%s: The memory allocation of Cover art image data failed", __func__); + avrc_cover_art_srv_free_image_data(); + return; + } + s_avrc_cover_art_srv_cb.image_data = p_buf; + memcpy(s_avrc_cover_art_srv_cb.image_data + s_avrc_cover_art_srv_cb.image_size - data_len, p_data, data_len); +} + +void avrc_cover_art_srv_ct_metadata_update(uint8_t *image_handle, int len) +{ + if (s_avrc_cover_art_srv_cb.connected && !s_avrc_cover_art_srv_cb.getting) { + /* check image handle is valid and different with last one, we don't want to get an image repeatedly */ + if (avrc_cover_art_srv_image_handle_check(image_handle, len)) { + /* free the previous image data */ + avrc_cover_art_srv_free_image_data(); + /* get the linked thumbnail */ + esp_avrc_ct_cover_art_get_linked_thumbnail(image_handle); + s_avrc_cover_art_srv_cb.getting = true; + } + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.h new file mode 100644 index 0000000000..f92ca796ce --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_COVER_ART_SERVICE_H__ +#define __AVRCP_COVER_ART_SERVICE_H__ + +#include +#include "esp_avrc_api.h" +#include "esp_err.h" + +/** + * @brief open AVRCP cover art service + */ +void avrc_cover_art_srv_open(void); + +/** + * @brief close AVRCP cover art service + */ +void avrc_cover_art_srv_close(void); + +/** + * @brief start the cover art connection + * + * @param [in] mtu: maximum transmission unit + */ +void avrc_cover_art_srv_connect(uint16_t mtu); + +/** + * @brief set AVRCP cover art image final, and then if image final is true, display the image + * + * @param [in] final: true if image reception has been completed, false otherwise + */ +void avrc_cover_art_srv_set_image_final(bool final); + +/** + * @brief set AVRCP cover art connected + * + * @param [in] connected: true if connected, false otherwise + */ +void avrc_cover_art_srv_set_connected(bool connected); + +/** + * @brief request AVRCP cover art + */ +void avrc_cover_art_srv_ca_req(void); + +/** + * @brief save cover art data + * + * @param [in] p_data: pointer to the cover art data + * @param [in] data_len: length of the cover art data + */ +void avrc_cover_art_srv_save_image_data(uint8_t *p_data, uint16_t data_len); + +/** + * @brief handle the cover art update when metadata response + * + * @param [in] image_handle: pointer to the image handle + * @param [in] len: length of the image handle + */ +void avrc_cover_art_srv_ct_metadata_update(uint8_t *image_handle, int len); + +#endif /* __AVRCP_COVER_ART_SERVICE_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.c new file mode 100644 index 0000000000..1d9eeefaf8 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.c @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_avrc_api.h" +#include "avrcp_utils_tags.h" +#include "avrcp_cover_art_service.h" + +void bt_avrc_ca_ct_evt_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event); + + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_AVRC_CT_CONNECTION_STATE_EVT: { + if (rc->conn_stat.connected) { + /* open the cover art service */ + avrc_cover_art_srv_open(); + } else { + /* close the cover art service */ + avrc_cover_art_srv_close(); + } + break; + } + /* when metadata response, this event comes */ + case ESP_AVRC_CT_METADATA_RSP_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_COVER_ART) { + avrc_cover_art_srv_ct_metadata_update(rc->meta_rsp.attr_text, rc->meta_rsp.attr_length); + } + break; + } + /* when notified, this event comes */ + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { + if (rc->change_ntf.event_id == ESP_AVRC_RN_TRACK_CHANGE) { + /* request the cover art */ + avrc_cover_art_srv_ca_req(); + } + break; + } + /* when feature of remote device indicated, this event comes */ + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC remote features %"PRIx32", TG features %x", rc->rmt_feats.feat_mask, rc->rmt_feats.tg_feat_flag); + if ((rc->rmt_feats.tg_feat_flag & ESP_AVRC_FEAT_FLAG_TG_COVER_ART)) { + ESP_LOGW(BT_RC_CT_TAG, "Peer support Cover Art feature"); + /* start the cover art connection */ + avrc_cover_art_srv_connect(ESP_AVRC_CA_MTU_MAX); + } + break; + } + /* when notification capability of peer device got, this event comes */ + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { + /* request the cover art */ + avrc_cover_art_srv_ca_req(); + break; + } + /* when the state of cover art changes, this event comes */ + case ESP_AVRC_CT_COVER_ART_STATE_EVT: { + if (rc->cover_art_state.state == ESP_AVRC_COVER_ART_CONNECTED) { + avrc_cover_art_srv_set_connected(true); + ESP_LOGW(BT_RC_CT_TAG, "Cover Art Client connected"); + /* request the cover art */ + avrc_cover_art_srv_ca_req(); + } else { + avrc_cover_art_srv_set_connected(false); + ESP_LOGW(BT_RC_CT_TAG, "Cover Art Client disconnected, reason:%d", rc->cover_art_state.reason); + } + break; + } + /* when obtaining the cover art image data, this event comes */ + case ESP_AVRC_CT_COVER_ART_DATA_EVT: { + /* when rc->cover_art_data.final is true, it means we have received the entire image */ + avrc_cover_art_srv_set_image_final(rc->cover_art_data.final); + break; + } + /* others */ + default: + ESP_LOGE(BT_RC_CT_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.h new file mode 100644 index 0000000000..88e9bcd747 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_COVER_ART_UTILS_H__ +#define __AVRCP_COVER_ART_UTILS_H__ + +#include + +/** + * @brief handle function for AVRCP controller cover art event + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_avrc_ca_ct_evt_hdl(uint16_t event, void *param); + +#endif /* __AVRCP_COVER_ART_UTILS_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/idf_component.yml b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/idf_component.yml new file mode 100644 index 0000000000..d5b8ca349a --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/idf_component.yml @@ -0,0 +1,5 @@ +dependencies: + idf: ">=4.4" + esp_jpeg: ">=1.0.2" + avrcp_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/CMakeLists.txt new file mode 100644 index 0000000000..896be16c5a --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "avrcp_metadata_utils.c" + "avrcp_metadata_service.c" + PRIV_REQUIRES bt avrcp_common_utils + INCLUDE_DIRS "." "../include") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.c new file mode 100644 index 0000000000..271311afb1 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.c @@ -0,0 +1,155 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include "esp_log.h" +#include "esp_avrc_api.h" +#include "avrcp_metadata_service.h" +#include "avrcp_common_utils.h" + +/* tags*/ +#define RC_MD_SRV_TAG "RC_MD_SRV" + +typedef struct { + /* AVRCP metadata response data from ESP_AVRC_CT_METADATA_RSP_EVT */ + avrc_metadata_srv_param_t attr_title; + avrc_metadata_srv_param_t attr_artist; + avrc_metadata_srv_param_t attr_album; + avrc_metadata_srv_param_t attr_genre; +} avrc_metadata_srv_cb_t; + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +/* AVRCP metadata service control block */ +static avrc_metadata_srv_cb_t s_avrc_metadata_srv_cb; + +/******************************** + * STATIC FUNCTION DEFINITIONS + *******************************/ + +static void avrc_metadata_srv_copy_metadata(avrc_metadata_srv_param_t *p_dest, avrc_metadata_srv_param_t *p_src) +{ + p_dest->attr_id = p_src->attr_id; + p_dest->attr_length = p_src->attr_length; + + if (p_dest->attr_text) { + free(p_dest->attr_text); + p_dest->attr_text = NULL; + } + + p_dest->attr_text = (uint8_t *)malloc(p_dest->attr_length + 1); + if (p_dest->attr_text == NULL) { + ESP_LOGE(RC_MD_SRV_TAG, "Memory allocation failed."); + return; + } + + memcpy(p_dest->attr_text, p_src->attr_text, p_dest->attr_length); + p_dest->attr_text[p_dest->attr_length] = 0; +} + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void avrc_metadata_srv_open(void) +{ + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_TITLE); + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_ARTIST); + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_ALBUM); + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_GENRE); + + memset(&s_avrc_metadata_srv_cb, 0, sizeof(avrc_metadata_srv_cb_t)); +} + +void avrc_metadata_srv_close(void) +{ + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_TITLE); + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_ARTIST); + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_ALBUM); + avrc_metadata_srv_md_free(ESP_AVRC_MD_ATTR_GENRE); + + memset(&s_avrc_metadata_srv_cb, 0, sizeof(avrc_metadata_srv_cb_t)); +} + +void avrc_metadata_srv_md_req(void) +{ + /* request metadata */ + uint8_t attr_mask = ESP_AVRC_MD_ATTR_TITLE | + ESP_AVRC_MD_ATTR_ARTIST | + ESP_AVRC_MD_ATTR_ALBUM | + ESP_AVRC_MD_ATTR_GENRE; + + /* send metadata request */ + esp_avrc_ct_send_metadata_cmd(bt_avrc_common_alloc_tl(), attr_mask); +} + +void avrc_metadata_srv_md_save(avrc_metadata_srv_param_t *param) +{ + avrc_metadata_srv_param_t *rc = param; + + switch (rc->attr_id) { + case ESP_AVRC_MD_ATTR_TITLE: { + avrc_metadata_srv_copy_metadata(&s_avrc_metadata_srv_cb.attr_title, rc); + break; + } + case ESP_AVRC_MD_ATTR_ARTIST: { + avrc_metadata_srv_copy_metadata(&s_avrc_metadata_srv_cb.attr_artist, rc); + break; + } + case ESP_AVRC_MD_ATTR_ALBUM: { + avrc_metadata_srv_copy_metadata(&s_avrc_metadata_srv_cb.attr_album, rc); + break; + } + case ESP_AVRC_MD_ATTR_GENRE: { + avrc_metadata_srv_copy_metadata(&s_avrc_metadata_srv_cb.attr_genre, rc); + break; + } + + default: + ESP_LOGW(RC_MD_SRV_TAG, "%s unhandled attr_id: %d", __func__, rc->attr_id); + break; + } +} + +void avrc_metadata_srv_md_free(uint8_t attr_id) +{ + switch (attr_id) { + case ESP_AVRC_MD_ATTR_TITLE: { + if (s_avrc_metadata_srv_cb.attr_title.attr_text) { + free(s_avrc_metadata_srv_cb.attr_title.attr_text); + s_avrc_metadata_srv_cb.attr_title.attr_text = NULL; + } + break; + } + case ESP_AVRC_MD_ATTR_ARTIST: { + if (s_avrc_metadata_srv_cb.attr_artist.attr_text) { + free(s_avrc_metadata_srv_cb.attr_artist.attr_text); + s_avrc_metadata_srv_cb.attr_artist.attr_text = NULL; + } + break; + } + case ESP_AVRC_MD_ATTR_ALBUM: { + if (s_avrc_metadata_srv_cb.attr_album.attr_text) { + free(s_avrc_metadata_srv_cb.attr_album.attr_text); + s_avrc_metadata_srv_cb.attr_album.attr_text = NULL; + } + break; + } + case ESP_AVRC_MD_ATTR_GENRE: { + if (s_avrc_metadata_srv_cb.attr_genre.attr_text) { + free(s_avrc_metadata_srv_cb.attr_genre.attr_text); + s_avrc_metadata_srv_cb.attr_genre.attr_text = NULL; + } + break; + } + + default: + ESP_LOGW(RC_MD_SRV_TAG, "%s unhandled attr_id: %d", __func__, attr_id); + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.h new file mode 100644 index 0000000000..e90319bf31 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_METADATA_SERVICE_H__ +#define __AVRCP_METADATA_SERVICE_H__ + +#include +#include "esp_avrc_api.h" + +typedef struct { + uint8_t attr_id; /*!< id of metadata attribute */ + uint8_t *attr_text; /*!< attribute itself */ + int attr_length; /*!< attribute character length */ +} avrc_metadata_srv_param_t; + +/** + * @brief open AVRCP metadata service + */ +void avrc_metadata_srv_open(void); + +/** + * @brief close AVRCP metadata service + */ +void avrc_metadata_srv_close(void); + +/** + * @brief request AVRCP metadata + */ +void avrc_metadata_srv_md_req(void); + +/** + * @brief save AVRCP metadata response data from ESP_AVRC_CT_METADATA_RSP_EVT + * + * @param [in] param AVRCP metadata response data + */ +void avrc_metadata_srv_md_save(avrc_metadata_srv_param_t *param); + +/** + * @brief free AVRCP metadata response data from ESP_AVRC_CT_METADATA_RSP_EVT + * + * @param [in] attr_id attribute id + */ +void avrc_metadata_srv_md_free(uint8_t attr_id); + +#endif /* __AVRCP_METADATA_SERVICE_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.c new file mode 100644 index 0000000000..5516db7d4e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.c @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_bt_main.h" +#include "esp_avrc_api.h" + +#include "avrcp_metadata_utils.h" +#include "avrcp_utils_tags.h" +#include "avrcp_metadata_service.h" + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +void bt_avrc_md_ct_evt_hdl(uint16_t event, void *param) +{ + ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event); + + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); + + switch (event) { + /* when connection state changed, this event comes */ + case ESP_AVRC_CT_CONNECTION_STATE_EVT: { + uint8_t *bda = rc->conn_stat.remote_bda; + ESP_LOGI(BT_RC_CT_TAG, "AVRC conn_state event: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", + rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + + if (rc->conn_stat.connected) { + /* get remote supported event_ids of peer AVRCP Target */ + avrc_metadata_srv_open(); + } else { + /* clear peer notification capability record */ + avrc_metadata_srv_close(); + } + break; + } + /* when metadata response, this event comes */ + case ESP_AVRC_CT_METADATA_RSP_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + /* save metadata to avrcp metadata service and then if there is a need to handle metadata, + functions can be added in the avrcp metadata service for processing */ + avrc_metadata_srv_md_save((avrc_metadata_srv_param_t *)rc); + break; + } + /* when notified, this event comes */ + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id); + if (rc->change_ntf.event_id == ESP_AVRC_RN_TRACK_CHANGE) { + /* request metadata */ + avrc_metadata_srv_md_req(); + } + break; + } + /* when notification capability of peer device got, this event comes */ + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { + ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, + rc->get_rn_caps_rsp.evt_set.bits); + /* request metadata */ + avrc_metadata_srv_md_req(); + break; + } + /* others */ + default: + ESP_LOGE(BT_RC_CT_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.h new file mode 100644 index 0000000000..0d979b8b18 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_METADATA_UTILS_H__ +#define __AVRCP_METADATA_UTILS_H__ + +#include + +/** + * @brief handle function for AVRCP controller metadata event + * + * @param [in] event event id + * @param [in] param callback parameter + */ +void bt_avrc_md_ct_evt_hdl(uint16_t event, void *param); + +#endif /* __AVRCP_METADATA_UTILS_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/idf_component.yml b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/idf_component.yml new file mode 100644 index 0000000000..421ea1aa86 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + avrcp_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/include/avrcp_utils_tags.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/include/avrcp_utils_tags.h new file mode 100644 index 0000000000..a722fbb8b1 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/include/avrcp_utils_tags.h @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __AVRCP_UTILS_TAGS_H__ +#define __AVRCP_UTILS_TAGS_H__ + +/* log tags */ +#define BT_RC_TAG "RC" +#define BT_RC_TG_TAG "RC_TG" +#define BT_RC_CT_TAG "RC_CT" + +#endif /* __AVRCP_UTILS_TAGS_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/CMakeLists.txt new file mode 100644 index 0000000000..3dd3d34ef1 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "bredr_app_common_utils.c" + PRIV_REQUIRES bt nvs_flash + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/Kconfig.projbuild new file mode 100644 index 0000000000..7f1d22b398 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/Kconfig.projbuild @@ -0,0 +1,10 @@ +menu "BR/EDR App Common Example Configuration" + config EXAMPLE_SSP_ENABLED + bool "Secure Simple Pairing" + depends on BT_CLASSIC_ENABLED + default y + help + This enables the Secure Simple Pairing. If disable this option, + Bluedroid will only support Legacy Pairing + +endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/bredr_app_common_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/bredr_app_common_utils.c new file mode 100644 index 0000000000..05d0cd7715 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/bredr_app_common_utils.c @@ -0,0 +1,185 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include +#include +#include "nvs.h" +#include "nvs_flash.h" + +#include "esp_system.h" +#include "esp_log.h" +#include "esp_bt.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" + +#include "bredr_app_common_utils.h" + +#define BREDR_APP_TAG "BREDR_APP" + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static char *bda2str(uint8_t * bda, char *str, size_t size) +{ + if (bda == NULL || str == NULL || size < 18) { + return NULL; + } + + uint8_t *p = bda; + sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", + p[0], p[1], p[2], p[3], p[4], p[5]); + return str; +} + +void bredr_app_dev_evt_def_hdl(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param) +{ + switch (event) { + case ESP_BT_DEV_NAME_RES_EVT: { + if (param->name_res.status == ESP_BT_STATUS_SUCCESS) { + ESP_LOGI(BREDR_APP_TAG, "Get local device name success: %s", param->name_res.name); + } else { + ESP_LOGE(BREDR_APP_TAG, "Get local device name failed, status: %d", param->name_res.status); + } + break; + } + default: { + ESP_LOGI(BREDR_APP_TAG, "event: %d", event); + break; + } + } +} + +void bredr_app_gap_evt_def_hdl(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + uint8_t *bda = NULL; + + switch (event) { + /* when authentication completed, this event comes */ + case ESP_BT_GAP_AUTH_CMPL_EVT: { + if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + ESP_LOGI(BREDR_APP_TAG, "authentication success: %s", param->auth_cmpl.device_name); + ESP_LOG_BUFFER_HEX(BREDR_APP_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); + } else { + ESP_LOGE(BREDR_APP_TAG, "authentication failed, status: %d", param->auth_cmpl.stat); + } + ESP_LOGI(BREDR_APP_TAG, "link key type of current link is: %d", param->auth_cmpl.lk_type); + break; + } + case ESP_BT_GAP_ENC_CHG_EVT: { + char *str_enc[3] = {"OFF", "E0", "AES"}; + bda = (uint8_t *)param->enc_chg.bda; + ESP_LOGI(BREDR_APP_TAG, "Encryption mode to [%02x:%02x:%02x:%02x:%02x:%02x] changed to %s", + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], str_enc[param->enc_chg.enc_mode]); + break; + } + +#if (CONFIG_EXAMPLE_SSP_ENABLED == true) + /* when Security Simple Pairing user confirmation requested, this event comes */ + case ESP_BT_GAP_CFM_REQ_EVT: + ESP_LOGI(BREDR_APP_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %06"PRIu32, param->cfm_req.num_val); + esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); + break; + /* when Security Simple Pairing passkey notified, this event comes */ + case ESP_BT_GAP_KEY_NOTIF_EVT: + ESP_LOGI(BREDR_APP_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey: %06"PRIu32, param->key_notif.passkey); + break; + /* when Security Simple Pairing passkey requested, this event comes */ + case ESP_BT_GAP_KEY_REQ_EVT: + ESP_LOGI(BREDR_APP_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); + break; +#endif + + /* when GAP mode changed, this event comes */ + case ESP_BT_GAP_MODE_CHG_EVT: + ESP_LOGI(BREDR_APP_TAG, "ESP_BT_GAP_MODE_CHG_EVT mode: %d, interval: %.2f ms", + param->mode_chg.mode, param->mode_chg.interval * 0.625); + break; + /* when ACL connection completed, this event comes */ + case ESP_BT_GAP_ACL_CONN_CMPL_STAT_EVT: + bda = (uint8_t *)param->acl_conn_cmpl_stat.bda; + ESP_LOGI(BREDR_APP_TAG, "ESP_BT_GAP_ACL_CONN_CMPL_STAT_EVT Connected to [%02x:%02x:%02x:%02x:%02x:%02x], status: 0x%x", + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], param->acl_conn_cmpl_stat.stat); + break; + /* when ACL disconnection completed, this event comes */ + case ESP_BT_GAP_ACL_DISCONN_CMPL_STAT_EVT: + bda = (uint8_t *)param->acl_disconn_cmpl_stat.bda; + ESP_LOGI(BREDR_APP_TAG, "ESP_BT_GAP_ACL_DISC_CMPL_STAT_EVT Disconnected from [%02x:%02x:%02x:%02x:%02x:%02x], reason: 0x%x", + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], param->acl_disconn_cmpl_stat.reason); + break; + /* others */ + default: { + ESP_LOGI(BREDR_APP_TAG, "event: %d", event); + break; + } + } +} + +esp_err_t bredr_app_common_init(void) +{ + char bda_str[18] = {0}; + /* initialize NVS — it is used to store PHY calibration data */ + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); + + /* + * This example only uses the functions of Classic Bluetooth. + * So release the controller memory for Bluetooth Low Energy. + */ + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { + ESP_LOGE(BREDR_APP_TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(err)); + return err; + } + if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { + ESP_LOGE(BREDR_APP_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(err)); + return err; + } + + esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT(); +#if (CONFIG_EXAMPLE_SSP_ENABLED == false) + bluedroid_cfg.ssp_en = false; +#endif + if ((err = esp_bluedroid_init_with_cfg(&bluedroid_cfg)) != ESP_OK) { + ESP_LOGE(BREDR_APP_TAG, "%s initialize bluedroid failed: %s", __func__, esp_err_to_name(err)); + return err; + } + + if ((err = esp_bluedroid_enable()) != ESP_OK) { + ESP_LOGE(BREDR_APP_TAG, "%s enable bluedroid failed: %s", __func__, esp_err_to_name(err)); + return err; + } + +#if (CONFIG_EXAMPLE_SSP_ENABLED == true) + /* set default parameters for Secure Simple Pairing */ + esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; + esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; + esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); +#endif + + /* set default parameters for Legacy Pairing (use fixed pin code 1234) */ + esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_FIXED; + esp_bt_pin_code_t pin_code; + pin_code[0] = '1'; + pin_code[1] = '2'; + pin_code[2] = '3'; + pin_code[3] = '4'; + esp_bt_gap_set_pin(pin_type, 4, pin_code); + + ESP_LOGI(BREDR_APP_TAG, "Own address:[%s]", bda2str((uint8_t *)esp_bt_dev_get_address(), bda_str, sizeof(bda_str))); + + return ESP_OK; +} diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/bredr_app_common_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/bredr_app_common_utils.h new file mode 100644 index 0000000000..590144b095 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils/bredr_app_common_utils.h @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef __BREDR_APP_COMMON_UTILS_H__ +#define __BREDR_APP_COMMON_UTILS_H__ + +#include +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" + +/** + * @brief Device event default handle function + * + * @param [in] event event id + * @param [in] param handler parameter + */ +void bredr_app_dev_evt_def_hdl(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *param); + +/** + * @brief GAP event default handle function + * + * @param [in] event event id + * @param [in] param handler parameter + */ +void bredr_app_gap_evt_def_hdl(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); + +/** + * @brief Classic BT common initialization + * + * @return ESP_OK on successful init + */ +esp_err_t bredr_app_common_init(void); + +#endif /* __BREDR_APP_COMMON_UTILS_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/CMakeLists.txt new file mode 100644 index 0000000000..2f000acd2b --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "bt_app_core_utils.c" + INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.c new file mode 100644 index 0000000000..514ce77f80 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.c @@ -0,0 +1,138 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include + +#include "esp_log.h" + +#include "freertos/FreeRTOSConfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" + +#include "bt_app_core_utils.h" + +/* log tag */ +#define BT_APP_CORE_TAG "BT_APP_CORE" + +/******************************* + * STATIC FUNCTION DECLARATIONS + ******************************/ + +/* handler for application task */ +static void bt_app_task_handler(void *arg); +/* message sender */ +static bool bt_app_send_msg(bt_app_msg_t *msg); +/* handle dispatched messages */ +static void bt_app_work_dispatched(bt_app_msg_t *msg); + +/******************************* + * STATIC VARIABLE DEFINITIONS + ******************************/ + +static QueueHandle_t s_bt_app_task_queue = NULL; /* handle of work queue */ +static TaskHandle_t s_bt_app_task_handle = NULL; /* handle of application task */ + +/******************************* + * STATIC FUNCTION DEFINITIONS + ******************************/ + +static bool bt_app_send_msg(bt_app_msg_t *msg) +{ + if (msg == NULL) { + return false; + } + + /* send the message to work queue */ + if (xQueueSend(s_bt_app_task_queue, msg, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGE(BT_APP_CORE_TAG, "%s xQueue send failed", __func__); + return false; + } + return true; +} + +static void bt_app_work_dispatched(bt_app_msg_t *msg) +{ + if (msg->cb) { + msg->cb(msg->event, msg->param); + } +} + +static void bt_app_task_handler(void *arg) +{ + bt_app_msg_t msg; + + for (;;) { + /* receive message from work queue and handle it */ + if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, (TickType_t)portMAX_DELAY)) { + ESP_LOGD(BT_APP_CORE_TAG, "%s, signal: 0x%x, event: 0x%x", __func__, msg.sig, msg.event); + + switch (msg.sig) { + case BT_APP_SIG_WORK_DISPATCH: + bt_app_work_dispatched(&msg); + break; + default: + ESP_LOGW(BT_APP_CORE_TAG, "%s, unhandled signal: %d", __func__, msg.sig); + break; + } /* switch (msg.sig) */ + + if (msg.param) { + free(msg.param); + } + } + } +} + +/******************************** + * EXTERNAL FUNCTION DEFINITIONS + *******************************/ + +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +{ + ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len); + + bt_app_msg_t msg; + memset(&msg, 0, sizeof(bt_app_msg_t)); + + msg.sig = BT_APP_SIG_WORK_DISPATCH; + msg.event = event; + msg.cb = p_cback; + + if (param_len == 0) { + return bt_app_send_msg(&msg); + } else if (p_params && param_len > 0) { + if ((msg.param = malloc(param_len)) != NULL) { + memcpy(msg.param, p_params, param_len); + /* check if caller has provided a copy callback to do the deep copy */ + if (p_copy_cback) { + p_copy_cback(msg.param, p_params, param_len); + } + return bt_app_send_msg(&msg); + } + } + + return false; +} + +void bt_app_task_start_up(void) +{ + s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); + xTaskCreate(bt_app_task_handler, "BtAppTask", 3072, NULL, 10, &s_bt_app_task_handle); +} + +void bt_app_task_shut_down(void) +{ + if (s_bt_app_task_handle) { + vTaskDelete(s_bt_app_task_handle); + s_bt_app_task_handle = NULL; + } + if (s_bt_app_task_queue) { + vQueueDelete(s_bt_app_task_queue); + s_bt_app_task_queue = NULL; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.h similarity index 64% rename from examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_core.h rename to examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.h index 055f7609f1..9161f08155 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_core.h +++ b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.h @@ -1,19 +1,16 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ -#ifndef __BT_APP_CORE_H__ -#define __BT_APP_CORE_H__ +#ifndef __BT_APP_CORE_UTILS_H__ +#define __BT_APP_CORE_UTILS_H__ #include #include #include -/* log tag */ -#define BT_APP_CORE_TAG "BT_APP_CORE" - /* signal for `bt_app_work_dispatch` */ #define BT_APP_SIG_WORK_DISPATCH (0x01) @@ -23,7 +20,7 @@ * @param [in] event event id * @param [in] param handler parameter */ -typedef void (* bt_app_cb_t) (uint16_t event, void *param); +typedef void (* bt_app_cb_t)(uint16_t event, void *param); /* message to be sent */ typedef struct { @@ -40,14 +37,14 @@ typedef struct { * @param [in] p_src pointer to source data * @param [in] len data length in byte */ -typedef void (* bt_app_copy_cb_t) (void *p_dest, void *p_src, int len); +typedef void (* bt_app_copy_cb_t)(void *p_dest, void *p_src, int len); /** * @brief work dispatcher for the application task * * @param [in] p_cback callback function * @param [in] event event id - * @param [in] p_params callback paramters + * @param [in] p_params callback parameters * @param [in] param_len parameter length in byte * @param [in] p_copy_cback parameter deep-copy function * @@ -65,24 +62,4 @@ void bt_app_task_start_up(void); */ void bt_app_task_shut_down(void); -/** - * @brief start up the is task - */ -void bt_i2s_task_start_up(void); - -/** - * @brief shut down the I2S task - */ -void bt_i2s_task_shut_down(void); - -/** - * @brief write data to ringbuffer - * - * @param [in] data pointer to data stream - * @param [in] size data length in byte - * - * @return size if writteen ringbuffer successfully, 0 others - */ -size_t write_ringbuf(const uint8_t *data, size_t size); - -#endif /* __BT_APP_CORE_H__ */ +#endif /* __BT_APP_CORE_UTILS_H__ */ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c index c60bde9997..d4b0defcc4 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -25,7 +25,6 @@ #include "sdkconfig.h" #include "bt_app_core.h" #include "bt_app_hf.h" -#include "osi/allocator.h" const char *c_hf_evt_str[] = { "CONNECTION_STATE_EVT", /*!< SERVICE LEVEL CONNECTION STATE CONTROL */ @@ -231,7 +230,7 @@ static void bt_app_send_data_task(void *arg) if (frame_data_num == 0) { continue; } - buf = osi_malloc(frame_data_num); + buf = (uint8_t *)malloc(frame_data_num); if (!buf) { ESP_LOGE(BT_HF_TAG, "%s, no mem", __FUNCTION__); continue; @@ -241,7 +240,7 @@ static void bt_app_send_data_task(void *arg) if (!done) { ESP_LOGE(BT_HF_TAG, "rb send fail"); } - osi_free(buf); + free(buf); vRingbufferGetInfo(s_m_rb, NULL, NULL, NULL, NULL, &item_size); if(s_audio_code == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) { diff --git a/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py b/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py index 3190035c38..acd55d9f75 100644 --- a/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py +++ b/examples/bluetooth/bluedroid/classic_bt/pytest_classic_bt_test.py @@ -72,34 +72,7 @@ def test_bt_spp_vfs(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: acceptor.expect_exact('ESP_SPP_SRV_OPEN_EVT status:0', timeout=30) -# Case 3: A2DP -@pytest.mark.two_duts -@pytest.mark.parametrize( - 'count, app_path, target, config', - [ - ( - 2, - f'{os.path.join(os.path.dirname(__file__), "a2dp_sink")}|' - f'{os.path.join(os.path.dirname(__file__), "a2dp_source")}', - 'esp32|esp32', - 'test', - ), - ], - indirect=True, -) -def test_bt_a2dp(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: - sink_dut = dut[0] - source_dut = dut[1] - source_dut_mac = source_dut.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') - sink_dut.expect_exact('A2DP PROF STATE: Init Complete', timeout=30) - source_dut.expect_exact('a2dp connecting to peer', timeout=30) - source_dut.expect_exact('a2dp connected', timeout=30) - source_dut.expect_exact('a2dp media start successfully', timeout=30) - sink_dut.expect_exact(f'A2DP connection state: Connected, [{source_dut_mac}]', timeout=30) - sink_dut.expect_exact('start volume change simulation', timeout=30) - - -# Case 4: HFP +# Case 3: HFP @pytest.mark.two_duts @pytest.mark.parametrize( 'count, app_path, target, config', @@ -124,7 +97,7 @@ def test_bt_hfp(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: hfp_ag.expect_exact('connection state SLC_CONNECTED', timeout=30) -# # Case 5: HID +# # Case 4: HID @pytest.mark.two_duts @pytest.mark.parametrize( 'count, app_path, target, config', @@ -153,7 +126,7 @@ def test_bt_hid(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: hid_host.expect_exact(f'ESP_HIDH_DEMO: {hid_device_mac} OPEN', timeout=30) -# Case 6: L2CAP +# Case 5: L2CAP @pytest.mark.two_duts @pytest.mark.parametrize( 'count, app_path, target, config', @@ -182,3 +155,57 @@ def test_bt_l2cap(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: client.expect_exact('ESP_SDP_SEARCH_COMP_EVT: status:0', timeout=30) client.expect_exact('ESP_BT_L2CAP_OPEN_EVT: status:0', timeout=30) server.expect_exact('ESP_BT_L2CAP_OPEN_EVT: status:0', timeout=30) + + +# case 6: A2DP Stream +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, target, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "a2dp_sink_stream")}|' + f'{os.path.join(os.path.dirname(__file__), "a2dp_source")}', + 'esp32|esp32', + 'test', + ), + ], + indirect=True, +) +def test_bt_a2dp_stream(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + sink_dut = dut[0] + source_dut = dut[1] + source_dut_mac = source_dut.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') + sink_dut.expect_exact('A2DP PROF STATE: Init Complete', timeout=30) + source_dut.expect_exact('a2dp connecting to peer', timeout=30) + source_dut.expect_exact('a2dp connected', timeout=30) + source_dut.expect_exact('a2dp media start successfully', timeout=30) + sink_dut.expect_exact(f'A2DP connection state: Connected, [{source_dut_mac}]', timeout=30) + + +# case 7: AVRCP absolute volume +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, target, config', + [ + ( + 2, + f'{os.path.join(os.path.dirname(__file__), "avrcp_absolute_volume")}|' + f'{os.path.join(os.path.dirname(__file__), "a2dp_source")}', + 'esp32|esp32', + 'test', + ), + ], + indirect=True, +) +def test_bt_avrcp_absolute_volume(app_path: str, dut: Tuple[IdfDut, IdfDut]) -> None: + sink_dut = dut[0] + source_dut = dut[1] + source_dut_mac = source_dut.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})').group(1).decode('utf8') + sink_dut.expect_exact('AVRCP CT STATE: Init Complete', timeout=30) + sink_dut.expect_exact('AVRCP TG STATE: Init Complete', timeout=30) + source_dut.expect_exact('a2dp connecting to peer', timeout=30) + source_dut.expect_exact('a2dp connected', timeout=30) + sink_dut.expect_exact(f'AVRC conn_state event: state 1, [{source_dut_mac}]', timeout=30) + sink_dut.expect_exact(f'AVRC conn_state evt: state 1, [{source_dut_mac}]', timeout=30) + sink_dut.expect_exact('start volume change simulation', timeout=30) diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/CMakeLists.txt b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/CMakeLists.txt index e68a065139..da473926c8 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/CMakeLists.txt +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/CMakeLists.txt @@ -1,5 +1,15 @@ +set(MY_COMPONENT_REQUIRES + bt_app_core_utils + bredr_app_common_utils + a2dp_sink_common_utils + a2dp_sink_int_codec_utils + avrcp_common_utils + avrcp_metadata_utils + avrcp_abs_vol_utils +) + idf_component_register(SRCS "bt_app_av.c" - "bt_app_core.c" "main.c" - PRIV_REQUIRES esp_driver_i2s bt nvs_flash esp_ringbuf esp_driver_dac + PRIV_REQUIRES bt nvs_flash + PRIV_REQUIRES ${MY_COMPONENT_REQUIRES} INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c index b0b166209f..7bed853682 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -9,506 +9,75 @@ #include #include #include -#include "esp_log.h" -#include "bt_app_core.h" -#include "bt_app_av.h" -#include "esp_bt_main.h" +#include "esp_log.h" #include "esp_bt_device.h" #include "esp_gap_bt_api.h" -#include "esp_a2dp_api.h" #include "esp_avrc_api.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -#include "driver/dac_continuous.h" -#else -#include "driver/i2s_std.h" -#endif -#include "sys/lock.h" - -/* AVRCP used transaction labels */ -#define APP_RC_CT_TL_GET_CAPS (0) -#define APP_RC_CT_TL_GET_META_DATA (1) -#define APP_RC_CT_TL_RN_TRACK_CHANGE (2) -#define APP_RC_CT_TL_RN_PLAYBACK_CHANGE (3) -#define APP_RC_CT_TL_RN_PLAY_POS_CHANGE (4) - -/* Application layer causes delay value */ -#define APP_DELAY_VALUE 50 // 5ms - -/******************************* - * STATIC FUNCTION DECLARATIONS - ******************************/ - -/* allocate new meta buffer */ -static void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t *param); -/* handler for new track is loaded */ -static void bt_av_new_track(void); -/* handler for track status change */ -static void bt_av_playback_changed(void); -/* handler for track playing position change */ -static void bt_av_play_pos_changed(void); -/* notification event handler */ -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter); -/* installation for i2s */ -static void bt_i2s_driver_install(void); -/* uninstallation for i2s */ -static void bt_i2s_driver_uninstall(void); -/* set volume by remote controller */ -static void volume_set_by_controller(uint8_t volume); -/* set volume by local host */ -static void volume_set_by_local_host(uint8_t volume); -/* simulation volume change */ -static void volume_change_simulation(void *arg); -/* a2dp event handler */ -static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param); -/* avrc controller event handler */ -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param); -/* avrc target event handler */ -static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param); - -/******************************* - * STATIC VARIABLE DEFINITIONS - ******************************/ - -static uint32_t s_pkt_cnt = 0; /* count for audio packet */ -static esp_a2d_audio_state_t s_audio_state = ESP_A2D_AUDIO_STATE_STOPPED; - /* audio stream datapath state */ -static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; - /* connection state in string */ -static const char *s_a2d_audio_state_str[] = {"Suspended", "Started"}; - /* audio stream datapath state in string */ -static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap; - /* AVRC target notification capability bit mask */ -static _lock_t s_volume_lock; -static TaskHandle_t s_vcs_task_hdl = NULL; /* handle for volume change simulation task */ -static uint8_t s_volume = 0; /* local volume value */ -static bool s_volume_notify; /* notify volume change or not */ -#ifndef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -i2s_chan_handle_t tx_chan = NULL; -#else -dac_continuous_handle_t tx_chan; -#endif +#include "bt_app_core_utils.h" +#include "avrcp_utils_tags.h" +#include "avrcp_common_utils.h" +#include "avrcp_metadata_utils.h" +#include "avrcp_abs_vol_utils.h" +#include "a2dp_utils_tags.h" +#include "a2dp_sink_common_utils.h" +#include "a2dp_sink_int_codec_utils.h" +#include "bt_app_av.h" /******************************** * STATIC FUNCTION DEFINITIONS *******************************/ -static void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t *param) -{ - esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); - uint8_t *attr_text = (uint8_t *) malloc (rc->meta_rsp.attr_length + 1); - - memcpy(attr_text, rc->meta_rsp.attr_text, rc->meta_rsp.attr_length); - attr_text[rc->meta_rsp.attr_length] = 0; - rc->meta_rsp.attr_text = attr_text; -} - -static void bt_av_new_track(void) -{ - /* request metadata */ - uint8_t attr_mask = ESP_AVRC_MD_ATTR_TITLE | - ESP_AVRC_MD_ATTR_ARTIST | - ESP_AVRC_MD_ATTR_ALBUM | - ESP_AVRC_MD_ATTR_GENRE; - esp_avrc_ct_send_metadata_cmd(APP_RC_CT_TL_GET_META_DATA, attr_mask); - - /* register notification if peer support the event_id */ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_TRACK_CHANGE)) { - esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_TRACK_CHANGE, - ESP_AVRC_RN_TRACK_CHANGE, 0); - } -} - -static void bt_av_playback_changed(void) -{ - /* register notification if peer support the event_id */ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_PLAY_STATUS_CHANGE)) { - esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_PLAYBACK_CHANGE, - ESP_AVRC_RN_PLAY_STATUS_CHANGE, 0); - } -} - -static void bt_av_play_pos_changed(void) -{ - /* register notification if peer support the event_id */ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_PLAY_POS_CHANGED)) { - esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_PLAY_POS_CHANGE, - ESP_AVRC_RN_PLAY_POS_CHANGED, 10); - } -} - -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter) -{ - switch (event_id) { - /* when new track is loaded, this event comes */ - case ESP_AVRC_RN_TRACK_CHANGE: - bt_av_new_track(); - break; - /* when track status changed, this event comes */ - case ESP_AVRC_RN_PLAY_STATUS_CHANGE: - ESP_LOGI(BT_AV_TAG, "Playback status changed: 0x%x", event_parameter->playback); - bt_av_playback_changed(); - break; - /* when track playing position changed, this event comes */ - case ESP_AVRC_RN_PLAY_POS_CHANGED: - ESP_LOGI(BT_AV_TAG, "Play position changed: %"PRIu32"-ms", event_parameter->play_pos); - bt_av_play_pos_changed(); - break; - /* others */ - default: - ESP_LOGI(BT_AV_TAG, "unhandled event: %d", event_id); - break; - } -} - -void bt_i2s_driver_install(void) -{ -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - dac_continuous_config_t cont_cfg = { - .chan_mask = DAC_CHANNEL_MASK_ALL, - .desc_num = 8, - .buf_size = 2048, - .freq_hz = 44100, - .offset = 127, - .clk_src = DAC_DIGI_CLK_SRC_DEFAULT, // Using APLL as clock source to get a wider frequency range - .chan_mode = DAC_CHANNEL_MODE_ALTER, - }; - /* Allocate continuous channels */ - ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &tx_chan)); - /* Enable the continuous channels */ - ESP_ERROR_CHECK(dac_continuous_enable(tx_chan)); -#else - i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); - chan_cfg.auto_clear = true; - i2s_std_config_t std_cfg = { - .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(44100), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = CONFIG_EXAMPLE_I2S_BCK_PIN, - .ws = CONFIG_EXAMPLE_I2S_LRCK_PIN, - .dout = CONFIG_EXAMPLE_I2S_DATA_PIN, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - }, - }, - }; - /* enable I2S */ - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, NULL)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_enable(tx_chan)); -#endif -} - -void bt_i2s_driver_uninstall(void) -{ -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - ESP_ERROR_CHECK(dac_continuous_disable(tx_chan)); - ESP_ERROR_CHECK(dac_continuous_del_channels(tx_chan)); -#else - ESP_ERROR_CHECK(i2s_channel_disable(tx_chan)); - ESP_ERROR_CHECK(i2s_del_channel(tx_chan)); -#endif -} - -static void volume_set_by_controller(uint8_t volume) -{ - ESP_LOGI(BT_RC_TG_TAG, "Volume is set by remote controller to: %"PRIu32"%%", (uint32_t)volume * 100 / 0x7f); - /* set the volume in protection of lock */ - _lock_acquire(&s_volume_lock); - s_volume = volume; - _lock_release(&s_volume_lock); -} - -static void volume_set_by_local_host(uint8_t volume) -{ - ESP_LOGI(BT_RC_TG_TAG, "Volume is set locally to: %"PRIu32"%%", (uint32_t)volume * 100 / 0x7f); - /* set the volume in protection of lock */ - _lock_acquire(&s_volume_lock); - s_volume = volume; - _lock_release(&s_volume_lock); - - /* send notification response to remote AVRCP controller */ - if (s_volume_notify) { - esp_avrc_rn_param_t rn_param; - rn_param.volume = s_volume; - esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_CHANGED, &rn_param); - s_volume_notify = false; - } -} - -static void volume_change_simulation(void *arg) -{ - ESP_LOGI(BT_RC_TG_TAG, "start volume change simulation"); - - for (;;) { - /* volume up locally every 10 seconds */ - vTaskDelay(10000 / portTICK_PERIOD_MS); - uint8_t volume = (s_volume + 5) & 0x7f; - volume_set_by_local_host(volume); - } -} - -static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) -{ - ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event); - - esp_a2d_cb_param_t *a2d = NULL; - - switch (event) { - /* when connection state changed, this event comes */ - case ESP_A2D_CONNECTION_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - uint8_t *bda = a2d->conn_stat.remote_bda; - ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", - s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { - esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); - bt_i2s_driver_uninstall(); - bt_i2s_task_shut_down(); - } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){ - esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); - bt_i2s_task_start_up(); - } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTING) { - bt_i2s_driver_install(); - } - break; - } - /* when audio stream transmission state changed, this event comes */ - case ESP_A2D_AUDIO_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]); - s_audio_state = a2d->audio_stat.state; - if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { - s_pkt_cnt = 0; - } - break; - } - /* when audio codec is configured, this event comes */ - case ESP_A2D_AUDIO_CFG_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - esp_a2d_mcc_t *p_mcc = &a2d->audio_cfg.mcc; - ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, codec type: %d", p_mcc->type); - /* for now only SBC stream is supported */ - if (p_mcc->type == ESP_A2D_MCT_SBC) { - int sample_rate = 16000; - int ch_count = 2; - if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_32K) { - sample_rate = 32000; - } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_44K) { - sample_rate = 44100; - } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_48K) { - sample_rate = 48000; - } - - if (p_mcc->cie.sbc_info.ch_mode & ESP_A2D_SBC_CIE_CH_MODE_MONO) { - ch_count = 1; - } - #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - dac_continuous_disable(tx_chan); - dac_continuous_del_channels(tx_chan); - dac_continuous_config_t cont_cfg = { - .chan_mask = DAC_CHANNEL_MASK_ALL, - .desc_num = 8, - .buf_size = 2048, - .freq_hz = sample_rate, - .offset = 127, - .clk_src = DAC_DIGI_CLK_SRC_DEFAULT, // Using APLL as clock source to get a wider frequency range - .chan_mode = (ch_count == 1) ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER, - }; - /* Allocate continuous channels */ - dac_continuous_new_channels(&cont_cfg, &tx_chan); - /* Enable the continuous channels */ - dac_continuous_enable(tx_chan); - #else - i2s_channel_disable(tx_chan); - i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(sample_rate); - i2s_std_slot_config_t slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, ch_count); - i2s_channel_reconfig_std_clock(tx_chan, &clk_cfg); - i2s_channel_reconfig_std_slot(tx_chan, &slot_cfg); - i2s_channel_enable(tx_chan); - #endif - ESP_LOGI(BT_AV_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", - p_mcc->cie.sbc_info.samp_freq, - p_mcc->cie.sbc_info.ch_mode, - p_mcc->cie.sbc_info.block_len, - p_mcc->cie.sbc_info.num_subbands, - p_mcc->cie.sbc_info.alloc_mthd, - p_mcc->cie.sbc_info.min_bitpool, - p_mcc->cie.sbc_info.max_bitpool); - ESP_LOGI(BT_AV_TAG, "Audio player configured, sample rate: %d", sample_rate); - } - break; - } - /* when a2dp init or deinit completed, this event comes */ - case ESP_A2D_PROF_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { - ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); - } else { - ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); - } - break; - } - /* When protocol service capabilities configured, this event comes */ - case ESP_A2D_SNK_PSC_CFG_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - ESP_LOGI(BT_AV_TAG, "protocol service capabilities configured: 0x%x ", a2d->a2d_psc_cfg_stat.psc_mask); - if (a2d->a2d_psc_cfg_stat.psc_mask & ESP_A2D_PSC_DELAY_RPT) { - ESP_LOGI(BT_AV_TAG, "Peer device support delay reporting"); - } else { - ESP_LOGI(BT_AV_TAG, "Peer device unsupported delay reporting"); - } - break; - } - /* when set delay value completed, this event comes */ - case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - if (ESP_A2D_SET_INVALID_PARAMS == a2d->a2d_set_delay_value_stat.set_state) { - ESP_LOGI(BT_AV_TAG, "Set delay report value: fail"); - } else { - ESP_LOGI(BT_AV_TAG, "Set delay report value: success, delay_value: %u * 1/10 ms", a2d->a2d_set_delay_value_stat.delay_value); - } - break; - } - /* when get delay value completed, this event comes */ - case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - ESP_LOGI(BT_AV_TAG, "Get delay report value: delay_value: %u * 1/10 ms", a2d->a2d_get_delay_value_stat.delay_value); - /* Default delay value plus delay caused by application layer */ - esp_a2d_sink_set_delay_value(a2d->a2d_get_delay_value_stat.delay_value + APP_DELAY_VALUE); - break; - } - /* others */ - default: - ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); - break; - } -} - -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) +/* handler for AVRCP controller events */ +static void bt_app_avrc_ct_evt_hdl(uint16_t event, void *param) { ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event); - esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param); + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); switch (event) { - /* when connection state changed, this event comes */ + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: + case ESP_AVRC_CT_PROF_STATE_EVT: { + bt_avrc_common_ct_evt_def_hdl(event, param); + break; + } case ESP_AVRC_CT_CONNECTION_STATE_EVT: { - uint8_t *bda = rc->conn_stat.remote_bda; - ESP_LOGI(BT_RC_CT_TAG, "AVRC conn_state event: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", - rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - + bt_avrc_md_ct_evt_hdl(event, param); if (rc->conn_stat.connected) { /* get remote supported event_ids of peer AVRCP Target */ - esp_avrc_ct_send_get_rn_capabilities_cmd(APP_RC_CT_TL_GET_CAPS); + bt_avrc_common_ct_get_peer_rn_cap(); } else { /* clear peer notification capability record */ - s_avrc_peer_rn_cap.bits = 0; + bt_avrc_common_ct_set_peer_rn_cap(0); } break; } - /* when passthrough responded, this event comes */ - case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC passthrough rsp: key_code 0x%x, key_state %d, rsp_code %d", rc->psth_rsp.key_code, - rc->psth_rsp.key_state, rc->psth_rsp.rsp_code); - break; - } - /* when metadata responded, this event comes */ - case ESP_AVRC_CT_METADATA_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); - free(rc->meta_rsp.attr_text); - break; - } - /* when notified, this event comes */ case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id); - bt_av_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter); + bt_avrc_md_ct_evt_hdl(event, param); + bt_avrc_common_ct_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter); break; } - /* when feature of remote device indicated, this event comes */ - case ESP_AVRC_CT_REMOTE_FEATURES_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC remote features %"PRIx32", TG features %x", rc->rmt_feats.feat_mask, rc->rmt_feats.tg_feat_flag); - break; - } - /* when notification capability of peer device got, this event comes */ case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, - rc->get_rn_caps_rsp.evt_set.bits); - s_avrc_peer_rn_cap.bits = rc->get_rn_caps_rsp.evt_set.bits; - bt_av_new_track(); - bt_av_playback_changed(); - bt_av_play_pos_changed(); + /* set peer notification capability record */ + bt_avrc_common_ct_set_peer_rn_cap(rc->get_rn_caps_rsp.evt_set.bits); + bt_avrc_common_ct_rn_track_changed(); + bt_avrc_common_ct_rn_play_status_changed(); + bt_avrc_common_ct_rn_play_pos_changed(); + + bt_avrc_md_ct_evt_hdl(event, param); + break; + } + case ESP_AVRC_CT_METADATA_RSP_EVT: { + bt_avrc_md_ct_evt_hdl(event, param); break; } - /* others */ default: - ESP_LOGE(BT_RC_CT_TAG, "%s unhandled event: %d", __func__, event); - break; - } -} - -static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param) -{ - ESP_LOGD(BT_RC_TG_TAG, "%s event: %d", __func__, event); - - esp_avrc_tg_cb_param_t *rc = (esp_avrc_tg_cb_param_t *)(p_param); - - switch (event) { - /* when connection state changed, this event comes */ - case ESP_AVRC_TG_CONNECTION_STATE_EVT: { - uint8_t *bda = rc->conn_stat.remote_bda; - ESP_LOGI(BT_RC_TG_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", - rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - if (rc->conn_stat.connected) { - /* create task to simulate volume change */ - xTaskCreate(volume_change_simulation, "vcsTask", 2048, NULL, 5, &s_vcs_task_hdl); - } else { - vTaskDelete(s_vcs_task_hdl); - ESP_LOGI(BT_RC_TG_TAG, "Stop volume change simulation"); - } - break; - } - /* when passthrough commanded, this event comes */ - case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC passthrough cmd: key_code 0x%x, key_state %d", rc->psth_cmd.key_code, rc->psth_cmd.key_state); - break; - } - /* when absolute volume command from remote device set, this event comes */ - case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC set absolute volume: %d%%", (int)rc->set_abs_vol.volume * 100 / 0x7f); - volume_set_by_controller(rc->set_abs_vol.volume); - break; - } - /* when notification registered, this event comes */ - case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC register event notification: %d, param: 0x%"PRIx32, rc->reg_ntf.event_id, rc->reg_ntf.event_parameter); - if (rc->reg_ntf.event_id == ESP_AVRC_RN_VOLUME_CHANGE) { - s_volume_notify = true; - esp_avrc_rn_param_t rn_param; - rn_param.volume = s_volume; - esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_INTERIM, &rn_param); - } - break; - } - /* when feature of remote device indicated, this event comes */ - case ESP_AVRC_TG_REMOTE_FEATURES_EVT: { - ESP_LOGI(BT_RC_TG_TAG, "AVRC remote features: %"PRIx32", CT features: %x", rc->rmt_feats.feat_mask, rc->rmt_feats.ct_feat_flag); - break; - } - /* others */ - default: - ESP_LOGE(BT_RC_TG_TAG, "%s unhandled event: %d", __func__, event); + ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); break; } } @@ -522,12 +91,15 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) switch (event) { case ESP_A2D_CONNECTION_STATE_EVT: case ESP_A2D_AUDIO_STATE_EVT: - case ESP_A2D_AUDIO_CFG_EVT: + case ESP_A2D_AUDIO_CFG_EVT: { + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + break; + } case ESP_A2D_PROF_STATE_EVT: case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - bt_app_work_dispatch(bt_av_hdl_a2d_evt, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); break; } default: @@ -538,28 +110,24 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) { - write_ringbuf(data, len); - - /* log the number every 100 packets */ - if (++s_pkt_cnt % 100 == 0) { - ESP_LOGI(BT_AV_TAG, "Audio packet count: %"PRIu32, s_pkt_cnt); - } + bt_a2d_data_hdl(data, len); } void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) { switch (event) { - case ESP_AVRC_CT_METADATA_RSP_EVT: - bt_app_alloc_meta_buffer(param); - /* fall through */ + case ESP_AVRC_CT_METADATA_RSP_EVT: { + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), bt_avrc_common_copy_metadata); + break; + } case ESP_AVRC_CT_CONNECTION_STATE_EVT: case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: case ESP_AVRC_CT_REMOTE_FEATURES_EVT: - case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { - bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: + case ESP_AVRC_CT_PROF_STATE_EVT: + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); break; - } default: ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); break; @@ -569,14 +137,19 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param) { switch (event) { - case ESP_AVRC_TG_CONNECTION_STATE_EVT: case ESP_AVRC_TG_REMOTE_FEATURES_EVT: case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: - case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: - case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: - bt_app_work_dispatch(bt_av_hdl_avrc_tg_evt, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + case ESP_AVRC_TG_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); break; + } + case ESP_AVRC_TG_CONNECTION_STATE_EVT: + case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: + case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { + bt_app_work_dispatch(bt_avrc_avc_tg_evt_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + break; + } default: ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event); break; diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.h b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.h index d0e6e6c789..3750ba67c3 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.h +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -11,11 +11,6 @@ #include "esp_a2dp_api.h" #include "esp_avrc_api.h" -/* log tags */ -#define BT_AV_TAG "BT_AV" -#define BT_RC_TG_TAG "RC_TG" -#define BT_RC_CT_TAG "RC_CT" - /** * @brief callback function for A2DP sink * diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_core.c b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_core.c deleted file mode 100644 index 29c915e893..0000000000 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_core.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#include -#include -#include -#include "freertos/FreeRTOSConfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "bt_app_core.h" -#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -#include "driver/dac_continuous.h" -#else -#include "driver/i2s_std.h" -#endif -#include "freertos/ringbuf.h" - - -#define RINGBUF_HIGHEST_WATER_LEVEL (32 * 1024) -#define RINGBUF_PREFETCH_WATER_LEVEL (20 * 1024) - -enum { - RINGBUFFER_MODE_PROCESSING, /* ringbuffer is buffering incoming audio data, I2S is working */ - RINGBUFFER_MODE_PREFETCHING, /* ringbuffer is buffering incoming audio data, I2S is waiting */ - RINGBUFFER_MODE_DROPPING /* ringbuffer is not buffering (dropping) incoming audio data, I2S is working */ -}; - -/******************************* - * STATIC FUNCTION DECLARATIONS - ******************************/ - -/* handler for application task */ -static void bt_app_task_handler(void *arg); -/* handler for I2S task */ -static void bt_i2s_task_handler(void *arg); -/* message sender */ -static bool bt_app_send_msg(bt_app_msg_t *msg); -/* handle dispatched messages */ -static void bt_app_work_dispatched(bt_app_msg_t *msg); - -/******************************* - * STATIC VARIABLE DEFINITIONS - ******************************/ - -static QueueHandle_t s_bt_app_task_queue = NULL; /* handle of work queue */ -static TaskHandle_t s_bt_app_task_handle = NULL; /* handle of application task */ -static TaskHandle_t s_bt_i2s_task_handle = NULL; /* handle of I2S task */ -static RingbufHandle_t s_ringbuf_i2s = NULL; /* handle of ringbuffer for I2S */ -static SemaphoreHandle_t s_i2s_write_semaphore = NULL; -static uint16_t ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; - -/********************************* - * EXTERNAL FUNCTION DECLARATIONS - ********************************/ -#ifndef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC -extern i2s_chan_handle_t tx_chan; -#else -extern dac_continuous_handle_t tx_chan; -#endif - -/******************************* - * STATIC FUNCTION DEFINITIONS - ******************************/ - -static bool bt_app_send_msg(bt_app_msg_t *msg) -{ - if (msg == NULL) { - return false; - } - - /* send the message to work queue */ - if (xQueueSend(s_bt_app_task_queue, msg, 10 / portTICK_PERIOD_MS) != pdTRUE) { - ESP_LOGE(BT_APP_CORE_TAG, "%s xQueue send failed", __func__); - return false; - } - return true; -} - -static void bt_app_work_dispatched(bt_app_msg_t *msg) -{ - if (msg->cb) { - msg->cb(msg->event, msg->param); - } -} - -static void bt_app_task_handler(void *arg) -{ - bt_app_msg_t msg; - - for (;;) { - /* receive message from work queue and handle it */ - if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, (TickType_t)portMAX_DELAY)) { - ESP_LOGD(BT_APP_CORE_TAG, "%s, signal: 0x%x, event: 0x%x", __func__, msg.sig, msg.event); - - switch (msg.sig) { - case BT_APP_SIG_WORK_DISPATCH: - bt_app_work_dispatched(&msg); - break; - default: - ESP_LOGW(BT_APP_CORE_TAG, "%s, unhandled signal: %d", __func__, msg.sig); - break; - } /* switch (msg.sig) */ - - if (msg.param) { - free(msg.param); - } - } - } -} - -static void bt_i2s_task_handler(void *arg) -{ - uint8_t *data = NULL; - size_t item_size = 0; - /** - * The total length of DMA buffer of I2S is: - * `dma_frame_num * dma_desc_num * i2s_channel_num * i2s_data_bit_width / 8`. - * Transmit `dma_frame_num * dma_desc_num` bytes to DMA is trade-off. - */ - const size_t item_size_upto = 240 * 6; - size_t bytes_written = 0; - - for (;;) { - if (pdTRUE == xSemaphoreTake(s_i2s_write_semaphore, portMAX_DELAY)) { - for (;;) { - item_size = 0; - /* receive data from ringbuffer and write it to I2S DMA transmit buffer */ - data = (uint8_t *)xRingbufferReceiveUpTo(s_ringbuf_i2s, &item_size, (TickType_t)pdMS_TO_TICKS(20), item_size_upto); - if (item_size == 0) { - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer underflowed! mode changed: RINGBUFFER_MODE_PREFETCHING"); - ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; - break; - } - - #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC - dac_continuous_write(tx_chan, data, item_size, &bytes_written, -1); - #else - i2s_channel_write(tx_chan, data, item_size, &bytes_written, portMAX_DELAY); - #endif - vRingbufferReturnItem(s_ringbuf_i2s, (void *)data); - } - } - } -} - -/******************************** - * EXTERNAL FUNCTION DEFINITIONS - *******************************/ - -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) -{ - ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len); - - bt_app_msg_t msg; - memset(&msg, 0, sizeof(bt_app_msg_t)); - - msg.sig = BT_APP_SIG_WORK_DISPATCH; - msg.event = event; - msg.cb = p_cback; - - if (param_len == 0) { - return bt_app_send_msg(&msg); - } else if (p_params && param_len > 0) { - if ((msg.param = malloc(param_len)) != NULL) { - memcpy(msg.param, p_params, param_len); - /* check if caller has provided a copy callback to do the deep copy */ - if (p_copy_cback) { - p_copy_cback(msg.param, p_params, param_len); - } - return bt_app_send_msg(&msg); - } - } - - return false; -} - -void bt_app_task_start_up(void) -{ - s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); - xTaskCreate(bt_app_task_handler, "BtAppTask", 3072, NULL, 10, &s_bt_app_task_handle); -} - -void bt_app_task_shut_down(void) -{ - if (s_bt_app_task_handle) { - vTaskDelete(s_bt_app_task_handle); - s_bt_app_task_handle = NULL; - } - if (s_bt_app_task_queue) { - vQueueDelete(s_bt_app_task_queue); - s_bt_app_task_queue = NULL; - } -} - -void bt_i2s_task_start_up(void) -{ - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data empty! mode changed: RINGBUFFER_MODE_PREFETCHING"); - ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; - if ((s_i2s_write_semaphore = xSemaphoreCreateBinary()) == NULL) { - ESP_LOGE(BT_APP_CORE_TAG, "%s, Semaphore create failed", __func__); - return; - } - if ((s_ringbuf_i2s = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) { - ESP_LOGE(BT_APP_CORE_TAG, "%s, ringbuffer create failed", __func__); - return; - } - xTaskCreate(bt_i2s_task_handler, "BtI2STask", 2048, NULL, configMAX_PRIORITIES - 3, &s_bt_i2s_task_handle); -} - -void bt_i2s_task_shut_down(void) -{ - if (s_bt_i2s_task_handle) { - vTaskDelete(s_bt_i2s_task_handle); - s_bt_i2s_task_handle = NULL; - } - if (s_ringbuf_i2s) { - vRingbufferDelete(s_ringbuf_i2s); - s_ringbuf_i2s = NULL; - } - if (s_i2s_write_semaphore) { - vSemaphoreDelete(s_i2s_write_semaphore); - s_i2s_write_semaphore = NULL; - } -} - -size_t write_ringbuf(const uint8_t *data, size_t size) -{ - size_t item_size = 0; - BaseType_t done = pdFALSE; - - if (ringbuffer_mode == RINGBUFFER_MODE_DROPPING) { - ESP_LOGW(BT_APP_CORE_TAG, "ringbuffer is full, drop this packet!"); - vRingbufferGetInfo(s_ringbuf_i2s, NULL, NULL, NULL, NULL, &item_size); - if (item_size <= RINGBUF_PREFETCH_WATER_LEVEL) { - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data decreased! mode changed: RINGBUFFER_MODE_PROCESSING"); - ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; - } - return 0; - } - - done = xRingbufferSend(s_ringbuf_i2s, (void *)data, size, (TickType_t)0); - - if (!done) { - ESP_LOGW(BT_APP_CORE_TAG, "ringbuffer overflowed, ready to decrease data! mode changed: RINGBUFFER_MODE_DROPPING"); - ringbuffer_mode = RINGBUFFER_MODE_DROPPING; - } - - if (ringbuffer_mode == RINGBUFFER_MODE_PREFETCHING) { - vRingbufferGetInfo(s_ringbuf_i2s, NULL, NULL, NULL, NULL, &item_size); - if (item_size >= RINGBUF_PREFETCH_WATER_LEVEL) { - ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data increased! mode changed: RINGBUFFER_MODE_PROCESSING"); - ringbuffer_mode = RINGBUFFER_MODE_PROCESSING; - if (pdFALSE == xSemaphoreGive(s_i2s_write_semaphore)) { - ESP_LOGE(BT_APP_CORE_TAG, "semphore give failed"); - } - } - } - - return done ? size : 0; -} diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_core.h b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_core.h deleted file mode 100644 index 055f7609f1..0000000000 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_core.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#ifndef __BT_APP_CORE_H__ -#define __BT_APP_CORE_H__ - -#include -#include -#include - -/* log tag */ -#define BT_APP_CORE_TAG "BT_APP_CORE" - -/* signal for `bt_app_work_dispatch` */ -#define BT_APP_SIG_WORK_DISPATCH (0x01) - -/** - * @brief handler for the dispatched work - * - * @param [in] event event id - * @param [in] param handler parameter - */ -typedef void (* bt_app_cb_t) (uint16_t event, void *param); - -/* message to be sent */ -typedef struct { - uint16_t sig; /*!< signal to bt_app_task */ - uint16_t event; /*!< message event id */ - bt_app_cb_t cb; /*!< context switch callback */ - void *param; /*!< parameter area needs to be last */ -} bt_app_msg_t; - -/** - * @brief parameter deep-copy function to be customized - * - * @param [out] p_dest pointer to destination data - * @param [in] p_src pointer to source data - * @param [in] len data length in byte - */ -typedef void (* bt_app_copy_cb_t) (void *p_dest, void *p_src, int len); - -/** - * @brief work dispatcher for the application task - * - * @param [in] p_cback callback function - * @param [in] event event id - * @param [in] p_params callback paramters - * @param [in] param_len parameter length in byte - * @param [in] p_copy_cback parameter deep-copy function - * - * @return true if work dispatch successfully, false otherwise - */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); - -/** - * @brief start up the application task - */ -void bt_app_task_start_up(void); - -/** - * @brief shut down the application task - */ -void bt_app_task_shut_down(void); - -/** - * @brief start up the is task - */ -void bt_i2s_task_start_up(void); - -/** - * @brief shut down the I2S task - */ -void bt_i2s_task_shut_down(void); - -/** - * @brief write data to ringbuffer - * - * @param [in] data pointer to data stream - * @param [in] size data length in byte - * - * @return size if writteen ringbuffer successfully, 0 others - */ -size_t write_ringbuf(const uint8_t *data, size_t size); - -#endif /* __BT_APP_CORE_H__ */ diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/idf_component.yml b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/idf_component.yml new file mode 100644 index 0000000000..d43bddf6d1 --- /dev/null +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/idf_component.yml @@ -0,0 +1,15 @@ +dependencies: + bt_app_core_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils + bredr_app_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/bredr_app_common_utils + a2dp_sink_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_common_utils + a2dp_sink_int_codec_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils + avrcp_common_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils + avrcp_metadata_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils + avrcp_abs_vol_utils: + path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c index 12e8bdd8b1..4b9288eedb 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c @@ -21,27 +21,30 @@ #include #include #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" + #include "nvs.h" #include "nvs_flash.h" #include "esp_system.h" #include "esp_log.h" - #include "esp_bt.h" -#include "bt_app_core.h" -#include "bt_app_av.h" #include "esp_bt_main.h" #include "esp_bt_device.h" #include "esp_gap_bt_api.h" #include "esp_a2dp_api.h" #include "esp_avrc_api.h" - #include "esp_gap_ble_api.h" #include "esp_gatts_api.h" #include "esp_bt_defs.h" #include "esp_gatt_common_api.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "bt_app_core_utils.h" +#include "bredr_app_common_utils.h" +#include "a2dp_sink_int_codec_utils.h" +#include "bt_app_av.h" + /* log tag */ #define BT_BLE_COEX_TAG "BT_BLE_COEX" /* device name */ @@ -95,8 +98,8 @@ esp_attr_value_t gatts_initial_char_val = { }; static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x060, - .adv_int_max = 0x060, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(60), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(60), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_RPA_PUBLIC, .channel_map = ADV_CHNL_ALL, @@ -138,8 +141,8 @@ static void ble_init_adv_data(const char *name) size_t len = strlen(name); // ADV data max is 31 bytes; overhead is 5 bytes (Flags: 3, Name header: 2) - #define ADV_DATA_MAX_LEN 31 - #define ADV_DATA_OVERHEAD 5 +#define ADV_DATA_MAX_LEN 31 +#define ADV_DATA_OVERHEAD 5 if (len > (ADV_DATA_MAX_LEN - ADV_DATA_OVERHEAD)) { ESP_LOGW(BT_BLE_COEX_TAG, "ADV name too long (%d), truncating to %d", (int)len, ADV_DATA_MAX_LEN - ADV_DATA_OVERHEAD); @@ -160,11 +163,11 @@ static void ble_init_adv_data(const char *name) //The length of adv data must be less than 31 bytes esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, adv_data_len); - if (raw_adv_ret){ + if (raw_adv_ret) { ESP_LOGE(BT_BLE_COEX_TAG, "config raw adv data failed, error code = 0x%x ", raw_adv_ret); } esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_adv_data, adv_data_len); - if (raw_scan_ret){ + if (raw_scan_ret) { ESP_LOGE(BT_BLE_COEX_TAG, "config raw scan rsp data failed, error code = 0x%x", raw_scan_ret); } } @@ -182,33 +185,33 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param //advertising start complete event to indicate advertising start successfully or failed if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { ESP_LOGE(BT_BLE_COEX_TAG, "Advertising start failed"); - }else { + } else { ESP_LOGI(BT_BLE_COEX_TAG, "Start adv successfully"); } break; case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { ESP_LOGE(BT_BLE_COEX_TAG, "Advertising stop failed"); - } - else { + } else { ESP_LOGI(BT_BLE_COEX_TAG, "Stop adv successfully"); } break; case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: - ESP_LOGI(BT_BLE_COEX_TAG, "update connection params status = %d, conn_int = %d, latency = %d, timeout = %d", - param->update_conn_params.status, - param->update_conn_params.conn_int, - param->update_conn_params.latency, - param->update_conn_params.timeout); + ESP_LOGI(BT_BLE_COEX_TAG, "update connection params status = %d, conn_int = %d, latency = %d, timeout = %d", + param->update_conn_params.status, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); break; default: break; } } -void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ +void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param) +{ esp_gatt_status_t status = ESP_GATT_OK; - if (param->write.need_rsp){ + if (param->write.need_rsp) { if (param->write.is_prep) { if (param->write.offset > PREPARE_BUF_MAX_SIZE) { status = ESP_GATT_INVALID_OFFSET; @@ -217,7 +220,7 @@ void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare } if (status == ESP_GATT_OK && prepare_write_env->prepare_buf == NULL) { - prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE*sizeof(uint8_t)); + prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t)); prepare_write_env->prepare_len = 0; if (prepare_write_env->prepare_buf == NULL) { ESP_LOGE(BT_BLE_COEX_TAG, "Gatt_server prep no mem"); @@ -233,7 +236,7 @@ void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len); esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp); - if (response_err != ESP_OK){ + if (response_err != ESP_OK) { ESP_LOGE(BT_BLE_COEX_TAG, "Send response error\n"); } free(gatt_rsp); @@ -241,7 +244,7 @@ void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare ESP_LOGE(BT_BLE_COEX_TAG, "%s, malloc failed", __func__); status = ESP_GATT_NO_RESOURCES; } - if (status != ESP_GATT_OK){ + if (status != ESP_GATT_OK) { return; } memcpy(prepare_write_env->prepare_buf + param->write.offset, @@ -249,17 +252,18 @@ void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare param->write.len); prepare_write_env->prepare_len += param->write.len; - }else{ + } else { esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, NULL); } } } -void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ - if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC){ +void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param) +{ + if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { ESP_LOG_BUFFER_HEX(BT_BLE_COEX_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len); - }else{ - ESP_LOGI(BT_BLE_COEX_TAG,"ESP_GATT_PREP_WRITE_CANCEL"); + } else { + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATT_PREP_WRITE_CANCEL"); } if (prepare_write_env->prepare_buf) { free(prepare_write_env->prepare_buf); @@ -268,7 +272,8 @@ void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble prepare_write_env->prepare_len = 0; } -static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { +static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ switch (event) { case ESP_GATTS_REG_EVT: ESP_LOGI(BT_BLE_COEX_TAG, "REGISTER_APP_EVT, status %d, app_id %d", param->reg.status, param->reg.app_id); @@ -297,39 +302,36 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i } case ESP_GATTS_WRITE_EVT: { ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %"PRIu32", handle %d", param->write.conn_id, param->write.trans_id, param->write.handle); - if (!param->write.is_prep){ + if (!param->write.is_prep) { ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len); ESP_LOG_BUFFER_HEX(BT_BLE_COEX_TAG, param->write.value, param->write.len); - if (gl_profile_tab[PROFILE_A_APP_ID].descr_handle == param->write.handle && param->write.len == 2){ - uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0]; - if (descr_value == 0x0001){ - if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){ + if (gl_profile_tab[PROFILE_A_APP_ID].descr_handle == param->write.handle && param->write.len == 2) { + uint16_t descr_value = param->write.value[1] << 8 | param->write.value[0]; + if (descr_value == 0x0001) { + if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY) { ESP_LOGI(BT_BLE_COEX_TAG, "notify enable"); uint8_t notify_data[15]; - for (int i = 0; i < sizeof(notify_data); ++i) - { - notify_data[i] = i%0xff; + for (int i = 0; i < sizeof(notify_data); ++i) { + notify_data[i] = i % 0xff; } //the size of notify_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle, - sizeof(notify_data), notify_data, false); + sizeof(notify_data), notify_data, false); } - }else if (descr_value == 0x0002){ - if (a_property & ESP_GATT_CHAR_PROP_BIT_INDICATE){ + } else if (descr_value == 0x0002) { + if (a_property & ESP_GATT_CHAR_PROP_BIT_INDICATE) { ESP_LOGI(BT_BLE_COEX_TAG, "indicate enable"); uint8_t indicate_data[15]; - for (int i = 0; i < sizeof(indicate_data); ++i) - { - indicate_data[i] = i%0xff; + for (int i = 0; i < sizeof(indicate_data); ++i) { + indicate_data[i] = i % 0xff; } //the size of indicate_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle, - sizeof(indicate_data), indicate_data, true); + sizeof(indicate_data), indicate_data, true); } - } - else if (descr_value == 0x0000){ + } else if (descr_value == 0x0000) { ESP_LOGI(BT_BLE_COEX_TAG, "notify/indicate disable "); - }else{ + } else { ESP_LOGE(BT_BLE_COEX_TAG, "unknown descr value"); ESP_LOG_BUFFER_HEX(BT_BLE_COEX_TAG, param->write.value, param->write.len); } @@ -340,7 +342,7 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i break; } case ESP_GATTS_EXEC_WRITE_EVT: - ESP_LOGI(BT_BLE_COEX_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_EXEC_WRITE_EVT"); esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); example_exec_write_event_env(&a_prepare_write_env, param); break; @@ -361,21 +363,21 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, a_property, &gatts_initial_char_val, NULL); - if (add_char_ret){ - ESP_LOGE(BT_BLE_COEX_TAG, "add char failed, error code = 0x%x",add_char_ret); + if (add_char_ret) { + ESP_LOGE(BT_BLE_COEX_TAG, "add char failed, error code = 0x%x", add_char_ret); } break; case ESP_GATTS_ADD_INCL_SRVC_EVT: break; case ESP_GATTS_ADD_CHAR_EVT: { ESP_LOGI(BT_BLE_COEX_TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d", - param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); + param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); gl_profile_tab[PROFILE_A_APP_ID].char_handle = param->add_char.attr_handle; gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16; gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; esp_err_t add_descr_ret = esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid, - ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL); - if (add_descr_ret){ + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL); + if (add_descr_ret) { ESP_LOGE(BT_BLE_COEX_TAG, "add char descr failed, error code = 0x%x", add_descr_ret); } break; @@ -404,7 +406,7 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i break; case ESP_GATTS_CONF_EVT: ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_CONF_EVT, status %d", param->conf.status); - if (param->conf.status != ESP_GATT_OK){ + if (param->conf.status != ESP_GATT_OK) { ESP_LOG_BUFFER_HEX(BT_BLE_COEX_TAG, param->conf.value, param->conf.len); } break; @@ -418,7 +420,8 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i } } -static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { +static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ switch (event) { case ESP_GATTS_REG_EVT: ESP_LOGI(BT_BLE_COEX_TAG, "REGISTER_APP_EVT, status %d, app_id %d", param->reg.status, param->reg.app_id); @@ -445,39 +448,36 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i } case ESP_GATTS_WRITE_EVT: { ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %"PRIu32", handle %d", param->write.conn_id, param->write.trans_id, param->write.handle); - if (!param->write.is_prep){ + if (!param->write.is_prep) { ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len); ESP_LOG_BUFFER_HEX(BT_BLE_COEX_TAG, param->write.value, param->write.len); - if (gl_profile_tab[PROFILE_B_APP_ID].descr_handle == param->write.handle && param->write.len == 2){ - uint16_t descr_value= param->write.value[1]<<8 | param->write.value[0]; - if (descr_value == 0x0001){ - if (b_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){ + if (gl_profile_tab[PROFILE_B_APP_ID].descr_handle == param->write.handle && param->write.len == 2) { + uint16_t descr_value = param->write.value[1] << 8 | param->write.value[0]; + if (descr_value == 0x0001) { + if (b_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY) { ESP_LOGI(BT_BLE_COEX_TAG, "notify enable"); uint8_t notify_data[15]; - for (int i = 0; i < sizeof(notify_data); ++i) - { - notify_data[i] = i%0xff; + for (int i = 0; i < sizeof(notify_data); ++i) { + notify_data[i] = i % 0xff; } //the size of notify_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle, - sizeof(notify_data), notify_data, false); + sizeof(notify_data), notify_data, false); } - }else if (descr_value == 0x0002){ - if (b_property & ESP_GATT_CHAR_PROP_BIT_INDICATE){ + } else if (descr_value == 0x0002) { + if (b_property & ESP_GATT_CHAR_PROP_BIT_INDICATE) { ESP_LOGI(BT_BLE_COEX_TAG, "indicate enable"); uint8_t indicate_data[15]; - for (int i = 0; i < sizeof(indicate_data); ++i) - { - indicate_data[i] = i%0xff; + for (int i = 0; i < sizeof(indicate_data); ++i) { + indicate_data[i] = i % 0xff; } //the size of indicate_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle, - sizeof(indicate_data), indicate_data, true); + sizeof(indicate_data), indicate_data, true); } - } - else if (descr_value == 0x0000){ + } else if (descr_value == 0x0000) { ESP_LOGI(BT_BLE_COEX_TAG, "notify/indicate disable "); - }else{ + } else { ESP_LOGE(BT_BLE_COEX_TAG, "unknown value"); } @@ -487,7 +487,7 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i break; } case ESP_GATTS_EXEC_WRITE_EVT: - ESP_LOGI(BT_BLE_COEX_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_EXEC_WRITE_EVT"); esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); example_exec_write_event_env(&b_prepare_write_env, param); break; @@ -504,12 +504,12 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i esp_ble_gatts_start_service(gl_profile_tab[PROFILE_B_APP_ID].service_handle); b_property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY; - esp_err_t add_char_ret =esp_ble_gatts_add_char( gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].char_uuid, + esp_err_t add_char_ret = esp_ble_gatts_add_char(gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].char_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, b_property, NULL, NULL); - if (add_char_ret){ - ESP_LOGE(BT_BLE_COEX_TAG, "add char failed, error code = 0x%x",add_char_ret); + if (add_char_ret) { + ESP_LOGE(BT_BLE_COEX_TAG, "add char failed, error code = 0x%x", add_char_ret); } break; case ESP_GATTS_ADD_INCL_SRVC_EVT: @@ -547,10 +547,10 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i break; case ESP_GATTS_CONF_EVT: ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_CONF_EVT status %d", param->conf.status); - if (param->conf.status != ESP_GATT_OK){ + if (param->conf.status != ESP_GATT_OK) { ESP_LOG_BUFFER_HEX(BT_BLE_COEX_TAG, param->conf.value, param->conf.len); } - break; + break; case ESP_GATTS_DISCONNECT_EVT: case ESP_GATTS_OPEN_EVT: case ESP_GATTS_CANCEL_OPEN_EVT: @@ -570,8 +570,8 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_ gl_profile_tab[param->reg.app_id].gatts_if = gatts_if; } else { ESP_LOGI(BT_BLE_COEX_TAG, "Reg app failed, app_id %04x, status %d", - param->reg.app_id, - param->reg.status); + param->reg.app_id, + param->reg.status); return; } } @@ -594,27 +594,27 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_ static void ble_gatts_init(void) { esp_err_t ret = esp_ble_gatts_register_callback(gatts_event_handler); - if (ret){ + if (ret) { ESP_LOGE(BT_BLE_COEX_TAG, "gatts register error, error code = 0x%x", ret); return; } ret = esp_ble_gap_register_callback(gap_event_handler); - if (ret){ + if (ret) { ESP_LOGE(BT_BLE_COEX_TAG, "gap register error, error code = 0x%x", ret); return; } ret = esp_ble_gatts_app_register(PROFILE_A_APP_ID); - if (ret){ + if (ret) { ESP_LOGE(BT_BLE_COEX_TAG, "gatts app register error, error code = 0x%x", ret); return; } ret = esp_ble_gatts_app_register(PROFILE_B_APP_ID); - if (ret){ + if (ret) { ESP_LOGE(BT_BLE_COEX_TAG, "gatts app register error, error code = 0x%x", ret); return; } esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500); - if (local_mtu_ret){ + if (local_mtu_ret) { ESP_LOGE(BT_BLE_COEX_TAG, "set local MTU failed, error code = 0x%x", local_mtu_ret); } } @@ -634,44 +634,7 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) { - switch (event) { - /* when authentication completed, this event comes */ - case ESP_BT_GAP_AUTH_CMPL_EVT: { - if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { - ESP_LOGI(BT_BLE_COEX_TAG, "authentication success: %s", param->auth_cmpl.device_name); - ESP_LOG_BUFFER_HEX(BT_BLE_COEX_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); - } else { - ESP_LOGE(BT_BLE_COEX_TAG, "authentication failed, status: %d", param->auth_cmpl.stat); - } - break; - } - -#if (CONFIG_EXAMPLE_A2DP_SINK_SSP_ENABLED == true) - /* when Security Simple Pairing user confirmation requested, this event comes */ - case ESP_BT_GAP_CFM_REQ_EVT: - ESP_LOGI(BT_BLE_COEX_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %06"PRIu32, param->cfm_req.num_val); - esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); - break; - /* when Security Simple Pairing passkey notified, this event comes */ - case ESP_BT_GAP_KEY_NOTIF_EVT: - ESP_LOGI(BT_BLE_COEX_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey: %06"PRIu32, param->key_notif.passkey); - break; - /* when Security Simple Pairing passkey requested, this event comes */ - case ESP_BT_GAP_KEY_REQ_EVT: - ESP_LOGI(BT_BLE_COEX_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); - break; -#endif - - /* when GAP mode changed, this event comes */ - case ESP_BT_GAP_MODE_CHG_EVT: - ESP_LOGI(BT_BLE_COEX_TAG, "ESP_BT_GAP_MODE_CHG_EVT mode: %d", param->mode_chg.mode); - break; - /* others */ - default: { - ESP_LOGI(BT_BLE_COEX_TAG, "event: %d", event); - break; - } - } + bredr_app_gap_evt_def_hdl(event, param); } static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) @@ -738,7 +701,7 @@ void app_main(void) } esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT(); -#if (CONFIG_EXAMPLE_A2DP_SINK_SSP_ENABLED == false) +#if (CONFIG_EXAMPLE_SSP_ENABLED == false) bluedroid_cfg.ssp_en = false; #endif if ((err = esp_bluedroid_init_with_cfg(&bluedroid_cfg)) != ESP_OK) { @@ -751,7 +714,7 @@ void app_main(void) return; } -#if (CONFIG_EXAMPLE_A2DP_SINK_SSP_ENABLED == true) +#if (CONFIG_EXAMPLE_SSP_ENABLED == true) /* set default parameters for Secure Simple Pairing */ esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/sdkconfig.defaults b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/sdkconfig.defaults index a20f726e12..9800abe7ad 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/sdkconfig.defaults @@ -1,8 +1,6 @@ # Override some defaults so BT stack is enabled and # Classic BT is enabled and BT_DRAM_RELEASE is disabled CONFIG_BT_ENABLED=y -CONFIG_BTDM_CTRL_MODE_BLE_ONLY=n -CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n CONFIG_BTDM_CTRL_MODE_BTDM=y CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y CONFIG_BTDM_CTRL_PINNED_TO_CORE_1=n diff --git a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c index 6d9627337b..eeacbfb6d1 100644 --- a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c +++ b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -145,8 +145,8 @@ static esp_ble_adv_data_t adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, - .min_interval = 0x20, - .max_interval = 0x40, + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(40), + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(80), .appearance = 0x00, .manufacturer_len = 0, .p_manufacturer_data = NULL, @@ -162,8 +162,8 @@ static esp_ble_adv_data_t scan_rsp_data = { .set_scan_rsp = true, .include_name = true, .include_txpower = true, - .min_interval = 0x0006, - .max_interval = 0x0010, + .min_interval = ESP_BLE_GAP_CONN_ITVL_MS(7.5), + .max_interval = ESP_BLE_GAP_CONN_ITVL_MS(20), .appearance = 0x00, .manufacturer_len = 0, .p_manufacturer_data = NULL, @@ -176,8 +176,8 @@ static esp_ble_adv_data_t scan_rsp_data = { #endif /* CONFIG_SET_RAW_ADV_DATA */ static esp_ble_adv_params_t adv_params = { - .adv_int_min = 0x20, - .adv_int_max = 0x40, + .adv_int_min = ESP_BLE_GAP_ADV_ITVL_MS(20), + .adv_int_max = ESP_BLE_GAP_ADV_ITVL_MS(40), .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, @@ -215,8 +215,8 @@ static esp_ble_scan_params_t ble_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, + .scan_interval = ESP_BLE_GAP_SCAN_ITVL_MS(50), + .scan_window = ESP_BLE_GAP_SCAN_WIN_MS(30), .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c b/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c index 1f2a6a8399..c8fc988fcb 100644 --- a/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c +++ b/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c @@ -1,7 +1,7 @@ /* * BLE Combined Advertising and Scanning Example. * - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -18,8 +18,10 @@ static const char *TAG = "BLE_ADV_SCAN"; +#define SCAN_LOCAL_NAME_MAX_LEN 32 + typedef struct { - char scan_local_name[32]; + char scan_local_name[SCAN_LOCAL_NAME_MAX_LEN]; uint8_t name_len; } ble_scan_local_name_t; @@ -187,28 +189,58 @@ static void hci_cmd_send_ble_set_adv_data(void) ESP_LOGI(TAG, "Starting BLE advertising with name \"%s\"", adv_name); } -static esp_err_t get_local_name (uint8_t *data_msg, uint8_t data_len, ble_scan_local_name_t *scanned_packet) +static esp_err_t get_local_name(uint8_t *data_msg, uint8_t data_len, ble_scan_local_name_t *scanned_packet) { - uint8_t curr_ptr = 0, curr_len, curr_type; + uint8_t curr_ptr = 0; + + /* Initialize output structure */ + scanned_packet->name_len = 0; + scanned_packet->scan_local_name[0] = '\0'; + while (curr_ptr < data_len) { - curr_len = data_msg[curr_ptr++]; - curr_type = data_msg[curr_ptr++]; + /* Ensure there is at least 1 byte for length field */ + if (curr_ptr >= data_len) { + return ESP_FAIL; + } + uint8_t curr_len = data_msg[curr_ptr++]; + + /* Length of 0 indicates end of AD structures or invalid data */ if (curr_len == 0) { return ESP_FAIL; } - /* Search for current data type and see if it contains name as data (0x08 or 0x09). */ - if (curr_type == 0x08 || curr_type == 0x09) { - for (uint8_t i = 0; i < curr_len - 1; i += 1) { - scanned_packet->scan_local_name[i] = data_msg[curr_ptr + i]; - } - scanned_packet->name_len = curr_len - 1; - return ESP_OK; - } else { - /* Search for next data. Current length includes 1 octate for AD Type (2nd octate). */ - curr_ptr += curr_len - 1; + /* Ensure there is at least 1 byte for type field */ + if (curr_ptr >= data_len) { + return ESP_FAIL; } + uint8_t curr_type = data_msg[curr_ptr++]; + + /* Calculate data field length (curr_len includes type byte) */ + uint8_t data_field_len = curr_len - 1; + + /* Verify remaining buffer has enough data */ + if (curr_ptr + data_field_len > data_len) { + return ESP_FAIL; + } + + /* Check for Local Name type (0x08: Shortened, 0x09: Complete) */ + if (curr_type == 0x08 || curr_type == 0x09) { + /* Limit copy length to prevent buffer overflow */ + uint8_t copy_len = data_field_len; + if (copy_len > SCAN_LOCAL_NAME_MAX_LEN - 1) { + copy_len = SCAN_LOCAL_NAME_MAX_LEN - 1; + } + + memcpy(scanned_packet->scan_local_name, &data_msg[curr_ptr], copy_len); + scanned_packet->scan_local_name[copy_len] = '\0'; /* Ensure null termination */ + scanned_packet->name_len = copy_len; + return ESP_OK; + } + + /* Move to next AD structure */ + curr_ptr += data_field_len; } + return ESP_FAIL; } diff --git a/examples/bluetooth/nimble/ble_ancs/main/main.c b/examples/bluetooth/nimble/ble_ancs/main/main.c index 8ef98e691f..d64dbda751 100644 --- a/examples/bluetooth/nimble/ble_ancs/main/main.c +++ b/examples/bluetooth/nimble/ble_ancs/main/main.c @@ -69,10 +69,10 @@ static ble_uuid128_t data_source = BLE_UUID128_INIT( #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x0e, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'a', 'n', 'c', 's', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x0e, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'a', 'n', 'c', 's', '-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c b/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c index 5ad76841a9..5779b32746 100644 --- a/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c +++ b/examples/bluetooth/nimble/ble_chan_sound_reflector/main/main.c @@ -32,10 +32,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x5B, 0x18, - 0x11, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x5B, 0x18, + 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', }; #endif static const char *tag = "NimBLE_BLE_CHAN_REFLECTOR"; diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c index ef897d132e..24fbb2beff 100644 --- a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c @@ -19,7 +19,7 @@ /* Global constants */ static const char *TAG = "CTE_ADV_EXAMPLE"; -static uint8_t s_periodic_adv_raw_data[] = {0x0D, 0x09, 'C','T','E',' ','P','e','r','i','o','d','i','c'}; +static uint8_t s_periodic_adv_raw_data[] = {0x0D, BLE_HS_ADV_TYPE_COMP_NAME, 'C','T','E',' ','P','e','r','i','o','d','i','c'}; /* Configuration based on Kconfig settings */ #if CONFIG_EXAMPLE_RANDOM_ADDR diff --git a/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c b/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c index 04ee0c3ead..b054ef9ecb 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c @@ -19,10 +19,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x05, 0x18, - 0x12, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'c', 't', 's', '-', 'p', 'r', 'p', 'h', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x05, 0x18, + 0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'c', 't', 's', '-', 'p', 'r', 'p', 'h', '-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c b/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c index 896c1d6fd4..e400a619c6 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c @@ -18,10 +18,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x09, - 0x12, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'h', 't', 'p', '-', 'p', 'r', 'p', 'h', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x09, + 0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'h', 't', 'p', '-', 'p', 'r', 'p', 'h', '-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c index 641a2f43bc..a4e9cb5cef 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c @@ -17,10 +17,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x12, - 0x12, 0X09, 'e', 'x', 't', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'l', '2', 'c', 'o', 'c', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x12, + 0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'e', 'x', 't', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'l', '2', 'c', 'o', 'c', }; #endif diff --git a/examples/bluetooth/nimble/ble_multi_adv/main/main.c b/examples/bluetooth/nimble/ble_multi_adv/main/main.c index 03f93210fd..f7e2483a74 100644 --- a/examples/bluetooth/nimble/ble_multi_adv/main/main.c +++ b/examples/bluetooth/nimble/ble_multi_adv/main/main.c @@ -30,33 +30,33 @@ static void ble_multi_advertise(ble_addr_t addr); /* Advertising patterns */ static uint8_t legacy_dur_adv_pattern[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x12, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'l', 'e', 'g', 'a', 'c', 'y', '-', 'd', 'u', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'l', 'e', 'g', 'a', 'c', 'y', '-', 'd', 'u', 'r' }; static uint8_t scannable_legacy_adv_pattern[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x13, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 's', 'c', 'a', 'n', '-', 'l', 'e', 'g', 'a', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x13, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 's', 'c', 'a', 'n', '-', 'l', 'e', 'g', 'a', 'c', 'y' }; static uint8_t connectable_adv_pattern[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x12, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'c', 'o', 'n', 'n', 'e', 't', 'a', 'b', 'l', 'e' + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x12, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'c', 'o', 'n', 'n', 'e', 't', 'a', 'b', 'l', 'e' }; static uint8_t non_conn_adv_pattern[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x10, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'n', 'o', 'n', '-', 'c', 'o', 'n', 'n' + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x10, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'n', 'o', 'n', '-', 'c', 'o', 'n', 'n' }; /** diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c index c324092aee..d2e626f1af 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c @@ -26,8 +26,8 @@ static const ble_uuid_t *remote_svc_uuid = 0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59); static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x14, 0X09, 'e', 's', 'p', '-', 'b', 'l', 'e', '-', 'r', 'o', 'l', 'e', '-', 'c', 'o', 'e', 'x', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x14, BLE_HS_ADV_TYPE_COMP_NAME, 'e', 's', 'p', '-', 'b', 'l', 'e', '-', 'r', 'o', 'l', 'e', '-', 'c', 'o', 'e', 'x', '-', 'e', }; void ble_store_config_init(void); diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c index e4b0f4686a..e697bfff3f 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c @@ -15,10 +15,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x11, 0X09, 'e', 's', 'p', '-', 'm', 'u', 'l', 't', 'i', '-', 'c', 'o', 'n', 'n', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'e', 's', 'p', '-', 'm', 'u', 'l', 't', 'i', '-', 'c', 'o', 'n', 'n', '-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c b/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c index 4fce3bedb3..915f2b90d1 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c @@ -16,24 +16,24 @@ #include "phy_prph.h" static uint8_t ext_adv_pattern_1M[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0xAB, 0xF2, - 0x0e, 0X09, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', '1', 'M', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xAB, 0xF2, + 0x0e, BLE_HS_ADV_TYPE_COMP_NAME, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', '1', 'M', }; static uint8_t ext_adv_pattern_2M[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0xAB, 0xF2, - 0x0e, 0X09, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', '2', 'M', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xAB, 0xF2, + 0x0e, BLE_HS_ADV_TYPE_COMP_NAME, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', '2', 'M', }; static uint8_t ext_adv_pattern_coded[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0xAB, 0xF2, - 0x11, 0X09, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', 'c', 'o', 'd', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xAB, 0xF2, + 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', 'c', 'o', 'd', 'e', 'd', }; diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c index 336f80c722..9b2190e83d 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c @@ -18,10 +18,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x03, - 0x13, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'p', 'r', 'o', 'x', '-', 'p', 'r', 'p', 'h', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x03, + 0x13, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'p', 'r', 'o', 'x', '-', 'p', 'r', 'p', 'h', '-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/blecent/README.md b/examples/bluetooth/nimble/blecent/README.md index 28ab5061ff..f0efe0eb95 100644 --- a/examples/bluetooth/nimble/blecent/README.md +++ b/examples/bluetooth/nimble/blecent/README.md @@ -61,6 +61,14 @@ idf.py menuconfig In the `Example Configuration` menu: * Change the `Peer Address` option if needed. +* Optional: enable static passkey support via `Component config -> Bluetooth -> NimBLE -> Enable support for Static Passkey`. + +Static passkey mode is useful for demos where you want to avoid interactive passkey entry. +When enabled, the example calls `ble_sm_configure_static_passkey(456789, true)` and NimBLE +automatically injects the passkey during pairing. Update the passkey in +`examples/bluetooth/nimble/blecent/main/main.c` if you want a different value. +Both devices must use the same 6-digit passkey, and you should only use a fixed +passkey for development or controlled environments. ### Build and Flash diff --git a/examples/bluetooth/nimble/blecent/main/main.c b/examples/bluetooth/nimble/blecent/main/main.c index b73ebe974f..652cbe05fe 100644 --- a/examples/bluetooth/nimble/blecent/main/main.c +++ b/examples/bluetooth/nimble/blecent/main/main.c @@ -1098,6 +1098,10 @@ app_main(void) ble_hs_cfg.store_status_cb = ble_store_util_status_rr; #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(STATIC_PASSKEY) + ble_sm_configure_static_passkey(456789, true); +#endif + int rc; /* Initialize data structures to track connected peers. */ #if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) diff --git a/examples/bluetooth/nimble/blecsc/main/main.c b/examples/bluetooth/nimble/blecsc/main/main.c index 73c30906d9..c146c986c5 100644 --- a/examples/bluetooth/nimble/blecsc/main/main.c +++ b/examples/bluetooth/nimble/blecsc/main/main.c @@ -31,10 +31,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x10, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'c', 's', 'c','-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x10, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'c', 's', 'c','-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/bleprph/README.md b/examples/bluetooth/nimble/bleprph/README.md index 390cbbc8d5..b1b64f47f9 100644 --- a/examples/bluetooth/nimble/bleprph/README.md +++ b/examples/bluetooth/nimble/bleprph/README.md @@ -41,6 +41,14 @@ In the `Example Configuration` menu: * Select I/O capabilities of device from `Example Configuration --> I/O Capability`, default is `Just_works`. * Enable/Disable other security related parameters `Bonding, MITM option, secure connection(SM SC)`. +* Optional: enable static passkey support via `Component config -> Bluetooth -> NimBLE -> Enable support for Static Passkey`. + +Static passkey mode is useful for demos where you want to avoid interactive passkey entry. +When enabled, the example calls `ble_sm_configure_static_passkey(456789, true)` and NimBLE +automatically injects the passkey during pairing. Update the passkey in +`examples/bluetooth/nimble/bleprph/main/main.c` if you want a different value. +Both devices must use the same 6-digit passkey, and you should only use a fixed +passkey for development or controlled environments. ### Build and Flash diff --git a/examples/bluetooth/nimble/bleprph/main/main.c b/examples/bluetooth/nimble/bleprph/main/main.c index d0eb370709..af47c35424 100644 --- a/examples/bluetooth/nimble/bleprph/main/main.c +++ b/examples/bluetooth/nimble/bleprph/main/main.c @@ -30,10 +30,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x11, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', }; #endif @@ -599,6 +599,10 @@ app_main(void) ble_hs_cfg.sm_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ID; #endif +#if MYNEWT_VAL(STATIC_PASSKEY) && NIMBLE_BLE_CONNECT + ble_sm_configure_static_passkey(456789, true); +#endif + #if MYNEWT_VAL(BLE_GATTS) rc = gatt_svr_init(); assert(rc == 0); diff --git a/examples/bluetooth/nimble/bleprph_host_only/main/main.c b/examples/bluetooth/nimble/bleprph_host_only/main/main.c index a03b3157ea..9523937350 100644 --- a/examples/bluetooth/nimble/bleprph_host_only/main/main.c +++ b/examples/bluetooth/nimble/bleprph_host_only/main/main.c @@ -18,10 +18,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x11, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/power_save/main/main.c b/examples/bluetooth/nimble/power_save/main/main.c index 0e7e9bcf5b..790f0f7489 100644 --- a/examples/bluetooth/nimble/power_save/main/main.c +++ b/examples/bluetooth/nimble/power_save/main/main.c @@ -41,10 +41,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0x18, 0x11, - 0x11, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x18, 0x11, + 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'e', }; #endif diff --git a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c index e15042207f..db9c525978 100644 --- a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c @@ -19,10 +19,10 @@ #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern[] = { - 0x02, 0x01, 0x06, - 0x03, 0x03, 0xab, 0xcd, - 0x03, 0x03, 0xAB, 0xF2, - 0x0e, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h' + 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, + 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xAB, 0xF2, + 0x0e, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h' }; static uint8_t s_current_phy; diff --git a/examples/build_system/cmake/multi_config/README.md b/examples/build_system/cmake/multi_config/README.md index ddf11e894e..1e036f01de 100644 --- a/examples/build_system/cmake/multi_config/README.md +++ b/examples/build_system/cmake/multi_config/README.md @@ -89,14 +89,14 @@ You can further enhance your build process by using configuration profile files. You can use these profile files to quickly set up the build environment with specific configurations. -- To build with the production profile: `idf.py @profiles/prod build` -- To build with the debug profile: `idf.py @profiles/debug build` +- To build with the production profile: `idf.py "@profiles/prod" build` +- To build with the debug profile: `idf.py "@profiles/debug" build` This approach simplifies the process of specifying complex command-line arguments and allows for greater flexibility in managing different build scenarios. Moreover, you can combine arguments from a profile file with additional command line arguments. Anywhere on the idf.py command line, you can specify a file as @filename.txt to read one or more arguments from the text file. Arguments in the file can be separated by newlines or spaces and are expanded exactly as if they had appeared in that order on the idf.py command line. -For example using [cutom_flash.txt](custom_flash.txt), you can expand the command: `idf.py -B build_production @custom_flash.txt monitor` +For example using [cutom_flash.txt](custom_flash.txt), you can expand the command: `idf.py -B build_production "@custom_flash.txt" monitor` ### Generated `sdkconfig` file diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index 7cfcca642b..c9bb84eff0 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -97,6 +97,7 @@ void app_main(void) #if CONFIG_OPENTHREAD_CLI ot_console_start(); + ot_register_external_commands(); #endif #if CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE @@ -113,7 +114,6 @@ void app_main(void) }; ESP_ERROR_CHECK(esp_openthread_start(&config)); - esp_netif_set_default_netif(esp_openthread_get_netif()); #if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION esp_cli_custom_command_init(); #endif @@ -123,6 +123,9 @@ void app_main(void) ESP_ERROR_CHECK(esp_coex_wifi_i154_enable()); #endif #endif +#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE + ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); +#endif #if CONFIG_OPENTHREAD_NETWORK_AUTO_START ot_network_auto_start(); #endif diff --git a/examples/openthread/ot_br/main/idf_component.yml b/examples/openthread/ot_br/main/idf_component.yml index b00b26c7bb..3dca30645e 100644 --- a/examples/openthread/ot_br/main/idf_component.yml +++ b/examples/openthread/ot_br/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.4.0" + version: "~2.0.0" espressif/mdns: "^1.0.3" ## Required IDF version idf: diff --git a/examples/openthread/ot_cli/README.md b/examples/openthread/ot_cli/README.md index 4ffe0a0131..ca7f2611a0 100644 --- a/examples/openthread/ot_cli/README.md +++ b/examples/openthread/ot_cli/README.md @@ -128,5 +128,49 @@ You can refer to the [extension command](https://github.com/espressif/esp-thread The following examples are supported by `ot_cli`: * TCP and UDP Example -* Iperf Example +## Using iPerf to measure bandwidth + +iPerf is a tool used to obtain TCP or UDP throughput on the Thread network. To run iPerf, you need to have two Thread devices on the same network. + +Refer to [the iperf-cmd component](https://components.espressif.com/components/espressif/iperf-cmd) for details on specific configurations. + +### Typical usage on a thread network + +For measuring the TCP throughput, first create an iperf service on one node: +```bash +> iperf -V -s -t 20 -i 3 -p 5001 -f k +Done +``` + +Then create an iperf client connecting to the service on another node. Note that the [ML-EID](https://openthread.io/guides/thread-primer/ipv6-addressing#unicast_address_types) address is used for iperf. + +```bash +> ipaddr mleid +fdde:ad00:beef:0:a7c6:6311:9c8c:271b +Done + +> iperf -V -c fdde:ad00:beef:0:a7c6:6311:9c8c:271b -t 20 -i 1 -p 5001 -l 85 -f k +Done +[ ID] Interval Transfer Bandwidth +[ 1] 0.0- 1.0 sec 3.15 KBytes 25.16 Kbits/sec +[ 1] 1.0- 2.0 sec 2.89 KBytes 23.12 Kbits/sec +[ 1] 2.0- 3.0 sec 2.98 KBytes 23.80 Kbits/sec +... +[ 1] 9.0-10.0 sec 2.55 KBytes 20.40 Kbits/sec +[ 1] 0.0-10.0 sec 27.80 KBytes 22.24 Kbits/sec +``` + +For measuring the UDP throughput, first create an iperf service similarly: + +```bash +> iperf -V -u -s -t 20 -i 3 -p 5001 -f k +Done +``` + +Then create an iperf client: + +```bash +> iperf -V -u -c fdde:ad00:beef:0:a7c6:6311:9c8c:271b -t 20 -i 1 -p 5001 -l 85 -f k +Done +``` diff --git a/examples/openthread/ot_cli/main/esp_ot_cli.c b/examples/openthread/ot_cli/main/esp_ot_cli.c index ee83bcc22d..44a7d1abe8 100644 --- a/examples/openthread/ot_cli/main/esp_ot_cli.c +++ b/examples/openthread/ot_cli/main/esp_ot_cli.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -58,6 +58,7 @@ void app_main(void) #if CONFIG_OPENTHREAD_CLI ot_console_start(); + ot_register_external_commands(); #endif static esp_openthread_config_t config = { @@ -73,6 +74,9 @@ void app_main(void) #if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION esp_cli_custom_command_init(); #endif +#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE + ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); +#endif #if CONFIG_OPENTHREAD_NETWORK_AUTO_START ot_network_auto_start(); #endif diff --git a/examples/openthread/ot_cli/main/idf_component.yml b/examples/openthread/ot_cli/main/idf_component.yml index 079266490f..49621895d6 100644 --- a/examples/openthread/ot_cli/main/idf_component.yml +++ b/examples/openthread/ot_cli/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.4.0" + version: "~2.0.0" idf: version: ">=4.1.0" ot_led: diff --git a/examples/openthread/ot_common_components/ot_examples_common/CMakeLists.txt b/examples/openthread/ot_common_components/ot_examples_common/CMakeLists.txt index 321063eb94..b78a93b927 100644 --- a/examples/openthread/ot_common_components/ot_examples_common/CMakeLists.txt +++ b/examples/openthread/ot_common_components/ot_examples_common/CMakeLists.txt @@ -15,5 +15,5 @@ endif() idf_component_register( SRCS "${srcs}" INCLUDE_DIRS "include" - PRIV_REQUIRES console cmd_system esp_coex openthread + PRIV_REQUIRES console cmd_system esp_coex openthread iperf-cmd iperf ) diff --git a/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild b/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild index 94e38cf6c1..0bca5c2987 100644 --- a/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild +++ b/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild @@ -9,6 +9,16 @@ menu "Config for OpenThread Examples" If enabled, the Openthread Device will create or connect to Thread network with pre-configured network parameters automatically. Otherwise, user need to configure Thread via CLI command manually. + menu "External Console Commands" + config OPENTHREAD_IPERF_CMD_ENABLE + bool "Enable iperf command" + depends on OPENTHREAD_FTD || OPENTHREAD_MTD + default y + help + If enabled, iperf will be registered and available as a console command. + This allows network performance testing using iperf over the Thread network. + endmenu # External Console Commands + menu "External coexist wire type and pin config" depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE diff --git a/examples/openthread/ot_common_components/ot_examples_common/idf_component.yml b/examples/openthread/ot_common_components/ot_examples_common/idf_component.yml index 77b231f2a7..64b8f724c2 100644 --- a/examples/openthread/ot_common_components/ot_examples_common/idf_component.yml +++ b/examples/openthread/ot_common_components/ot_examples_common/idf_component.yml @@ -1,4 +1,5 @@ ## IDF Component Manager Manifest File dependencies: + espressif/iperf-cmd: "^1.0.0" cmd_system: path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system diff --git a/examples/openthread/ot_common_components/ot_examples_common/include/ot_examples_common.h b/examples/openthread/ot_common_components/ot_examples_common/include/ot_examples_common.h index 9c7ab22964..0c5c298c09 100644 --- a/examples/openthread/ot_common_components/ot_examples_common/include/ot_examples_common.h +++ b/examples/openthread/ot_common_components/ot_examples_common/include/ot_examples_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -61,3 +61,9 @@ void ot_console_start(void); * */ void ot_network_auto_start(void); + +/** + * @brief Register external system commands (e.g., iperf). + * + */ +void ot_register_external_commands(void); diff --git a/examples/openthread/ot_common_components/ot_examples_common/ot_console.c b/examples/openthread/ot_common_components/ot_examples_common/ot_console.c index a293adf38c..6c679941d3 100644 --- a/examples/openthread/ot_common_components/ot_examples_common/ot_console.c +++ b/examples/openthread/ot_common_components/ot_examples_common/ot_console.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -18,6 +18,10 @@ #include "esp_console.h" #include "cmd_system.h" +#if CONFIG_OPENTHREAD_IPERF_CMD_ENABLE +#include "iperf_cmd.h" +#endif + void ot_console_start(void) { esp_console_repl_t *repl = NULL; @@ -43,6 +47,12 @@ void ot_console_start(void) #error Unsupported console type #endif ESP_ERROR_CHECK(esp_console_start_repl(repl)); - - register_system(); +} + +void ot_register_external_commands(void) +{ + register_system(); +#if CONFIG_OPENTHREAD_IPERF_CMD_ENABLE + iperf_cmd_register_iperf(); +#endif } diff --git a/examples/openthread/ot_trel/main/esp_ot_trel.c b/examples/openthread/ot_trel/main/esp_ot_trel.c index d45b211b7b..5ffd6dc610 100644 --- a/examples/openthread/ot_trel/main/esp_ot_trel.c +++ b/examples/openthread/ot_trel/main/esp_ot_trel.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -44,7 +44,6 @@ #include "esp_ot_cli_extension.h" #endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - #define TAG "ot_esp_trel" void app_main(void) @@ -68,6 +67,7 @@ void app_main(void) #if CONFIG_OPENTHREAD_CLI ot_console_start(); + ot_register_external_commands(); #endif static esp_openthread_config_t config = { @@ -83,6 +83,9 @@ void app_main(void) #if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION esp_cli_custom_command_init(); #endif +#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE + ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); +#endif #if CONFIG_OPENTHREAD_NETWORK_AUTO_START ot_network_auto_start(); #endif diff --git a/examples/openthread/ot_trel/main/idf_component.yml b/examples/openthread/ot_trel/main/idf_component.yml index 4318a41630..cb9759faca 100644 --- a/examples/openthread/ot_trel/main/idf_component.yml +++ b/examples/openthread/ot_trel/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.4.0" + version: "~2.0.0" espressif/mdns: "^1.0.3" idf: version: ">=4.1.0" diff --git a/examples/peripherals/i2s/i2s_advance/i2s_usb/main/i2s_usb_example_main.c b/examples/peripherals/i2s/i2s_advance/i2s_usb/main/i2s_usb_example_main.c index bf66f0d52b..2f1e8c2909 100644 --- a/examples/peripherals/i2s/i2s_advance/i2s_usb/main/i2s_usb_example_main.c +++ b/examples/peripherals/i2s/i2s_advance/i2s_usb/main/i2s_usb_example_main.c @@ -236,6 +236,11 @@ static esp_err_t usb_uac_device_input_cb(uint8_t *buf, size_t len, size_t *bytes return ESP_FAIL; } + /* Report full-length data for UAC */ + if (bytes_read) { + *bytes_read = len; + } + return ESP_OK; } diff --git a/examples/peripherals/spi_master/lcd/main/Kconfig.projbuild b/examples/peripherals/spi_master/lcd/main/Kconfig.projbuild index bab78fc6bf..6a341da771 100644 --- a/examples/peripherals/spi_master/lcd/main/Kconfig.projbuild +++ b/examples/peripherals/spi_master/lcd/main/Kconfig.projbuild @@ -23,4 +23,13 @@ menu "Example Configuration" in practice the driver chips work fine with a higher clock rate, and using that gives a better framerate. Select this to try using the out-of-spec clock rate. + config LCD_BUFFER_IN_PSRAM + bool + prompt "Malloc LCD buffer from PSRAM, it can save internal RAM" + depends on SPIRAM && SOC_PSRAM_DMA_CAPABLE + default "y" + help + Driver is now support using PSRAM memory as LCD buffer directly + without additional internal copy, using it is able to save internal + memory space, and without CPU cost. endmenu diff --git a/examples/peripherals/spi_master/lcd/main/pretty_effect.c b/examples/peripherals/spi_master/lcd/main/pretty_effect.c index 9ccd6fd020..bce1d1c8a3 100644 --- a/examples/peripherals/spi_master/lcd/main/pretty_effect.c +++ b/examples/peripherals/spi_master/lcd/main/pretty_effect.c @@ -19,6 +19,10 @@ uint16_t *pixels; //Grab a rgb16 pixel from the esp32_tiles image static inline uint16_t get_bgnd_pixel(int x, int y) { + // Clamp coordinates to valid image bounds + x = (x < 0) ? 0 : (x >= IMAGE_W) ? IMAGE_W - 1 : x; + y = (y < 0) ? 0 : (y >= IMAGE_H) ? IMAGE_H - 1 : y; + //Get color of the pixel on x,y coords return (uint16_t) * (pixels + (y * IMAGE_W) + x); } @@ -26,7 +30,7 @@ static inline uint16_t get_bgnd_pixel(int x, int y) //This variable is used to detect the next frame. static int prev_frame = -1; -//Instead of calculating the offsets for each pixel we grab, we pre-calculate the valueswhenever a frame changes, then re-use +//Instead of calculating the offsets for each pixel we grab, we pre-calculate the valueswhenever a frame changes, then reuse //these as we go through all the pixels in the frame. This is much, much faster. static int8_t xofs[320], yofs[240]; static int8_t xcomp[320], ycomp[240]; diff --git a/examples/peripherals/spi_master/lcd/main/spi_master_example_main.c b/examples/peripherals/spi_master/lcd/main/spi_master_example_main.c index 498a83e1a1..f0e33bf428 100644 --- a/examples/peripherals/spi_master/lcd/main/spi_master_example_main.c +++ b/examples/peripherals/spi_master/lcd/main/spi_master_example_main.c @@ -343,7 +343,11 @@ static void send_lines(spi_device_handle_t spi, int ypos, uint16_t *linedata) trans[4].tx_data[0] = 0x2C; //memory write trans[5].tx_buffer = linedata; //finally send the line data trans[5].length = 320 * 2 * 8 * PARALLEL_LINES; //Data length, in bits +#if CONFIG_LCD_BUFFER_IN_PSRAM + trans[5].flags = SPI_TRANS_DMA_USE_PSRAM; //using PSRAM +#else trans[5].flags = 0; //undo SPI_TRANS_USE_TXDATA flag +#endif //Queue all transactions. for (x = 0; x < 6; x++) { @@ -375,9 +379,17 @@ static void send_line_finish(spi_device_handle_t spi) static void display_pretty_colors(spi_device_handle_t spi) { uint16_t *lines[2]; +#if CONFIG_LCD_BUFFER_IN_PSRAM + uint32_t mem_cap = MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA; + printf("Get LCD buffer from PSRAM\n"); +#else + uint32_t mem_cap = MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA; + printf("Get LCD buffer from internal\n"); +#endif + //Allocate memory for the pixel buffers for (int i = 0; i < 2; i++) { - lines[i] = spi_bus_dma_memory_alloc(LCD_HOST, 320 * PARALLEL_LINES * sizeof(uint16_t), 0); + lines[i] = spi_bus_dma_memory_alloc(LCD_HOST, 320 * PARALLEL_LINES * sizeof(uint16_t), mem_cap); assert(lines[i] != NULL); } int frame = 0; diff --git a/examples/peripherals/touch_sensor/touch_sens_sleep/main/touch_sens_sleep.c b/examples/peripherals/touch_sensor/touch_sens_sleep/main/touch_sens_sleep.c index 7b2c3aa293..d363a932cf 100644 --- a/examples/peripherals/touch_sensor/touch_sens_sleep/main/touch_sens_sleep.c +++ b/examples/peripherals/touch_sensor/touch_sens_sleep/main/touch_sens_sleep.c @@ -13,11 +13,11 @@ static const char *TAG = "touch_wakeup"; #define EXAMPLE_TOUCH_SAMPLE_CFG_NUM 1 -#define EXAMPLE_TOUCH_CHANNEL_NUM 3 +#define EXAMPLE_TOUCH_CHANNEL_NUM 2 #define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3 // If you want to change the wake-up channels, please make sure the channel GPIOs won't conflict to the EXT wakeup GPIOs -static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {7, 8, 9}; +static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {8, 9}; // Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio)) static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = { diff --git a/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py b/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py index 6228462e5e..21c40d7ef6 100644 --- a/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py +++ b/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py @@ -7,6 +7,14 @@ from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'deep_sleep', + 'light_sleep', + ], + indirect=True, +) @idf_parametrize( 'target', soc_filtered_targets('SOC_TOUCH_SENSOR_SUPPORTED == 1 and SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP == 1'), diff --git a/examples/phy/.build-test-rules.yml b/examples/phy/.build-test-rules.yml index 3e70012edf..3ebe78f56e 100644 --- a/examples/phy/.build-test-rules.yml +++ b/examples/phy/.build-test-rules.yml @@ -2,9 +2,9 @@ examples/phy/antenna: disable: - - if: IDF_TARGET in ["esp32c5", "esp32c61", "esp32h21", "esp32h4"] + - if: IDF_TARGET in ["esp32c61", "esp32h21", "esp32h4"] temporary: true - reason: not supported yet # TODO: [ESP32C5] IDF-8851, [esp32c61] IDF-9859, [esp32h21] IDF-12041, [ESP32H4] IDF-12716 + reason: not supported yet # TODO: [esp32c61] IDF-9859, [esp32h21] IDF-12041, [ESP32H4] IDF-12716 - if: IDF_TARGET in ["esp32p4", "esp32h2"] reason: not supported examples/phy/cert_test: @@ -13,4 +13,4 @@ examples/phy/cert_test: reason: not supported - if: IDF_TARGET in ["esp32c61", "esp32h21", "esp32h4"] temporary: true - reason: not supported yet # TODO: [ESP32C5] IDF-8851, [esp32c61] IDF-9859, [esp32h21] IDF-12041, [ESP32H4] IDF-12716 + reason: not supported yet # TODO: [esp32c61] IDF-9859, [esp32h21] IDF-12041, [ESP32H4] IDF-12716 diff --git a/examples/phy/antenna/README.md b/examples/phy/antenna/README.md index 8551b80717..d060d6ba53 100644 --- a/examples/phy/antenna/README.md +++ b/examples/phy/antenna/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # Wi-Fi antenna soft switch Example diff --git a/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt b/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt index 055d4c563a..e6d6094e5b 100644 --- a/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt +++ b/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt esp_netif + PRIV_REQUIRES mqtt esp_netif nvs_flash INCLUDE_DIRS ".") diff --git a/examples/storage/sd_card/sdspi/README.md b/examples/storage/sd_card/sdspi/README.md index 284d922aa5..09be26421b 100644 --- a/examples/storage/sd_card/sdspi/README.md +++ b/examples/storage/sd_card/sdspi/README.md @@ -236,3 +236,15 @@ In the absence of connected pullups and having the weak pullups enabled, you can It will also provide the voltage levels at the corresponding SD pins. By default, this information is provided for ESP32 chip only, and for other chipsets, verify the availability of ADC pins for the respective GPIO using [this](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html#gpio-summary) and configure ADC mapped pins using menuconfig. Then test the voltage levels accordingly. You can monitor the voltage levels of individual pins using `PIN voltage levels` and `PIN voltage levels with weak pullup`. However, if one pin being pulled low and experiencing interference with another pin, you can detect it through `PIN cross-talk` and `PIN cross-talk with weak pullup`. In the absence of pullups, voltage levels at each pin should range from 0 to 0.3V. With 10k pullups connected, the voltage will be between 3.1V to 3.3V, contingent on the connection between ADC pins and SD pins, and with weak pullups connected, it can fluctuate between 0.8V to 1.2V, depending on pullup strength. + +### Slow performance / low throughput (no or incorrect pull-up resistor on MISO line) + +The current driver implementation waits for the MISO line to be high before sending the next transaction. This is the correct behavior and fixes certain issues especially when there are more SPI devices connected to same SPI bus. However this can slow down SD throughput on boards lacking a sufficiently strong pull-up resistor on the MISO line. + +If you experience this slowdown, you can try adding the following line. Modifying this value can cause problems in certain scenarios (e.g. SD card and another device like TFT screen sharing the same SPI bus resulting in failed communication with SD card), so please use it with caution. + +```c + sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT() + slot_config.wait_for_miso = -1; // <--- Add this line + // If this causes problems, try to set the value higher (-1: no waiting (0ms); 0: default value (40ms); 1-127: timeout in ms; else: invalid value, default will be used) +``` diff --git a/examples/system/esp_timer/main/esp_timer_example_main.c b/examples/system/esp_timer/main/esp_timer_example_main.c index 54183cb8a3..30da583018 100644 --- a/examples/system/esp_timer/main/esp_timer_example_main.c +++ b/examples/system/esp_timer/main/esp_timer_example_main.c @@ -71,7 +71,6 @@ void app_main(void) int64_t t2 = esp_timer_get_time(); ESP_LOGI(TAG, "Woke up from light sleep, time since boot: %lld us", t2); - // TODO: PM-232 assert(((t2 - t1 - 500000) < 1000) && ((t2 - t1 - 500000) > -2000)); #endif diff --git a/examples/system/esp_timer/sdkconfig.defaults b/examples/system/esp_timer/sdkconfig.defaults index c4a1e55cf8..dfd208c65a 100644 --- a/examples/system/esp_timer/sdkconfig.defaults +++ b/examples/system/esp_timer/sdkconfig.defaults @@ -3,4 +3,7 @@ CONFIG_ESP_TIMER_PROFILING=y # NEWLIB_NANO_FORMAT is enabled by default on ESP32-C2 # This example needs 64-bit integer formatting, this is why this option is disabled -CONFIG_NEWLIB_NANO_FORMAT=n +CONFIG_LIBC_NEWLIB_NANO_FORMAT=n + +# Put sleep related source code in IRAM +CONFIG_PM_SLP_IRAM_OPT=y diff --git a/tools/ci/idf_pytest/constants.py b/tools/ci/idf_pytest/constants.py index 9e1d354dff..17f107258e 100644 --- a/tools/ci/idf_pytest/constants.py +++ b/tools/ci/idf_pytest/constants.py @@ -150,6 +150,7 @@ ENV_MARKERS = { 'esp32c2eco4': 'esp32c2 major version(v2.0) chips', 'recovery_bootloader': 'Runner with recovery bootloader offset set in eFuse', 'esp32p4_eco4': 'Runner with esp32p4 eco4 connected', + 'esp32c5_eco3': 'Runner with esp32c5 eco3 connected', } # by default the timeout is 1h, for some special cases we need to extend it diff --git a/tools/test_apps/configs/sdkconfig.flash_auto_suspend_iram_reduction b/tools/test_apps/configs/sdkconfig.flash_auto_suspend_iram_reduction index 0e1236fa14..09019098d4 100644 --- a/tools/test_apps/configs/sdkconfig.flash_auto_suspend_iram_reduction +++ b/tools/test_apps/configs/sdkconfig.flash_auto_suspend_iram_reduction @@ -72,6 +72,8 @@ CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=n # System common CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=n +CONFIG_RTC_CLK_FUNC_IN_IRAM=n +CONFIG_RTC_TIME_FUNC_IN_IRAM=n # Phy related options CONFIG_ESP_PHY_IRAM_OPT=n diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c5_rev102 b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c5_rev102 new file mode 100644 index 0000000000..8aa5053fc7 --- /dev/null +++ b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c5_rev102 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c5" +CONFIG_ESP32C5_REV_MIN_102=y diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.esp32c61_rev101 b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c61_rev101 new file mode 100644 index 0000000000..7b69fea537 --- /dev/null +++ b/tools/test_apps/system/build_test/sdkconfig.ci.esp32c61_rev101 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c61" +CONFIG_ESP32C61_REV_MIN_101=y