diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index 659eedea2b..491943a5a5 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -166,6 +166,7 @@ - "components/heap/tlsf" - "components/bt/controller/lib_esp32c6/esp32c6-bt-lib" - "components/bt/controller/lib_esp32c5/esp32c5-bt-lib" + - "components/bt/controller/lib_esp32h4/esp32h4-bt-lib" - "components/bt/esp_ble_mesh/lib/lib" - ".gitmodules" diff --git a/.gitmodules b/.gitmodules index 54d3cd6c8d..5975009eb5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -116,6 +116,11 @@ url = ../../espressif/esp32h2-bt-lib.git shallow = true +[submodule "components/bt/controller/lib_esp32h4/esp32h4-bt-lib"] + path = components/bt/controller/lib_esp32h4/esp32h4-bt-lib + url = ../../espressif/esp32h4-bt-lib.git + shallow = true + [submodule "components/bt/controller/lib_esp32c2/esp32c2-bt-lib"] path = components/bt/controller/lib_esp32c2/esp32c2-bt-lib url = ../../espressif/esp32c2-bt-lib.git diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 1701603b9a..dd87982bcb 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -105,9 +105,15 @@ if(CONFIG_BT_ENABLED) list(APPEND priv_include_dirs common/btc/include common/include + ) + + if(NOT CONFIG_BT_DUAL_MODE_ARCH) + list(APPEND priv_include_dirs porting/mem/ porting/include ) + endif() + list(APPEND include_dirs ${common_include_dirs}) list(APPEND srcs "common/btc/core/btc_alarm.c" @@ -672,7 +678,22 @@ if(CONFIG_BT_ENABLED) endif() endif() - if(CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT) + if(CONFIG_BT_DUAL_MODE_ARCH) + add_subdirectory(porting_btdm) + list(APPEND srcs + ${porting_btdm_srcs} + ) + + if(CONFIG_BT_NIMBLE_ENABLED) + list(APPEND srcs + "host/nimble/nimble/nimble/transport/esp_ipc_btdm/src/hci_esp_ipc.c" + ) + endif() + + list(APPEND include_dirs + ${porting_btdm_include_dirs} + ) + elseif(CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT) list(APPEND srcs "porting/npl/freertos/src/npl_os_freertos.c" "porting/mem/os_msys_init.c" @@ -867,9 +888,21 @@ if(CONFIG_BT_ENABLED) list(APPEND srcs "host/nimble/nimble/porting/nimble/src/nimble_port.c" - "host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c" "host/nimble/port/src/nvs_port.c" + "host/nimble/port/src/esp_nimble_mem.c" ) + if(CONFIG_BT_DUAL_MODE_ARCH) + list(APPEND srcs + "host/nimble/nimble/porting/npl/esp-idf/src/nimble_port_freertos.c" + ) + list(APPEND include_dirs + "host/nimble/nimble/porting/npl/esp-idf/include" + ) + else() + list(APPEND srcs + "host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c" + ) + endif() list(APPEND include_dirs host/nimble/nimble/porting/nimble/include @@ -884,7 +917,7 @@ if(CONFIG_BT_ENABLED) ) endif() - if(NOT CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT) + if((NOT CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT) AND (NOT CONFIG_BT_DUAL_MODE_ARCH)) list(APPEND srcs "host/nimble/nimble/porting/nimble/src/endian.c" "porting/mem/os_mempool.c" @@ -1087,6 +1120,12 @@ if(CONFIG_BT_ENABLED) endif() endif() target_link_libraries(${COMPONENT_LIB} PRIVATE libble_app) + + if(CONFIG_BT_DUAL_MODE_ARCH) + add_prebuilt_library(libbtdm_common + "controller/lib_${target_name}/${target_name}-bt-lib/libbtdm_common.a") + target_link_libraries(${COMPONENT_LIB} PRIVATE libbtdm_common) + endif() endif() set_source_files_properties( diff --git a/components/bt/controller/esp32h4/Kconfig.ble.in b/components/bt/controller/esp32h4/Kconfig.ble.in new file mode 100644 index 0000000000..4ab95400b3 --- /dev/null +++ b/components/bt/controller/esp32h4/Kconfig.ble.in @@ -0,0 +1,739 @@ + +menuconfig BT_LE_50_FEATURE_SUPPORT + bool "Enable BLE 5 feature" + depends on !BT_NIMBLE_ENABLED + default y + help + Enable BLE 5 feature + +config BT_LE_LL_CFG_FEAT_LE_2M_PHY + bool "Enable 2M Phy" + depends on BT_LE_50_FEATURE_SUPPORT + default y + help + Enable 2M-PHY + +config BT_LE_LL_CFG_FEAT_LE_CODED_PHY + bool "Enable coded Phy" + depends on BT_LE_50_FEATURE_SUPPORT + default y + help + Enable coded-PHY + +config BT_LE_EXT_ADV + bool "Enable extended advertising" + depends on BT_LE_50_FEATURE_SUPPORT + default y + help + Enable this option to do extended advertising. Extended advertising + will be supported from BLE 5.0 onwards. + +if BT_LE_EXT_ADV + config BT_LE_MAX_EXT_ADV_INSTANCES + int "Maximum number of extended advertising instances." + range 0 4 + default 1 + depends on BT_LE_EXT_ADV + help + Change this option to set maximum number of extended advertising + instances. Minimum there is always one instance of + advertising. Enter how many more advertising instances you + want. + Each extended advertising instance will take about 0.5k DRAM. + + config BT_LE_EXT_ADV_MAX_SIZE + int "Maximum length of the advertising data." + range 0 1650 + default 1650 + depends on BT_LE_EXT_ADV + help + Defines the length of the extended adv data. The value should not + exceed 1650. + + config BT_LE_ENABLE_PERIODIC_ADV + bool "Enable periodic advertisement." + default y + depends on BT_LE_EXT_ADV + help + Enable this option to start periodic advertisement. + + config BT_LE_PERIODIC_ADV_SYNC_TRANSFER + bool "Enable Transfer Sync Events" + depends on BT_LE_ENABLE_PERIODIC_ADV + default y + help + This enables controller transfer periodic sync events to host + +endif + +config BT_LE_MAX_PERIODIC_SYNCS + int "Maximum number of periodic advertising syncs" + depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED + + range 0 8 + default 1 if BT_LE_ENABLE_PERIODIC_ADV + default 0 + help + Set this option to set the upper limit for number of periodic sync + connections. This should be less than maximum connections allowed by + controller. + +config BT_LE_MAX_PERIODIC_ADVERTISER_LIST + int "Maximum number of periodic advertiser list" + depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED + range 1 5 + default 5 + help + Set this option to set the upper limit for number of periodic advertiser list. + +config BT_LE_POWER_CONTROL_ENABLED + bool "Enable controller support for BLE Power Control" + depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED + default n + help + Set this option to enable the Power Control feature on controller + +menuconfig BT_LE_ISO_SUPPORT + bool "Enable BLE ISO feature" + default n + help + Support BLE 5.2 ISO feature + +config BT_LE_ISO_FRA_UNSEG + bool "Enable Unsegmented mode for Framed PDU" + depends on BT_LE_ISO_SUPPORT + help + Enable this to support the Framed Unsegmented mode. + +config BT_LE_ISO_NSFC_EN + bool "Enable Non-standard Flow Control (NSFC) mode" + depends on BT_LE_ISO_SUPPORT + default y + help + Enable this to support ISO non-standard flow control. + Note: + If non-standard flow control mode is used, no Number of + Completed Packets event will be posted from Controller. + Instead before transmitting an ISO packet, Host needs to + invoke an API provided by Controller to make sure that + the ISO packet could be accommodated by Controller. + +config BT_LE_ISO_NSFC_NUM + int "Maximum number of ISO packets for NSFC mode" + depends on BT_LE_ISO_SUPPORT && BT_LE_ISO_NSFC_EN + range 1 255 + default 12 + help + Maximum number of ISO packets could be accommodated by + Controller while using non-standard flow control mode. + +config BT_LE_ISO_BUF_COUNT + int "Number of allocated ISO buffers" + depends on BT_LE_ISO_SUPPORT + range 1 255 + default 12 + help + Number of ISO buffers allocated in Controller. + +config BT_LE_ISO_BUF_SIZE + int "Size of each allocated ISO buffer" + depends on BT_LE_ISO_SUPPORT + range 1 65535 + default 251 + help + Size of each allocated ISO buffer in Controller. + And the allocated ISO buffers will be used to hold + ISO Data PDUs for transmission. + Currently a larger value is meaningless, which only + increase memory consumption. + +config BT_LE_ISO_BIG + int "Maximum number of BIGs" + depends on BT_LE_ISO_SUPPORT + range 1 2 + default 1 + help + Maximum number of BIGs. + +config BT_LE_ISO_BIS + int "Maximum number of BISes" + depends on BT_LE_ISO_SUPPORT + range 1 6 + default 2 + help + Maximum number of BISes. + +config BT_LE_ISO_BIS_PER_BIG + int "Maximum number of BISes per BIG" + depends on BT_LE_ISO_SUPPORT + range 1 BT_LE_ISO_BIS + default BT_LE_ISO_BIS + help + Maximum number of BISes per BIG. + +config BT_LE_ISO_CIG + int "Maximum number of CIGs" + depends on BT_LE_ISO_SUPPORT + range 1 2 + default 1 + help + Maximum number of CIGs. + +config BT_LE_ISO_CIS + int "Maximum number of CISes" + depends on BT_LE_ISO_SUPPORT + range 1 6 + default 2 + help + Maximum number of CISes. + +config BT_LE_ISO_CIS_PER_CIG + int "Maximum number of CISes per CIG" + depends on BT_LE_ISO_SUPPORT + range 1 BT_LE_ISO_CIS + default BT_LE_ISO_CIS + help + Maximum number of CISes per CIG. + +menu "Memory Settings" + depends on !BT_NIMBLE_ENABLED + + config BT_LE_MSYS_1_BLOCK_COUNT + int "MSYS_1 Block Count" + default 12 + help + MSYS is a system level mbuf registry. For prepare write & prepare + responses MBUFs are allocated out of msys_1 pool. For NIMBLE_MESH + enabled cases, this block count is increased by 8 than user defined + count. + + config BT_LE_MSYS_1_BLOCK_SIZE + int "MSYS_1 Block Size" + default 256 + help + Dynamic memory size of block 1 + + config BT_LE_MSYS_2_BLOCK_COUNT + int "MSYS_2 Block Count" + default 24 + help + Dynamic memory count + + config BT_LE_MSYS_2_BLOCK_SIZE + int "MSYS_2 Block Size" + default 320 + help + Dynamic memory size of block 2 + + config BT_LE_MSYS_BUF_FROM_HEAP + bool "Get Msys Mbuf from heap" + default y + depends on BT_LE_MSYS_INIT_IN_CONTROLLER + help + This option sets the source of the shared msys mbuf memory between + the Host and the Controller. Allocate the memory from the heap if + this option is sets, from the mempool otherwise. + + config BT_LE_ACL_BUF_COUNT + int "ACL Buffer count" + default 10 + help + The number of ACL data buffers. + + config BT_LE_ACL_BUF_SIZE + int "ACL Buffer size" + default 517 + help + This is the maximum size of the data portion of HCI ACL data packets. + It does not include the HCI data header (of 4 bytes) + + config BT_LE_HCI_EVT_BUF_SIZE + int "HCI Event Buffer size" + default 257 if BT_LE_EXT_ADV + default 70 + help + This is the size of each HCI event buffer in bytes. In case of + extended advertising, packets can be fragmented. 257 bytes is the + maximum size of a packet. + + config BT_LE_HCI_EVT_HI_BUF_COUNT + int "High Priority HCI Event Buffer count" + default 30 + help + This is the high priority HCI events' buffer size. High-priority + event buffers are for everything except advertising reports. If there + are no free high-priority event buffers then host will try to allocate a + low-priority buffer instead + + config BT_LE_HCI_EVT_LO_BUF_COUNT + int "Low Priority HCI Event Buffer count" + default 8 + help + This is the low priority HCI events' buffer size. Low-priority event + buffers are only used for advertising reports. If there are no free + low-priority event buffers, then an incoming advertising report will + get dropped +endmenu + +menu "Controller debug features" + menuconfig BT_LE_CONTROLLER_LOG_ENABLED + bool "Controller log enable" + default n + help + Enable controller log + + config BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 + bool "Utilize BLE Log v2 for controller log" + depends on BLE_LOG_ENABLED + default y + help + Utilize BLE Log v2 for controller log + + if !BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 + config BT_LE_CONTROLLER_LOG_CTRL_ENABLED + bool "enable controller log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help + Enable controller log module + + config BT_LE_CONTROLLER_LOG_HCI_ENABLED + bool "enable HCI log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help + Enable hci log module + + config BT_LE_CONTROLLER_LOG_DUMP_ONLY + bool "Controller log dump mode only" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help + Only operate in dump mode + + config BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + bool "Output ble controller logs to SPI bus (Experimental)" + depends on BT_LE_CONTROLLER_LOG_ENABLED + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + select BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Output ble controller logs to SPI bus + + config BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED + bool "Output ble controller logs via UART DMA (Experimental)" + depends on BT_LE_CONTROLLER_LOG_ENABLED + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + depends on !BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + select BT_BLE_LOG_UHCI_OUT_ENABLED + default y + help + Output ble controller logs via UART DMA + + config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + bool "Store ble controller logs to flash(Experimental)" + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Store ble controller logs to flash memory. + + config BT_LE_CONTROLLER_LOG_PARTITION_SIZE + int "size of ble controller log partition(Multiples of 4K)" + depends on BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + default 65536 + help + The size of ble controller log partition shall be a multiples of 4K. + The name of log partition shall be "bt_ctrl_log". + The partition type shall be ESP_PARTITION_TYPE_DATA. + The partition sub_type shall be ESP_PARTITION_SUBTYPE_ANY. + + config BT_LE_LOG_CTRL_BUF1_SIZE + int "size of the first BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help + Configure the size of the first BLE controller LOG buffer. + + config BT_LE_LOG_CTRL_BUF2_SIZE + int "size of the second BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 1024 + help + Configure the size of the second BLE controller LOG buffer. + + config BT_LE_LOG_HCI_BUF_SIZE + int "size of the BLE HCI LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help + Configure the size of the BLE HCI LOG buffer. + endif + + config BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE + bool "Enable wrap panic handler" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Wrap esp_panic_handler to get controller logs when PC pointer exception crashes. + + config BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + bool "Enable esp_task_wdt_isr_user_handler implementation" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Implement esp_task_wdt_isr_user_handler to get controller logs when task wdt issue is triggered. + + config BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL + int "The output level of controller log" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 5 + default 1 + help + The output level of controller log. + + config BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH + hex "The switch of module log output" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 0xFFFFFFFF + default 0xFFFFFFFF + help + The switch of module log output, this is an unsigned 32-bit hexadecimal value. + + config BT_LE_ERROR_SIM_ENABLED + bool "Enable controller features for internal testing" + default n + + config BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + bool "When ACL disconnects abnormally, assertion processing is performed(Experimental)" + default n + + config BT_LE_DEBUG_REMAIN_SCENE_ENABLED + bool "Remain scene with GDB to capture relevant status info(Experimental)" + default n + help + Retain scene with GDB to capture info, requires disabling WDT (CONFIG_ESP_INT_WDT, CONFIG_ESP_TASK_WDT_EN). + + config BT_LE_PTR_CHECK_ENABLED + bool "Enable boundary check for internal memory" + default n + + config BT_LE_MEM_CHECK_ENABLED + bool "Enable memory allocation check" + default n + help + Used in internal tests only. Enable the memory allocation check. +endmenu + +config BT_LE_LL_RESOLV_LIST_SIZE + int "BLE LL Resolving list size" + range 1 5 + default 4 + help + Configure the size of resolving list used in link layer. + +menuconfig BT_LE_SECURITY_ENABLE + bool "Enable BLE SM feature" + depends on !BT_NIMBLE_ENABLED + default y + help + Enable BLE sm feature + +config BT_LE_SM_LEGACY + bool "Security manager legacy pairing" + depends on BT_LE_SECURITY_ENABLE + default y + help + Enable security manager legacy pairing + +config BT_LE_SM_SC + bool "Security manager secure connections (4.2)" + depends on BT_LE_SECURITY_ENABLE + default y + help + Enable security manager secure connections + +config BT_LE_SM_SC_DEBUG_KEYS + bool "Use predefined public-private key pair" + default n + depends on BT_LE_SECURITY_ENABLE && BT_LE_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_LE_LL_CFG_FEAT_LE_ENCRYPTION + bool "Enable LE encryption" + depends on BT_LE_SECURITY_ENABLE + default y + help + Enable encryption connection + +config BT_LE_CRYPTO_STACK_MBEDTLS + bool "Override TinyCrypt with mbedTLS for crypto computations" + default n + depends on !BT_NIMBLE_ENABLED + select MBEDTLS_CMAC_C + help + Enable this option to choose mbedTLS instead of TinyCrypt for crypto + computations. + +config BT_LE_WHITELIST_SIZE + int "BLE white list size" + range 1 15 + default 12 + depends on !BT_NIMBLE_ENABLED + + help + BLE list size + +config BT_LE_LL_DUP_SCAN_LIST_COUNT + int "BLE duplicate scan list count" + range 1 100 + default 20 + help + config the max count of duplicate scan list + +config BT_LE_LL_SCA + int "BLE Sleep clock accuracy" + range 0 500 + default 60 + help + Sleep clock accuracy of our device (in ppm) + +config BT_LE_MAX_CONNECTIONS + int "Maximum number of concurrent connections" + depends on !BT_NIMBLE_ENABLED + range 1 70 + default 3 + help + Defines maximum number of concurrent BLE connections. + Each connection will take about 1k DRAM. + +choice BT_LE_COEX_PHY_CODED_TX_RX_TLIM + prompt "Coexistence: limit on MAX Tx/Rx time for coded-PHY connection" + default BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS + help + When using PHY-Coded in BLE connection, limitation on max tx/rx time can be applied to + better avoid dramatic performance deterioration of Wi-Fi. + + config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN + bool "Force Enable" + help + Always enable the limitation on max tx/rx time for Coded-PHY connection + + config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS + bool "Force Disable" + help + Disable the limitation on max tx/rx time for Coded-PHY connection +endchoice + +config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF + int + default 1 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN + default 0 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS + +choice BT_LE_LP_CLK_SRC + prompt "BLE low power clock source" + default BT_LE_LP_CLK_SRC_MAIN_XTAL + depends on BT_CTRL_SLEEP_ENABLE + config BT_LE_LP_CLK_SRC_MAIN_XTAL + bool "Use main XTAL as RTC clock source" + help + User main XTAL as RTC clock source. + This option is recommended if external 32.768k XTAL is not available. + Using the external 32.768 kHz XTAL will have lower current consumption + in light sleep compared to using the main XTAL. + + config BT_LE_LP_CLK_SRC_DEFAULT + bool "Use system RTC slow clock source" + help + Use the same slow clock source as system RTC + Using any clock source other than external 32.768 kHz XTAL supports only + legacy ADV and SCAN due to low clock accuracy. + +endchoice + +config BT_LE_USE_ESP_TIMER + bool "Enable Esp Timer for Callout" + depends on !BT_NIMBLE_ENABLED + default y + help + Set this option to use Esp Timer which has higher priority timer + instead of FreeRTOS timer +config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP + bool "BLE adv report flow control supported" + default y + help + The function is mainly used to enable flow control for advertising reports. When it is enabled, + advertising reports will be discarded by the controller if the number of unprocessed advertising + reports exceeds the size of BLE adv report flow control. + +config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM + int "BLE adv report flow control number" + depends on BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP + range 50 1000 + default 100 + help + The number of unprocessed advertising report that bluetooth host can save.If you set + `BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM` to a small value, this may cause adv packets lost. + If you set `BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM` to a large value, bluetooth host may cache a + lot of adv packets and this may cause system memory run out. For example, if you set + it to 50, the maximum memory consumed by host is 35 * 50 bytes. Please set + `BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM` according to your system free memory and handle adv + packets as fast as possible, otherwise it will cause adv packets lost. + +config BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD + int "BLE adv lost event threshold value" + depends on BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP + range 1 1000 + default 20 + help + When adv report flow control is enabled, The ADV lost event will be generated when the number + of ADV packets lost in the controller reaches this threshold. It is better to set a larger value. + If you set `BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it + may cause adv packets lost more. + +config BT_LE_SCAN_DUPL + bool "BLE Scan Duplicate Options" + default y + help + This select enables parameters setting of BLE scan duplicate. + +choice BT_LE_SCAN_DUPL_TYPE + prompt "Scan Duplicate Type" + default BT_LE_SCAN_DUPL_TYPE_DEVICE + depends on BT_LE_SCAN_DUPL + help + Scan duplicate have three ways. one is "Scan Duplicate By Device Address", This way is to use + advertiser address filtering. The adv packet of the same address is only allowed to be reported once. + Another way is "Scan Duplicate By Device Address And Advertising Data". This way is to use advertising + data and device address filtering. All different adv packets with the same address are allowed to be + reported. The last way is "Scan Duplicate By Advertising Data". This way is to use advertising data + filtering. All same advertising data only allow to be reported once even though they are from + different devices. + + config BT_LE_SCAN_DUPL_TYPE_DEVICE + bool "Scan Duplicate By Device Address" + help + This way is to use advertiser address filtering. The adv packet of the same address is only + allowed to be reported once + + config BT_LE_SCAN_DUPL_TYPE_DATA + bool "Scan Duplicate By Advertising Data" + help + This way is to use advertising data filtering. All same advertising data only allow to be reported + once even though they are from different devices. + + config BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE + bool "Scan Duplicate By Device Address And Advertising Data" + help + This way is to use advertising data and device address filtering. All different adv packets with + the same address are allowed to be reported. +endchoice + +config BT_LE_SCAN_DUPL_TYPE + int + depends on BT_LE_SCAN_DUPL + default 0 if BT_LE_SCAN_DUPL_TYPE_DEVICE + default 1 if BT_LE_SCAN_DUPL_TYPE_DATA + default 2 if BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE + default 0 + + +config BT_LE_SCAN_DUPL_CACHE_SIZE + int "Maximum number of devices in scan duplicate filter" + depends on BT_LE_SCAN_DUPL + range 10 1000 + default 100 + help + Maximum number of devices which can be recorded in scan duplicate filter. + When the maximum amount of device in the filter is reached, the cache will be refreshed. + +config BT_LE_SCAN_DUPL_CACHE_REFRESH_PERIOD + int "Duplicate scan list refresh period (seconds)" + depends on BT_LE_SCAN_DUPL + range 0 1000 + default 0 + help + If the period value is non-zero, the controller will periodically clear the device information + stored in the scan duuplicate filter. If it is 0, the scan duuplicate filter will not be cleared + until the scanning is disabled. Duplicate advertisements for this period should not be sent to the + Host in advertising report events. + There are two scenarios where the ADV packet will be repeatedly reported: + 1. The duplicate scan cache is full, the controller will delete the oldest device information and + add new device information. + 2. When the refresh period is up, the controller will clear all device information and start filtering + again. + +config BT_LE_MSYS_INIT_IN_CONTROLLER + bool "Msys Mbuf Init in Controller" + default y + +config BT_LE_TX_CCA_ENABLED + bool "Enable TX CCA feature" + default n + help + Enable CCA feature to cancel sending the packet if the signal power is stronger than CCA threshold. + +config BT_LE_CCA_RSSI_THRESH + int "CCA RSSI threshold value" + depends on BT_LE_TX_CCA_ENABLED + range 20 100 + default 20 + help + Power threshold of CCA in unit of -1 dBm. + +choice BT_LE_DFT_TX_POWER_LEVEL_DBM + prompt "BLE default Tx power level(dBm)" + default BT_LE_DFT_TX_POWER_LEVEL_P9 + help + Specify default Tx power level(dBm). + config BT_LE_DFT_TX_POWER_LEVEL_N15 + bool "-15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N12 + bool "-12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N9 + bool "-9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N6 + bool "-6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N3 + bool "-3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N0 + bool "0dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P3 + bool "+3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P6 + bool "+6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P9 + bool "+9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P12 + bool "+12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P15 + bool "+15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P18 + bool "+18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P20 + bool "+20dBm" +endchoice + +config BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF + int + default -15 if BT_LE_DFT_TX_POWER_LEVEL_N15 + default -12 if BT_LE_DFT_TX_POWER_LEVEL_N12 + default -9 if BT_LE_DFT_TX_POWER_LEVEL_N9 + default -6 if BT_LE_DFT_TX_POWER_LEVEL_N6 + default -3 if BT_LE_DFT_TX_POWER_LEVEL_N3 + default 0 if BT_LE_DFT_TX_POWER_LEVEL_N0 + default 3 if BT_LE_DFT_TX_POWER_LEVEL_P3 + default 6 if BT_LE_DFT_TX_POWER_LEVEL_P6 + default 9 if BT_LE_DFT_TX_POWER_LEVEL_P9 + default 12 if BT_LE_DFT_TX_POWER_LEVEL_P12 + default 15 if BT_LE_DFT_TX_POWER_LEVEL_P15 + default 18 if BT_LE_DFT_TX_POWER_LEVEL_P18 + default 20 if BT_LE_DFT_TX_POWER_LEVEL_P20 + default 0 + +config BT_LE_ERROR_SIM_ENABLED + bool "Enable controller features for internal testing" + default n diff --git a/components/bt/controller/esp32h4/Kconfig.in b/components/bt/controller/esp32h4/Kconfig.in index e69de29bb2..c87c4e186e 100644 --- a/components/bt/controller/esp32h4/Kconfig.in +++ b/components/bt/controller/esp32h4/Kconfig.in @@ -0,0 +1,191 @@ +choice + prompt "Bluetooth controller mode (BR/EDR/BLE/DUALMODE)" + help + Specify the bluetooth controller mode (BR/EDR, BLE or dual mode). + + config BTDM_CTRL_MODE_BLE_ONLY + bool "BLE Only" + depends on SOC_BLE_SUPPORTED + + config BTDM_CTRL_MODE_BR_EDR_ONLY + bool "BR/EDR Only" + depends on SOC_BT_CLASSIC_SUPPORTED + + config BTDM_CTRL_MODE_BTDM + bool "Bluetooth Dual Mode" + depends on SOC_BLE_SUPPORTED && SOC_BT_CLASSIC_SUPPORTED +endchoice + +choice BT_CTRL_PINNED_TO_CORE_CHOICE + prompt "The cpu core which bluetooth controller run" + depends on !FREERTOS_UNICORE + help + Specify the cpu core to run bluetooth controller. + Can not specify no-affinity. + + config BT_CTRL_PINNED_TO_CORE_CHOICE_0 + bool "Core 0 (PRO CPU)" + config BT_CTRL_PINNED_TO_CORE_CHOICE_1 + bool "Core 1 (APP CPU)" + depends on !FREERTOS_UNICORE +endchoice + +config BT_CTRL_PINNED_TO_CORE + int + default 0 if BT_CTRL_PINNED_TO_CORE_CHOICE_0 + default 1 if BT_CTRL_PINNED_TO_CORE_CHOICE_1 + default 0 + +config BT_CTRL_TASK_STACK_SIZE + int "Controller task stack size" + default 5120 if BLE_MESH + default 4096 + help + This configures stack size of NimBLE controller task + +config BT_CTRL_SLEEP_ENABLE + bool "Enable Bluetooth Controller sleep" + default n + help + Enable Bluetooth Controller sleep + +menu "Bluetooth controller HCI" + config BT_CTRL_HCI_CMD_NUM + int "HCI CMD buffer number" + range 1 255 + default 5 + + choice BT_CTRL_HCI_INTERFACE + prompt "HCI mode" + default BT_CTRL_HCI_INTERFACE_USE_RAM + + config BT_CTRL_HCI_INTERFACE_USE_RAM + bool "VHCI" + help + Use RAM as HCI interface + config BT_CTRL_HCI_INTERFACE_USE_UART + bool "UART(H4)" + help + Use UART as HCI interface + endchoice + + choice BT_CTRL_UART_HCI_MODE_CHOICE + prompt "UART HCI mode" + depends on BT_CTRL_HCI_INTERFACE_USE_UART + default BT_CTRL_UART_HCI_NO_DMA_MODE + help + Specify UART HCI mode: DMA or No DMA + + config BT_CTRL_UART_HCI_DMA_MODE + bool "UHCI(UART with DMA)(EXPERIMENTAL)" + help + UART HCI Mode with DMA functionality. + + config BT_CTRL_UART_HCI_NO_DMA_MODE + bool "UART(NO DMA)" + help + UART HCI Mode without DMA functionality. + endchoice + + config BT_CTRL_HCI_UART_PORT + int "HCI UART port" + depends on BT_CTRL_HCI_INTERFACE_USE_UART + default 1 + help + Set the port number of HCI UART + + config BT_CTRL_HCI_UART_FLOWCTRL + bool "HCI uart Hardware Flow ctrl" + depends on BT_CTRL_HCI_INTERFACE_USE_UART + default n + + config BT_CTRL_HCI_UART_TX_PIN + int "HCI uart Tx gpio" + depends on BT_CTRL_HCI_INTERFACE_USE_UART + default 19 + + config BT_CTRL_HCI_UART_RX_PIN + int "HCI uart Rx gpio" + depends on BT_CTRL_HCI_INTERFACE_USE_UART + default 10 + + config BT_CTRL_HCI_UART_RTS_PIN + int "HCI uart RTS gpio" + depends on BT_CTRL_HCI_UART_FLOWCTRL + default 4 + + config BT_CTRL_HCI_UART_CTS_PIN + int "HCI uart CTS gpio" + depends on BT_CTRL_HCI_UART_FLOWCTRL + default 5 + + config BT_CTRL_HCI_UART_BAUD + int "HCI uart baudrate" + depends on BT_CTRL_HCI_INTERFACE_USE_UART + default 921600 + help + HCI uart baud rate 115200 ~ 1000000 + + choice BT_CTRL_HCI_UART_PARITY + prompt "select uart parity" + depends on BT_CTRL_HCI_INTERFACE_USE_UART + default BT_CTRL_HCI_UART_UART_PARITY_DISABLE + + config BT_CTRL_HCI_UART_UART_PARITY_DISABLE + bool "PARITY_DISABLE" + help + UART_PARITY_DISABLE + config BT_CTRL_HCI_UART_UART_PARITY_EVEN + bool "PARITY_EVEN" + help + UART_PARITY_EVEN + config BT_CTRL_HCI_UART_UART_PARITY_ODD + bool "PARITY_ODD" + help + UART_PARITY_ODD + endchoice + + config BT_CTRL_HCI_UART_RX_BUFFER_SIZE + int "The size of rx ring buffer memory" + depends on BT_CTRL_UART_HCI_NO_DMA_MODE + default 512 + help + The size of rx ring buffer memory + + config BT_CTRL_HCI_UART_TX_BUFFER_SIZE + int "The size of tx ring buffer memory" + depends on BT_CTRL_UART_HCI_NO_DMA_MODE + default 256 + help + The size of tx ring buffer memory + + config BT_CTRL_HCI_TRANS_TASK_STACK_SIZE + int "HCI transport task stack size" + depends on !BT_CTRL_HCI_INTERFACE_USE_RAM + default 1024 + help + This configures stack size of hci transport task + + config BT_CTRL_HCI_TRANS_RX_MEM_NUM + int "The amount of rx memory received at the same time" + depends on BT_CTRL_UART_HCI_DMA_MODE + default 3 + help + The amount of rx memory received at the same time + + config BT_CTRL_HCI_LLDESCS_POOL_NUM + int "The amount of lldecs memory for driver dma mode" + depends on BT_CTRL_UART_HCI_DMA_MODE + default 20 + help + The amount of lldecs memory for driver dma mode +endmenu + +menu "BLE Controller Settings" + depends on BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM + source "$IDF_PATH/components/bt/controller/$IDF_TARGET/Kconfig.ble.in" +endmenu + +config BT_DUAL_MODE_ARCH + bool + default y diff --git a/components/bt/controller/esp32h4/ble.c b/components/bt/controller/esp32h4/ble.c new file mode 100644 index 0000000000..6c3880b982 --- /dev/null +++ b/components/bt/controller/esp32h4/ble.c @@ -0,0 +1,1697 @@ +/* + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include + +#include "esp_random.h" +#include "esp_heap_caps.h" +#include "esp_heap_caps_init.h" +#include "esp_mac.h" + +#include "sdkconfig.h" + +#if CONFIG_BT_NIMBLE_ENABLED +#include "nimble/nimble_port.h" +#endif // CONFIG_BT_NIMBLE_ENABLED + +// #include "nimble/nimble_port_freertos.h" +#include "esp_private/esp_modem_clock.h" + +#ifdef ESP_PLATFORM +#include "esp_log.h" +#endif // ESP_PLATFORM + +#if CONFIG_SW_COEXIST_ENABLE +#include "private/esp_coexist_internal.h" +#endif // CONFIG_SW_COEXIST_ENABLE + +// #include "nimble/nimble_npl_os.h" +#include "btdm_endian.h" + +#include "esp_bt.h" +#include "ble_priv.h" +#include "esp_intr_alloc.h" +#include "esp_sleep.h" +#include "esp_pm.h" +#include "esp_phy_init.h" +#include "esp_private/periph_ctrl.h" +#include "esp_rom_sys.h" + +#ifdef CONFIG_BT_BLUEDROID_ENABLED +#include "hci/hci_hal.h" +#endif // CONFIG_BT_BLUEDROID_ENABLED +#include "esp_private/sleep_retention.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "esp_private/periph_ctrl.h" +#include "esp_sleep.h" +#include "soc/rtc.h" + + +#include "ble_msys.h" +#include "btdm_osal.h" + + +#if CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 +#include "ble_log.h" +#else /* !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED +#include "ble_log/ble_log_uhci_out.h" +#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED +#endif /* CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */ + + + +#if UC_BT_CTRL_BLE_IS_ENABLE + +/* Macro definition + ************************************************************************ + */ +#define NIMBLE_PORT_LOG_TAG "BLE_INIT" + +#define EXT_FUNC_VERSION 0x20250819 +#define EXT_FUNC_MAGIC_VALUE 0xA5A5A5A5 + +#define BT_ASSERT_PRINT esp_rom_printf + +#ifdef CONFIG_BT_BLUEDROID_ENABLED +/* ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data */ +#define ACL_DATA_MBUF_LEADINGSPCAE 4 +#endif // CONFIG_BT_BLUEDROID_ENABLED + +/* Types definition + ************************************************************************ + */ + +struct ext_funcs_t { + uint32_t ext_version; + void *(* _malloc)(uint32_t size, uint32_t flags); + void (*_free)(void *p); + void (*_osi_assert)(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); + uint32_t (* _os_random)(void); + int (* _ecc_gen_key_pair)(uint8_t *public, uint8_t *priv); + int (* _ecc_gen_dh_key)(const uint8_t *remote_pub_key_x, const uint8_t *remote_pub_key_y, + const uint8_t *local_priv_key, uint8_t *dhkey); + void (* _esp_reset_rpa_moudle)(void); + int (*_ecc_aes_cmac)(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out); + uint32_t magic; +}; + +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); + +enum { + BLE_LOG_INTERFACE_FLAG_CONTINUE = 0, + BLE_LOG_INTERFACE_FLAG_END, +}; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + +/* External functions or variables + ************************************************************************ + */ +extern void btdm_get_default_mac(uint8_t *mac); + +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +extern int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_deinit_async(void); +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); +extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); +extern void r_ble_log_async_output_dump_all(bool output); +extern void esp_panic_handler_feed_wdts(void); +extern int r_ble_log_ctrl_level_and_mod(uint8_t log_level, uint32_t mod_switch); +extern int r_ble_ctrl_mod_type(uint16_t mod, uint32_t mod_type_switch); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + +extern int r_ble_controller_deinit(void); +extern int ble_controller_enable(uint8_t mode); +extern int ble_controller_disable(void); +extern int esp_register_ext_funcs (struct ext_funcs_t *); +extern void esp_unregister_ext_funcs (void); +extern int r_esp_ble_ll_set_public_addr(const uint8_t *addr); +extern uint32_t r_os_cputime_get32(void); +extern uint32_t r_os_cputime_ticks_to_usecs(uint32_t ticks); +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +extern const sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); +extern void esp_ble_set_wakeup_overhead(uint32_t overhead); +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +extern void esp_ble_change_rtc_freq(uint32_t freq); +extern void btdm_sleep_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, + void *w_arg, uint32_t us_to_enabled); +// extern void r_ble_rtc_wake_up_state_clr(void); + +extern int r_esp_ble_msys_init(uint16_t msys_size1, uint16_t msys_size2, uint16_t msys_cnt1, uint16_t msys_cnt2, uint8_t from_heap); +extern void r_esp_ble_msys_deinit(void); + +extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, + const uint8_t *peer_pub_key_y, + const uint8_t *our_priv_key, uint8_t *out_dhkey); +extern int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv); +extern int r_ble_txpwr_set(esp_ble_enhanced_power_type_t power_type, uint16_t handle, int power_level); +extern int r_ble_txpwr_get(esp_ble_enhanced_power_type_t power_type, uint16_t handle); +extern uint32_t _bt_bss_start; +extern uint32_t _bt_bss_end; +extern uint32_t _bt_controller_bss_start; +extern uint32_t _bt_controller_bss_end; +extern uint32_t _bt_data_start; +extern uint32_t _bt_data_end; +extern uint32_t _bt_controller_data_start; +extern uint32_t _bt_controller_data_end; + +int ble_sm_ecc_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out); +static void osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); +static uint32_t osi_random_wrapper(void); +static void esp_reset_rpa_moudle(void); +static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); +static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, + const uint8_t *our_priv_key, uint8_t *out_dhkey); +static int esp_ecc_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out); +/* Local variable definition + *************************************************************************** + */ +/* Static variable declare */ +static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +#if !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED && !CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED && !CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#endif /* !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */ +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +static bool log_is_inited = false; + +#if CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 +/* TODO: Remove event handler dependency in lib */ +static void void_handler(void) {} + +/* TODO: Declare public interfaces in a public header */ +void esp_bt_controller_log_deinit(void) +{ + log_is_inited = false; + r_ble_log_deinit_simple(); + ble_log_deinit(); +} + +esp_err_t esp_bt_controller_log_init(void) +{ + if (log_is_inited) { + return ESP_OK; + } + + if (!ble_log_init()) { + goto exit; + } + + if (r_ble_log_init_simple(ble_log_write_hex_ll, void_handler) != 0) { + goto exit; + } + + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, + CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto exit; + } + log_is_inited = true; + return ESP_OK; + +exit: + esp_bt_controller_log_deinit(); + return ESP_FAIL; +} +#else /* !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */ +const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; +esp_err_t esp_bt_controller_log_init(void) +{ + if (log_is_inited) { + return ESP_OK; + } + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + if (ble_log_uhci_out_init() != 0) { + goto uhci_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#elif CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_uhci_out_ll_write, ble_log_uhci_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else + uint8_t buffers = 0; +#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); +#endif + + if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; + } +#endif + + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto ctrl_level_init_failed; + } + log_is_inited = true; + return ESP_OK; + +ctrl_level_init_failed: +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#elif CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else + r_ble_log_deinit_async(); +#endif +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + ble_log_uhci_out_deinit(); +uhci_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + return ESP_FAIL; +} + +void esp_bt_controller_log_deinit(void) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + ble_log_uhci_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#elif CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else + r_ble_log_deinit_async(); +#endif + + log_is_inited = false; +} +#endif /* CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */ + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#include "esp_partition.h" +#include "hal/wdt_hal.h" + +#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" + +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; + +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + r_ble_log_async_output_dump_all(true); + esp_bt_controller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_feed_wdts(); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(log_output_mode); + assert(err == ESP_OK); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE +void esp_task_wdt_isr_user_handler(void) +{ + esp_ble_controller_log_dump_all(true); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE +void __real_esp_panic_handler(void *info); +void __wrap_esp_panic_handler (void *info) +{ + esp_ble_controller_log_dump_all(true); + __real_esp_panic_handler(info); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + +struct ext_funcs_t ext_funcs_ro = { + .ext_version = EXT_FUNC_VERSION, + ._malloc = (void *(*)(uint32_t, uint32_t))btdm_osal_malloc, + ._free = btdm_osal_free, + ._osi_assert = osi_assert_wrapper, + ._os_random = osi_random_wrapper, + ._ecc_gen_key_pair = esp_ecc_gen_key_pair, + ._ecc_gen_dh_key = esp_ecc_gen_dh_key, + ._esp_reset_rpa_moudle = esp_reset_rpa_moudle, + ._ecc_aes_cmac = esp_ecc_aes_cmac, + .magic = EXT_FUNC_MAGIC_VALUE, +}; + +static void IRAM_ATTR esp_reset_rpa_moudle(void) +{ + +} + +static void IRAM_ATTR osi_assert_wrapper(const uint32_t ln, const char *fn, + uint32_t param1, uint32_t param2) +{ + BT_ASSERT_PRINT("BLE assert: line %d in function %s, param: 0x%x, 0x%x", ln, fn, param1, param2); +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + esp_ble_controller_log_dump_all(true); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + assert(0); +} + +static uint32_t IRAM_ATTR osi_random_wrapper(void) +{ + static bool first = true; + + if (first) { + first = false; + srand(esp_random()); + } + + return rand(); +} + +static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv) +{ + int rc = -1; +#if CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC + rc = ble_sm_alg_gen_key_pair(pub, priv); +#endif // CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC + return rc; +} + +static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, + const uint8_t *our_priv_key, uint8_t *out_dhkey) +{ + int rc = -1; +#if CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC + rc = ble_sm_alg_gen_dhkey(peer_pub_key_x, peer_pub_key_y, our_priv_key, out_dhkey); +#endif // CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC + return rc; +} + +static int esp_ecc_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out) +{ + return ble_sm_ecc_aes_cmac(key, in, len, out); +} + +static int ble_hci_unregistered_hook(void*, void*) +{ + ESP_LOGD(NIMBLE_PORT_LOG_TAG,"%s ble hci rx_evt is not registered.",__func__); + return 0; +} + +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +esp_err_t sleep_modem_ble_mac_modem_state_init(void) +{ + uint8_t size; + const sleep_retention_entries_config_t *ble_mac_modem_config = r_esp_ble_mac_retention_link_get(&size, 0); + esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_MAC); + if (err == ESP_OK) { + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization"); + } + return err; +} +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + +typedef enum { + FILTER_DUPLICATE_PDUTYPE = BIT(0), + FILTER_DUPLICATE_LENGTH = BIT(1), + FILTER_DUPLICATE_ADDRESS = BIT(2), + FILTER_DUPLICATE_ADVDATA = BIT(3), + FILTER_DUPLICATE_DEFAULT = FILTER_DUPLICATE_PDUTYPE | FILTER_DUPLICATE_ADDRESS, + FILTER_DUPLICATE_PDU_ALL = 0xF, + FILTER_DUPLICATE_EXCEPTION_FOR_MESH = BIT(4), + FILTER_DUPLICATE_AD_TYPE = BIT(5), +}disc_duplicate_mode_t; + +extern void r_filter_duplicate_mode_enable(disc_duplicate_mode_t mode); +extern void r_filter_duplicate_mode_disable(disc_duplicate_mode_t mode); +extern void r_filter_duplicate_set_ring_list_max_num(uint32_t max_num); +extern void r_scan_duplicate_cache_refresh_set_time(uint32_t period_time); + +int +ble_vhci_disc_duplicate_mode_enable(int mode) +{ + // TODO: use vendor hci to update + r_filter_duplicate_mode_enable(mode); + return true; +} + +int +ble_vhci_disc_duplicate_mode_disable(int mode) +{ + // TODO: use vendor hci to update + r_filter_duplicate_mode_disable(mode); + return true; +} + +int ble_vhci_disc_duplicate_set_max_cache_size(int max_cache_size){ + // TODO: use vendor hci to update + r_filter_duplicate_set_ring_list_max_num(max_cache_size); + return true; +} + +int ble_vhci_disc_duplicate_set_period_refresh_time(int refresh_period_time){ + // TODO: use vendor hci to update + r_scan_duplicate_cache_refresh_set_time(refresh_period_time); + return true; +} + +/** + * @brief Config scan duplicate option mode from menuconfig (Adapt to the old configuration method.) + */ +void ble_controller_scan_duplicate_config(void) +{ + uint32_t duplicate_mode = FILTER_DUPLICATE_DEFAULT; + uint32_t cache_size = 100; +#if CONFIG_BT_LE_SCAN_DUPL == true + cache_size = CONFIG_BT_LE_SCAN_DUPL_CACHE_SIZE; + if (CONFIG_BT_LE_SCAN_DUPL_TYPE == 0) { + duplicate_mode = FILTER_DUPLICATE_ADDRESS | FILTER_DUPLICATE_PDUTYPE; + } else if (CONFIG_BT_LE_SCAN_DUPL_TYPE == 1) { + duplicate_mode = FILTER_DUPLICATE_ADVDATA; + } else if (CONFIG_BT_LE_SCAN_DUPL_TYPE == 2) { + duplicate_mode = FILTER_DUPLICATE_ADDRESS | FILTER_DUPLICATE_ADVDATA; + } + duplicate_mode |= FILTER_DUPLICATE_EXCEPTION_FOR_MESH; + + ble_vhci_disc_duplicate_set_period_refresh_time(CONFIG_BT_LE_SCAN_DUPL_CACHE_REFRESH_PERIOD); +#endif + + ble_vhci_disc_duplicate_mode_disable(0xFFFFFFFF); + ble_vhci_disc_duplicate_mode_enable(duplicate_mode); + ble_vhci_disc_duplicate_set_max_cache_size(cache_size); +} + +esp_err_t esp_ble_controller_init(esp_bt_controller_config_t *cfg) +{ + uint8_t mac[6]; + esp_err_t ret = ESP_OK; + // uint32_t slow_clk_freq = 0; + + extern const char *ble_controller_get_compile_version(void); + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "BLE controller compile version [%s]\n", ble_controller_get_compile_version()); + + if (!cfg) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "cfg is NULL"); + return ESP_ERR_INVALID_ARG; + } + + ret = esp_register_ext_funcs(&ext_funcs_ro); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "register extend functions failed"); + return ret; + } + +#if CONFIG_BT_NIMBLE_ENABLED + /* ble_npl_eventq_init() needs to use npl functions in rom and + * must be called after esp_ble_controller_init(). + */ + ble_npl_eventq_init(nimble_port_get_dflt_eventq()); +#endif // CONFIG_BT_NIMBLE_ENABLE + + /* Enable BT-related clocks */ + // modem_clock_module_mac_reset(PERIPH_BT_MODULE); + // modem_clock_module_enable(PERIPH_BT_MODULE); +// #if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL +// esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); +// slow_clk_freq = 100000; +// #else +// #if CONFIG_RTC_CLK_SRC_INT_RC +// esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC_SLOW); +// slow_clk_freq = 30000; +// #elif CONFIG_RTC_CLK_SRC_EXT_CRYS +// if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { +// esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_XTAL32K); +// slow_clk_freq = 32768; +// } else { +// ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); +// esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); +// slow_clk_freq = 100000; +// } +// #elif CONFIG_RTC_CLK_SRC_INT_RC32K +// esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC32K); +// slow_clk_freq = 32000; +// #elif CONFIG_RTC_CLK_SRC_EXT_OSC +// esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_EXT32K); +// slow_clk_freq = 32000; +// #else +// ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); +// assert(0); +// #endif +// #endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + +// #if CONFIG_SW_COEXIST_ENABLE +// if (ble_osi_coex_funcs_register((struct osi_coex_funcs_t *)&s_osi_coex_funcs_ro) != 0) { +// ESP_LOGW(NIMBLE_PORT_LOG_TAG, "osi coex funcs reg failed"); +// ret = ESP_ERR_INVALID_ARG; +// goto modem_deint; +// } + +// coex_init(); +// #endif // CONFIG_SW_COEXIST_ENABLE + cfg->ble.rtc_freq = 32000; + +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + ret = esp_bt_controller_log_init(); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); + goto modem_deint; + } +#endif // CONFIG_BT_CONTROLLER_LOG_ENABLED + + extern int esp_ble_register_bb_funcs(void); + ret = esp_ble_register_bb_funcs(); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "esp_ble_register_bb_funcs failed %d", ret); + goto modem_deint; + } + + extern int r_ble_controller_init(void *cfg); + ret = r_ble_controller_init(&cfg->ble); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_init failed %d", ret); + goto modem_deint; + } + + // esp_ble_change_rtc_freq(slow_clk_freq); + + ble_controller_scan_duplicate_config(); + + ret = ble_msys_init(); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_msys_init failed %d", ret); + goto free_controller; + } + + // ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); + btdm_osal_read_efuse_mac(mac); + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + btdm_swap_in_place(mac, 6); + r_esp_ble_ll_set_public_addr(mac); + ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; + + return ESP_OK; + +free_controller: + ble_msys_deinit(); + r_ble_controller_deinit(); +modem_deint: +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + esp_bt_controller_log_deinit(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + // modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); + // modem_clock_module_disable(PERIPH_BT_MODULE); +#if CONFIG_BT_NIMBLE_ENABLED + ble_npl_eventq_deinit(nimble_port_get_dflt_eventq()); +#endif // CONFIG_BT_NIMBLE_ENABLED + + esp_unregister_ext_funcs(); + return ret; +} + +esp_err_t esp_ble_controller_deinit(void) +{ + if ((ble_controller_status < ESP_BT_CONTROLLER_STATUS_INITED) || + (ble_controller_status >= ESP_BT_CONTROLLER_STATUS_ENABLED)) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state"); + return ESP_FAIL; + } + + ble_msys_deinit(); + + // modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); + // modem_clock_module_disable(PERIPH_BT_MODULE); + + r_ble_controller_deinit(); + +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + esp_bt_controller_log_deinit(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + +#if CONFIG_BT_NIMBLE_ENABLED + /* De-initialize default event queue */ + ble_npl_eventq_deinit(nimble_port_get_dflt_eventq()); +#endif // CONFIG_BT_NIMBLE_ENABLED + + esp_unregister_ext_funcs(); + + ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + + return ESP_OK; +} + +static +esp_err_t esp_ble_controller_enable(esp_bt_mode_t mode) +{ + esp_err_t ret = ESP_OK; + + // if (mode != ESP_BT_MODE_BLE) { + // ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller mode"); + // return ESP_FAIL; + // } + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_INITED) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state"); + return ESP_FAIL; + } + // esp_btbb_enable(); +// #if CONFIG_SW_COEXIST_ENABLE +// coex_enable(); +// #endif // CONFIG_SW_COEXIST_ENABLE + + +// ******************************* BTDM TODO ***************************************************** + ret = ble_stack_enable(); + printf("ble_stack_enable:%d\n", ret); + if (ret) { + goto error; + } + + int btdm_task_enable(void); + ret = btdm_task_enable(); + printf("btdm_task_enable:%d\n", ret); + if (ret) { + goto error; + } + +// ************************************************************************************************* + + // if (ble_controller_enable(mode) != 0) { + // ret = ESP_FAIL; + // goto error; + // } + ble_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED; + return ESP_OK; + +error: + return ret; +} + +esp_err_t esp_ble_controller_disable(void) +{ + if (ble_controller_status < ESP_BT_CONTROLLER_STATUS_ENABLED) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state"); + return ESP_FAIL; + } + if (ble_controller_disable() != 0) { + return ESP_FAIL; + } + ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; + return ESP_OK; +} + +esp_err_t esp_ble_controller_mem_release(esp_bt_mode_t mode) +{ + ESP_LOGD(NIMBLE_PORT_LOG_TAG, "%s not implemented, return OK", __func__); + return ESP_OK; +} + +static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end) +{ + int ret = heap_caps_add_region(start, end); + + /* heap_caps_add_region() returns ESP_ERR_INVALID_SIZE if the memory region is + * is too small to fit a heap. This cannot be termed as a fatal error and hence + * we replace it by ESP_OK + */ + if (ret == ESP_ERR_INVALID_SIZE) { + return ESP_OK; + } + return ret; +} + +esp_err_t esp_ble_mem_release(esp_bt_mode_t mode) +{ + intptr_t mem_start, mem_end; + + if (mode & ESP_BT_MODE_BLE) { + /* If the addresses of btdm .bss and bt .bss are consecutive, + * they are registered in the system heap as a piece of memory + */ + if(_bt_bss_end == _bt_controller_bss_start) { + mem_start = (intptr_t)&_bt_bss_start; + mem_end = (intptr_t)&_bt_controller_bss_end; + if (mem_start != mem_end) { + ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BSS [0x%08x] - [0x%08x], len %d", + mem_start, mem_end, mem_end - mem_start); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } + } else { + mem_start = (intptr_t)&_bt_bss_start; + mem_end = (intptr_t)&_bt_bss_end; + if (mem_start != mem_end) { + ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BT BSS [0x%08x] - [0x%08x], len %d", + mem_start, mem_end, mem_end - mem_start); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } + + mem_start = (intptr_t)&_bt_controller_bss_start; + mem_end = (intptr_t)&_bt_controller_bss_end; + if (mem_start != mem_end) { + ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release Controller BSS [0x%08x] - [0x%08x], len %d", + mem_start, mem_end, mem_end - mem_start); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } + } + /* If the addresses of btdm .data and bt .data are consecutive, + * they are registered in the system heap as a piece of memory + */ + if(_bt_data_end == _bt_controller_data_start) { + mem_start = (intptr_t)&_bt_data_start; + mem_end = (intptr_t)&_bt_controller_data_end; + if (mem_start != mem_end) { + ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release data [0x%08x] - [0x%08x], len %d", + mem_start, mem_end, mem_end - mem_start); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } + } else { + mem_start = (intptr_t)&_bt_data_start; + mem_end = (intptr_t)&_bt_data_end; + if (mem_start != mem_end) { + ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x], len %d", + mem_start, mem_end, mem_end - mem_start); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } + + mem_start = (intptr_t)&_bt_controller_data_start; + mem_end = (intptr_t)&_bt_controller_data_end; + if (mem_start != mem_end) { + ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release Controller Data [0x%08x] - [0x%08x], len %d", + mem_start, mem_end, mem_end - mem_start); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } + } + } + + return ESP_OK; +} + + +esp_bt_controller_status_t esp_ble_controller_get_status(void) +{ + return ble_controller_status; +} + +esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level) +{ + esp_err_t stat = ESP_FAIL; + + switch (power_type) { + case ESP_BLE_PWR_TYPE_DEFAULT: + case ESP_BLE_PWR_TYPE_ADV: + case ESP_BLE_PWR_TYPE_SCAN: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; + case ESP_BLE_PWR_TYPE_CONN_HDL0: + case ESP_BLE_PWR_TYPE_CONN_HDL1: + case ESP_BLE_PWR_TYPE_CONN_HDL2: + case ESP_BLE_PWR_TYPE_CONN_HDL3: + case ESP_BLE_PWR_TYPE_CONN_HDL4: + case ESP_BLE_PWR_TYPE_CONN_HDL5: + case ESP_BLE_PWR_TYPE_CONN_HDL6: + case ESP_BLE_PWR_TYPE_CONN_HDL7: + case ESP_BLE_PWR_TYPE_CONN_HDL8: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_CONN, power_type, power_level) == 0) { + stat = ESP_OK; + } + break; + default: + stat = ESP_ERR_NOT_SUPPORTED; + break; + } + + return stat; +} + +esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle, + esp_power_level_t power_level) +{ + esp_err_t stat = ESP_FAIL; + switch (power_type) { + case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: + case ESP_BLE_ENHANCED_PWR_TYPE_INIT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; + case ESP_BLE_ENHANCED_PWR_TYPE_ADV: + case ESP_BLE_ENHANCED_PWR_TYPE_CONN: + if (r_ble_txpwr_set(power_type, handle, power_level) == 0) { + stat = ESP_OK; + } + break; + default: + stat = ESP_ERR_NOT_SUPPORTED; + break; + } + + return stat; +} + +esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) +{ + int tx_level = 0; + + switch (power_type) { + case ESP_BLE_PWR_TYPE_ADV: + case ESP_BLE_PWR_TYPE_SCAN: + case ESP_BLE_PWR_TYPE_DEFAULT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; + case ESP_BLE_PWR_TYPE_CONN_HDL0: + case ESP_BLE_PWR_TYPE_CONN_HDL1: + case ESP_BLE_PWR_TYPE_CONN_HDL2: + case ESP_BLE_PWR_TYPE_CONN_HDL3: + case ESP_BLE_PWR_TYPE_CONN_HDL4: + case ESP_BLE_PWR_TYPE_CONN_HDL5: + case ESP_BLE_PWR_TYPE_CONN_HDL6: + case ESP_BLE_PWR_TYPE_CONN_HDL7: + case ESP_BLE_PWR_TYPE_CONN_HDL8: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_CONN, power_type); + break; + default: + return ESP_PWR_LVL_INVALID; + } + + if (tx_level < 0) { + return ESP_PWR_LVL_INVALID; + } + + return (esp_power_level_t)tx_level; +} + +esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, + uint16_t handle) +{ + int tx_level = 0; + + switch (power_type) { + case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: + case ESP_BLE_ENHANCED_PWR_TYPE_INIT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; + case ESP_BLE_ENHANCED_PWR_TYPE_ADV: + case ESP_BLE_ENHANCED_PWR_TYPE_CONN: + tx_level = r_ble_txpwr_get(power_type, handle); + break; + default: + return ESP_PWR_LVL_INVALID; + } + + if (tx_level < 0) { + return ESP_PWR_LVL_INVALID; + } + + return (esp_power_level_t)tx_level; +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 +void esp_ble_controller_log_dump_all(bool output) +{ + ble_log_dump_to_console(); +} +#else /* !CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */ +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED && !CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) +{ + bool end = (flag & BIT(BLE_LOG_INTERFACE_FLAG_END)); +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + + if (len && addr) { + for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } + } + if (len_append && addr_append) { + for (int i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); } + } + if (end) { esp_rom_printf("\n"); } + + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +} +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED && !CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED + +void esp_ble_controller_log_dump_all(bool output) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + ble_log_uhci_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED && !CONFIG_BT_LE_CONTROLLER_LOG_UHCI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + BT_ASSERT_PRINT("\r\n[DUMP_START:"); + r_ble_log_async_output_dump_all(output); + BT_ASSERT_PRINT(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); +#endif +} +#endif /* CONFIG_BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2 */ +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + +/* Adapt to the aes cmac function under Nimble Host */ +#if CONFIG_BT_NIMBLE_ENABLED +#if CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS +#include "mbedtls/aes.h" +#include "mbedtls/cipher.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/cmac.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" +#else +#include "tinycrypt/aes.h" +#include "tinycrypt/constants.h" +#include "tinycrypt/utils.h" +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/ecc_dh.h" +#endif // CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS + +int ble_sm_ecc_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out) +{ +#if CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS + int ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + + mbedtls_cipher_init(&ctx); + + // Choose AES-128 cipher info (or AES-256 if using 32-byte key) + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + if (cipher_info == NULL) { + ret = -1; + goto exit; + } + + if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) { + goto exit; + } + + if ((ret = mbedtls_cipher_cmac_starts(&ctx, key, 128)) != 0) { + goto exit; + } + + if ((ret = mbedtls_cipher_cmac_update(&ctx, in, len)) != 0) { + goto exit; + } + + if ((ret = mbedtls_cipher_cmac_finish(&ctx, out)) != 0) { + goto exit; + } + + ret = 0; + +exit: + mbedtls_cipher_free(&ctx); + return ret; +#else + // TinyCrypt implementation + struct tc_aes_key_sched_struct sched; + struct tc_cmac_struct state; + // Initialize CMAC context, set key and scheduling information + // If initialization fails, return -1 + if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) { + return -1; + } + + if (tc_cmac_update(&state, in, len) == TC_CRYPTO_FAIL) { + return -1; + } + + if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) { + return -1; + } + + return 0; +#endif // CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS + // Calculation successful, return 0 + return 0; +} + +#endif // CONFIG_BT_NIMBLE_ENABLED + +#if (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED == true) +#define BLE_SM_KEY_ERR 0x17 +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS +#include "mbedtls/aes.h" +#if CONFIG_BT_LE_SM_SC +#include "mbedtls/cipher.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/cmac.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" +#endif // CONFIG_BT_LE_SM_SC +#else +#include "tinycrypt/aes.h" +#include "tinycrypt/constants.h" +#include "tinycrypt/utils.h" +#if CONFIG_BT_LE_SM_SC +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/ecc_dh.h" +#endif // CONFIG_BT_LE_SM_SC +#endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS +#if CONFIG_BT_LE_SM_SC +static mbedtls_ecp_keypair keypair; +#endif // CONFIG_BT_LE_SM_SC +#endif// CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + +int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, + const uint8_t *our_priv_key, uint8_t *out_dhkey) +{ + uint8_t dh[32]; + uint8_t pk[64]; + uint8_t priv[32]; + int rc = BLE_SM_KEY_ERR; + + btdm_swap_buf(pk, peer_pub_key_x, 32); + btdm_swap_buf(&pk[32], peer_pub_key_y, 32); + btdm_swap_buf(priv, our_priv_key, 32); + +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + struct mbedtls_ecp_point pt = {0}, Q = {0}; + mbedtls_mpi z = {0}, d = {0}; + mbedtls_ctr_drbg_context ctr_drbg = {0}; + mbedtls_entropy_context entropy = {0}; + + uint8_t pub[65] = {0}; + /* Hardcoded first byte of pub key for MBEDTLS_ECP_PF_UNCOMPRESSED */ + pub[0] = 0x04; + memcpy(&pub[1], pk, 64); + + /* Initialize the required structures here */ + mbedtls_ecp_point_init(&pt); + mbedtls_ecp_point_init(&Q); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + mbedtls_mpi_init(&d); + mbedtls_mpi_init(&z); + + /* Below 3 steps are to validate public key on curve secp256r1 */ + if (mbedtls_ecp_group_load(&keypair.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1) != 0) { + goto exit; + } + + if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &pt, pub, 65) != 0) { + goto exit; + } + + if (mbedtls_ecp_check_pubkey(&keypair.MBEDTLS_PRIVATE(grp), &pt) != 0) { + goto exit; + } + + /* Set PRNG */ + if ((rc = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + NULL, 0)) != 0) { + goto exit; + } + + /* Prepare point Q from pub key */ + if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &Q, pub, 65) != 0) { + goto exit; + } + + if (mbedtls_mpi_read_binary(&d, priv, 32) != 0) { + goto exit; + } + + rc = mbedtls_ecdh_compute_shared(&keypair.MBEDTLS_PRIVATE(grp), &z, &Q, &d, + mbedtls_ctr_drbg_random, &ctr_drbg); + if (rc != 0) { + goto exit; + } + + rc = mbedtls_mpi_write_binary(&z, dh, 32); + if (rc != 0) { + goto exit; + } + +exit: + mbedtls_ecp_point_free(&pt); + mbedtls_mpi_free(&z); + mbedtls_mpi_free(&d); + mbedtls_ecp_point_free(&Q); + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + if (rc != 0) { + return BLE_SM_KEY_ERR; + } + +#else + if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { + return BLE_SM_KEY_ERR; + } + + rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1); + if (rc == TC_CRYPTO_FAIL) { + return BLE_SM_KEY_ERR; + } +#endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + + btdm_swap_buf(out_dhkey, dh, 32); + return 0; +} + +/* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */ +static const uint8_t ble_sm_alg_dbg_priv_key[32] = { + 0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38, 0x74, 0xc9, 0xb3, 0xe3, + 0xd2, 0x10, 0x3f, 0x50, 0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99, + 0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd +}; + +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS +static int mbedtls_gen_keypair(uint8_t *public_key, uint8_t *private_key) +{ + int rc = BLE_SM_KEY_ERR; + size_t olen = 0; + uint8_t pub[65] = {0}; + mbedtls_entropy_context entropy = {0}; + mbedtls_ctr_drbg_context ctr_drbg = {0}; + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_ecp_keypair_init(&keypair); + + if ((rc = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + NULL, 0)) != 0) { + goto exit; + } + + if ((rc = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, &keypair, + mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) { + goto exit; + } + + if ((rc = mbedtls_mpi_write_binary(&keypair.MBEDTLS_PRIVATE(d), private_key, 32)) != 0) { + goto exit; + } + + + if ((rc = mbedtls_ecp_point_write_binary(&keypair.MBEDTLS_PRIVATE(grp), + &keypair.MBEDTLS_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, + &olen, pub, 65)) != 0) { + goto exit; + } + + memcpy(public_key, &pub[1], 64); + +exit: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + if (rc != 0) { + mbedtls_ecp_keypair_free(&keypair); + return BLE_SM_KEY_ERR; + } + + return 0; +} +#endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + +/** + * pub: 64 bytes + * priv: 32 bytes + */ +int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) +{ +#if CONFIG_BT_LE_SM_SC_DEBUG_KEYS + btdm_swap_buf(pub, ble_sm_alg_dbg_pub_key, 32); + btdm_swap_buf(&pub[32], &ble_sm_alg_dbg_pub_key[32], 32); + btdm_swap_buf(priv, ble_sm_alg_dbg_priv_key, 32); +#else + uint8_t pk[64]; + + do { +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + if (mbedtls_gen_keypair(pk, priv) != 0) { + return BLE_SM_KEY_ERR; + } +#else + if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + return BLE_SM_KEY_ERR; + } +#endif // CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + /* Make sure generated key isn't debug key. */ + } while (memcmp(priv, ble_sm_alg_dbg_priv_key, 32) == 0); + + btdm_swap_buf(pub, pk, 32); + btdm_swap_buf(&pub[32], &pk[32], 32); + btdm_swap_in_place(priv, 32); +#endif // CONFIG_BT_LE_SM_SC_DEBUG_KEYS + + return 0; +} + +int ble_sm_ecc_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out) +{ +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + int ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + + mbedtls_cipher_init(&ctx); + + // Choose AES-128 cipher info (or AES-256 if using 32-byte key) + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + if (cipher_info == NULL) { + ret = -1; + goto exit; + } + + if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) { + goto exit; + } + + if ((ret = mbedtls_cipher_cmac_starts(&ctx, key, 128)) != 0) { + goto exit; + } + + if ((ret = mbedtls_cipher_cmac_update(&ctx, in, len)) != 0) { + goto exit; + } + + if ((ret = mbedtls_cipher_cmac_finish(&ctx, out)) != 0) { + goto exit; + } + + ret = 0; + +exit: + mbedtls_cipher_free(&ctx); + return ret; + +#else + // TinyCrypt implementation + struct tc_aes_key_sched_struct sched; + struct tc_cmac_struct state; + // Initialize CMAC context, set key and scheduling information + // If initialization fails, return -1 + if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) { + return -1; + } + + if (tc_cmac_update(&state, in, len) == TC_CRYPTO_FAIL) { + return -1; + } + + if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) { + return -1; + } + + return 0; +#endif + // Calculation successful, return 0 + return 0; +} +#endif // (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED == true) + +/* +* Bluetooth LE stack functions +************************************************************************************************** +*/ +extern int r_base_stack_initEnv(void); +extern int r_base_stack_deinitEnv(void); +extern void r_base_stack_init(void); +extern int r_base_stack_enable(void); +extern void r_base_stack_disable(void); + +extern int r_conn_stack_initEnv(void); +extern void r_conn_stack_deinitEnv(void); +extern int r_conn_stack_enable(void); +extern void r_conn_stack_disable(void); +extern int r_gapFinder_stack_enable(void); +extern void r_gapFinder_stack_disable(void); + +#define base_stack_initEnv r_base_stack_initEnv +#define base_stack_deinitEnv r_base_stack_deinitEnv +#define base_stack_enable r_base_stack_enable +#define base_stack_disable r_base_stack_disable + +#define conn_stack_initEnv r_conn_stack_initEnv +#define conn_stack_deinitEnv r_conn_stack_deinitEnv +#define conn_stack_enable r_conn_stack_enable +#define conn_stack_disable r_conn_stack_disable +#define gapFinder_stack_enable r_gapFinder_stack_enable +#define gapFinder_stack_disable r_gapFinder_stack_disable + +#if CONFIG_BT_LE_ERROR_SIM_ENABLED +extern int r_conn_errorSim_initEnv(void); +extern void r_conn_errorSim_deinitEnv(void); +extern int r_conn_errorSim_enable(void); +extern void r_conn_errorSim_disable(void); + + +#define conn_errorSim_initEnv r_conn_errorSim_initEnv +#define conn_errorSim_deinitEnv r_conn_errorSim_deinitEnv +#define conn_errorSim_enable r_conn_errorSim_enable +#define conn_errorSim_disable r_conn_errorSim_disable +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + +#if CONFIG_BT_LE_ISO_SUPPORT +extern int r_iso_stack_initEnv(void); +extern void r_iso_stack_deinitEnv(void); +extern int r_iso_stack_enable(void); +extern void r_iso_stack_disable(void); +#define iso_stack_enable r_iso_stack_enable +#define iso_stack_disable r_iso_stack_disable +#define iso_stack_initEnv r_iso_stack_initEnv +#define iso_stack_deinitEnv r_iso_stack_deinitEnv +#endif // CONFIG_BT_LE_ISO_SUPPORT + + +int ble_stack_init(esp_bt_controller_config_t *cfg) +{ + int rc; + + rc = esp_ble_controller_init(cfg); + if (rc != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "esp_ble_controller_init failed %d", rc); + return rc; + } + + rc = base_stack_initEnv(); + if (rc != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "base_stack_initEnv failed %d", rc); + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_initEnv(); + if (rc) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "conn_stack_initEnv failed %d", rc); + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_initEnv(); + if (rc) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "conn_errorSim_initEnv failed %d", rc); + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + +#if CONFIG_BT_LE_ISO_SUPPORT + rc = iso_stack_initEnv(); + if (rc) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "iso_stack_initEnv failed %d", rc); + return rc; + } +#endif // CONFIG_BT_LE_ISO_SUPPORT + +#if CONFIG_SW_COEXIST_ENABLE + // Should be invoked in ble ? + extern int r_bt_rf_coex_env_init(void); + r_bt_rf_coex_env_init(); +#endif /* CONFIG_SW_COEXIST_ENABLE */ + return 0; +} + +void ble_stack_deinit(void) +{ +#if CONFIG_SW_COEXIST_ENABLE + extern void r_bt_rf_coex_env_deinit(void); + r_bt_rf_coex_env_deinit(); +#endif /* CONFIG_SW_COEXIST_ENABLE */ + +#if CONFIG_BT_LE_ISO_SUPPORT + iso_stack_deinitEnv(); +#endif // CONFIG_BT_LE_ISO_SUPPORT +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_deinitEnv(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_deinitEnv(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_deinitEnv(); + + esp_ble_controller_deinit(); +} + +int ble_stack_enable(void) +{ + int rc; + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE && CONFIG_BT_CTRL_MULTI_LINK_ENABLED + extern void r_sched_txn_bredrIsEnabled(bool); + r_sched_txn_bredrIsEnabled(true); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE && CONFIG_BT_CTRL_MULTI_LINK_ENABLED + + rc = base_stack_enable(); + if (rc != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "base_stack_enable failed %d", rc); + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_enable(); + if (rc) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "conn_stack_enable failed %d", rc); + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_enable(); + if (rc) { + ESP_LOGW(conn_errorSim_enable, "conn_errorSim_enable failed %d", rc); + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + +#if CONFIG_BT_LE_ISO_SUPPORT + + rc = iso_stack_enable(); + if (rc != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "iso_stack_enable failed %d", rc); + return rc; + } + + rc = gapFinder_stack_enable(); + if (rc != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "gapFinder_stack_enable failed %d", rc); + return rc; + } + +#endif // BT_LE_ISO_SUPPORT + +#if CONFIG_SW_COEXIST_ENABLE + extern int r_bt_rf_coex_env_enable(void); + r_bt_rf_coex_env_enable(); +#endif /* CONFIG_SW_COEXIST_ENABLE */ + return 0; +} + +void ble_stack_disable(void) +{ +#if CONFIG_BT_LE_ISO_SUPPORT + gapFinder_stack_disable(); + + iso_stack_disable(); +#endif // BT_LE_ISO_SUPPORT + +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_disable(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_disable(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_disable(); +} +#endif // UC_BT_CTRL_BLE_IS_ENABLE + + +#if CONFIG_BT_NIMBLE_ENABLED +#define BLE_HOST_CO_COUNT (8) +#define BLE_HOST_EV_COUNT (11 + BLE_HOST_CO_COUNT) +#define BLE_HOST_EVQ_COUNT (3) +#define BLE_HOST_SEM_COUNT (10) +#define BLE_HOST_MUTEX_COUNT (4) +#else +#define BLE_HOST_CO_COUNT (0) +#define BLE_HOST_EV_COUNT (0) +#define BLE_HOST_EVQ_COUNT (0) +#define BLE_HOST_SEM_COUNT (0) +#define BLE_HOST_MUTEX_COUNT (0) +#endif + +void +ble_osal_elem_calc(esp_bt_controller_config_t *cfg, btdm_osal_elem_num_t *elem) +{ + btdm_osal_elem_num_t ble_osal_elem; + + extern int r_ble_ll_get_npl_element_info(void *cfg, btdm_osal_elem_num_t *elem); + r_ble_ll_get_npl_element_info(cfg, &ble_osal_elem); + + // elem->evt_count += ble_osal_elem.evt_count + BLE_HOST_CO_COUNT; + // elem->evtq_count += ble_osal_elem.evtq_count + BLE_HOST_EV_COUNT; + // elem->co_count += ble_osal_elem.co_count + BLE_HOST_EVQ_COUNT; + // elem->sem_count += ble_osal_elem.sem_count + BLE_HOST_SEM_COUNT; + // elem->mutex_count += ble_osal_elem.mutex_count + BLE_HOST_MUTEX_COUNT; + + // TODO + elem->evt_count += ble_osal_elem.evt_count + BLE_HOST_CO_COUNT + 10; + elem->evtq_count += ble_osal_elem.evtq_count + BLE_HOST_EV_COUNT + 10; + elem->co_count += ble_osal_elem.co_count + BLE_HOST_EVQ_COUNT + 10; + elem->sem_count += ble_osal_elem.sem_count + BLE_HOST_SEM_COUNT + 10; + elem->mutex_count += ble_osal_elem.mutex_count + BLE_HOST_MUTEX_COUNT + 10; +} diff --git a/components/bt/controller/esp32h4/bt.c b/components/bt/controller/esp32h4/bt.c new file mode 100644 index 0000000000..8de5026bdc --- /dev/null +++ b/components/bt/controller/esp32h4/bt.c @@ -0,0 +1,335 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_err.h" +#include "esp_log.h" +#include "sdkconfig.h" + +/* From ESP Bluetooth */ +#include "esp_bt.h" +#include "esp_hci_transport.h" +#include "ble_priv.h" +#include "btdm_coex.h" +#include "btdm_lp.h" +#include "btdm_log.h" +#include "btdm_external.h" + +/* + *************************************************************************************************** + * Local Defined Macros + *************************************************************************************************** + */ +#define BTDM_LOG_TAG "BTDM_INIT" + +#if UC_BT_CTRL_HCI_INTERFACE_USE_RAM +#define BT_HCI_TRANSPORT_MODE HCI_TRANSPORT_VHCI +#elif UC_BT_CTRL_HCI_INTERFACE_USE_UART +#define BT_HCI_TRANSPORT_MODE HCI_TRANSPORT_UART_NO_DMA +#if UC_BT_CTRL_UART_HCI_DMA_MODE +#define BT_HCI_TRANSPORT_MODE HCI_TRANSPORT_UART_UHCI +#endif // UC_BT_CTRL_UART_HCI_DMA_MODE +#endif // UC_BT_CTRL_HCI_INTERFACE_USE_RAM + +/* + *************************************************************************************************** + * External Functions + *************************************************************************************************** + */ +extern const char *r_btdm_get_compile_version(void); +extern int r_btdm_hci_fc_env_init(); +extern void r_btdm_hci_fc_env_deinit(void); +extern int r_btdm_hci_fc_enable(void); +extern void r_btdm_hci_fc_disable(void); + +extern int r_btdm_task_init(esp_btdm_controller_config_t *cfg); +extern void r_btdm_task_deinit(void); +extern int r_btdm_task_enable(void); +extern void r_btdm_task_disable(void); +extern void r_btdm_task_shutdown(void); + +/* + *************************************************************************************************** + * Local Variables + *************************************************************************************************** + */ +esp_bt_controller_status_t s_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + +/* + *************************************************************************************************** + * Static Function Definitions + *************************************************************************************************** + */ +static void +bt_shutdown(void) +{ + if (s_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return; + } + + r_btdm_task_shutdown(); + btdm_lp_shutdown(); +} + +/* + *************************************************************************************************** + * Public Function Definitions + *************************************************************************************************** + */ +esp_err_t +esp_bt_mem_release(esp_bt_mode_t mode) +{ + ESP_LOGW(BTDM_LOG_TAG, "esp_bt_mem_release not implement yet!"); + return ESP_OK; +} + +esp_err_t +esp_bt_controller_mem_release(esp_bt_mode_t mode) +{ + + ESP_LOGW(BTDM_LOG_TAG, "esp_bt_controller_mem_release not implement yet!"); + return ESP_OK; +} + +esp_err_t +esp_bt_controller_init(esp_bt_controller_config_t *cfg) +{ + int ret; + // TODO: Delete workaround + btdm_osal_elem_num_t elem = { + .evt_count = 3 + 100, + .evtq_count = 1 + 2, + .co_count = 0 + 10, + .sem_count = 0, + .mutex_count = 1, + }; + + ESP_LOGI(BTDM_LOG_TAG, "BTDM version [%s]", r_btdm_get_compile_version()); + + if (cfg->btdm.bluetooth_mode == ESP_BT_MODE_IDLE) { + ESP_LOGE(BTDM_LOG_TAG, "bluetooth_mode in cfg is IDLE"); + return ESP_ERR_INVALID_ARG; + } + + if (s_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return ESP_ERR_INVALID_STATE; + } + s_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; + + ret = ESP_FAIL; + +#if UC_BT_CTRL_BLE_IS_ENABLE + ble_osal_elem_calc(cfg, &elem); +#endif // UC_BT_CTRL_BLE_IS_ENABLE + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + bredr_osal_elem_calc(cfg, &elem); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + + ret = btdm_osal_elem_mempool_init(&elem); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "btdm_osal_elem_mempool_init failed: %d", ret); + goto init_failed; + } + + ret = btdm_log_init(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "btdm_log_init failed: %d", ret); + goto init_failed; + } + + ret = btdm_external_init(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "btdm_external_init failed: %d", ret); + goto init_failed; + } + + ret = btdm_coex_init(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "btdm_coex_init failed: %d", ret); + goto init_failed; + } + + btdm_lp_enable_clock(&cfg->btdm); + + ret = r_btdm_task_init(&cfg->btdm); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "r_btdm_task_init failed: %d", ret); + goto init_failed; + } + + ret = btdm_lp_init(); + if (ret != ESP_OK) { + ESP_LOGE(BTDM_LOG_TAG, "btdm_lp_init failed %d", ret); + goto init_failed; + } + +#if UC_BT_CTRL_CONN_FC_ENABLE + ret = r_btdm_hci_fc_env_init(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "r_btdm_hci_fc_env_init failed: %d", ret); + goto init_failed; + } +#endif // UC_BT_CTRL_CONN_FC_ENABLE + +#if UC_BT_CTRL_BLE_IS_ENABLE + ret = ble_stack_init(cfg); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "ble_stack_init failed: %d", ret); + goto init_failed; + } +#endif // UC_BT_CTRL_BLE_IS_ENABLE + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + ret = bredr_stack_init(cfg); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "bredr_stack_init failed: %d", ret); + goto init_failed; + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + + ret = hci_transport_init(BT_HCI_TRANSPORT_MODE); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "hci_transport_init failed %d", ret); + goto init_failed; + } + + ESP_LOGI(BTDM_LOG_TAG, "BTDM controller init OK"); + + return ESP_OK; + +init_failed: + esp_bt_controller_deinit(); + + return ESP_FAIL; +} + +esp_err_t +esp_bt_controller_deinit(void) +{ + if (s_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED) { + return ESP_ERR_INVALID_STATE; + } + s_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + + hci_transport_deinit(); + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + bredr_stack_deinit(); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + +#if UC_BT_CTRL_BLE_IS_ENABLE + ble_stack_deinit(); +#endif // UC_BT_CTRL_BLE_IS_ENABLE + +#if UC_BT_CTRL_CONN_FC_ENABLE + r_btdm_hci_fc_env_deinit(); +#endif // UC_BT_CTRL_CONN_FC_ENABLE + + btdm_lp_deinit(); + r_btdm_task_deinit(); + btdm_lp_disable_clock(); + btdm_coex_deinit(); + btdm_log_deinit(); + btdm_external_deinit(); + btdm_osal_elem_mempool_deinit(); + + return ESP_OK; +} + +esp_err_t +esp_bt_controller_enable(esp_bt_mode_t mode) +{ + int ret; + + if (s_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED) { + return ESP_ERR_INVALID_STATE; + } + s_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED; + + btdm_lp_reset(true); + + ret = btdm_coex_enable(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "btdm_coex_enable failed %d", ret); + goto enable_failed; + } + +#if UC_BT_CTRL_BLE_IS_ENABLE + ret = ble_stack_enable(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "ble_stack_enable failed %d", ret); + goto enable_failed; + } +#endif // UC_BT_CTRL_BLE_IS_ENABLE + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + ret = bredr_stack_enable(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "bredr_stack_enable failed %d", ret); + goto enable_failed; + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + +#if UC_BT_CTRL_CONN_FC_ENABLE + ret = r_btdm_hci_fc_enable(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "r_btdm_hci_fc_enable failed %d", ret); + goto enable_failed; + } +#endif // UC_BT_CTRL_CONN_FC_ENABLE + + ret = r_btdm_task_enable(); + if (ret) { + ESP_LOGE(BTDM_LOG_TAG, "r_btdm_task_enable failed %d", ret); + goto enable_failed; + } + + ret = esp_register_shutdown_handler(bt_shutdown); + if (ret) { + ESP_LOGW(BTDM_LOG_TAG, "Register shutdown handler failed, ret = 0x%x", ret); + } + + return ESP_OK; + +enable_failed: + esp_bt_controller_disable(); + return ESP_FAIL; +} + +esp_err_t +esp_bt_controller_disable(void) +{ + if (s_btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + s_btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; + + esp_unregister_shutdown_handler(bt_shutdown); + + r_btdm_task_disable(); + +#if UC_BT_CTRL_CONN_FC_ENABLE + r_btdm_hci_fc_disable(); +#endif // UC_BT_CTRL_CONN_FC_ENABLE + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + bredr_stack_disable(); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + +#if UC_BT_CTRL_BLE_IS_ENABLE + ble_stack_disable(); +#endif // UC_BT_CTRL_BLE_IS_ENABLE + + btdm_coex_disable(); + btdm_lp_reset(false); + + return ESP_OK; +} + +esp_bt_controller_status_t +esp_bt_controller_get_status(void) +{ + return s_btdm_controller_status; +} diff --git a/components/bt/controller/lib_esp32h4/esp32h4-bt-lib b/components/bt/controller/lib_esp32h4/esp32h4-bt-lib new file mode 160000 index 0000000000..9a0df711be --- /dev/null +++ b/components/bt/controller/lib_esp32h4/esp32h4-bt-lib @@ -0,0 +1 @@ +Subproject commit 9a0df711bea1a4b6eab6868ed95648c242744162 diff --git a/components/bt/host/bluedroid/hci/include/hci/hci_hal.h b/components/bt/host/bluedroid/hci/include/hci/hci_hal.h index aec926b6af..f50bef28cd 100644 --- a/components/bt/host/bluedroid/hci/include/hci/hci_hal.h +++ b/components/bt/host/bluedroid/hci/include/hci/hci_hal.h @@ -24,9 +24,7 @@ #include "common/bt_target.h" #include "osi/pkt_queue.h" #include "stack/bt_types.h" -#if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER) -#include "os/os_mbuf.h" -#endif + typedef enum { DATA_TYPE_COMMAND = 1, DATA_TYPE_ACL = 2, @@ -87,11 +85,6 @@ typedef struct hci_hal_t { // Gets the correct hal implementation, as compiled for. const hci_hal_t *hci_hal_h4_get_interface(void); -#if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER) -int ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg); - -int ble_hs_rx_data(struct os_mbuf *om, void *arg); -#endif #endif /* _HCI_HAL_H */ diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index 539482b93f..afe5f2f17d 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -569,7 +569,7 @@ menu "Memory Settings" config BT_NIMBLE_MEMPOOL_RUNTIME_ALLOC bool "Support on-demand runtime memory allocation for mempool" - depends on BT_NIMBLE_ENABLED && BT_NIMBLE_STATIC_TO_DYNAMIC + depends on BT_NIMBLE_ENABLED && BT_NIMBLE_STATIC_TO_DYNAMIC && !BT_DUAL_MODE_ARCH default n help When this option is enabled, mempool does not require pre-allocating memory. diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index 23bfcada3e..2d0d4de008 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit 23bfcada3e7719d4c3817e949d05751ac2cf72b3 +Subproject commit 2d0d4de008a15ef0ea0519ea7d4dc6d37dba2f44 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 d0c5a75185..09fb1f982f 100644 --- a/components/bt/host/nimble/port/include/esp_nimble_mem.h +++ b/components/bt/host/nimble/port/include/esp_nimble_mem.h @@ -13,9 +13,95 @@ extern "C" { #endif -// #pragma message "This file should be replaced with bt_osi_mem.h, used here for compatibility" +void *bt_osi_mem_malloc(size_t size); + +void *bt_osi_mem_calloc(size_t n, size_t size); + +void bt_osi_mem_free(void *ptr); + +#if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED +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 -#include "bt_osi_mem.h" #if CONFIG_BT_NIMBLE_MEM_DEBUG diff --git a/components/bt/host/nimble/port/src/esp_nimble_mem.c b/components/bt/host/nimble/port/src/esp_nimble_mem.c new file mode 100644 index 0000000000..d4a72b2a41 --- /dev/null +++ b/components/bt/host/nimble/port/src/esp_nimble_mem.c @@ -0,0 +1,339 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_attr.h" +#include "esp_heap_caps.h" +#include "sdkconfig.h" +#include "esp_log.h" +#include + +static uint8_t log_count; +#if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED +static size_t host_mem_used_size = 0; +#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + +#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 + mem = heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL + mem = heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT + mem = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#else + mem = malloc(size); +#endif + if (!mem) { + log_count ++; + if ((log_count % 100) == 0) { + ESP_EARLY_LOGI("ESP_LOG_INFO","malloc failed (size %zu)",size); + log_count = 0; + } + assert(mem != NULL); + } +#if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + if(mem) { + host_mem_used_size += heap_caps_get_allocated_size(mem); + } +#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + return mem; +} + +#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 + mem = heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL + mem = heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT + mem = heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#else + mem = calloc(n, size); +#endif +#if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + if(mem) { + host_mem_used_size += heap_caps_get_allocated_size(mem); + } +#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + return mem; +} + +#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) { + size_t alloc_size = heap_caps_get_allocated_size(ptr); + // assert(host_mem_used_size >= alloc_size); + host_mem_used_size -= alloc_size; + } +#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + if (ptr) { + heap_caps_free(ptr); + } +} + +#if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED +size_t +bt_osi_mem_used_size_get(void) +{ + return host_mem_used_size; +} + +#if CONFIG_BT_NIMBLE_ENABLED +uint32_t esp_host_used_heap_size_get(void) +{ + return bt_osi_mem_used_size_get(); +} +#endif // CONFIG_BT_NIMBLE_ENABLED +#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED diff --git a/components/bt/include/esp32h4/include/esp_bt.h b/components/bt/include/esp32h4/include/esp_bt.h index 242bc39c96..6f639c25d8 100644 --- a/components/bt/include/esp32h4/include/esp_bt.h +++ b/components/bt/include/esp32h4/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,23 +12,75 @@ #include "esp_err.h" #include "sdkconfig.h" #include "esp_task.h" +#include "esp_assert.h" -#include "nimble/nimble_npl.h" -#include "esp_bt_cfg.h" +#include "btdm_user_cfg.h" + +#if CONFIG_BTDM_CTRL_MODE_BLE_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +// #include "nimble/nimble_npl.h" +#include "ble_user_cfg.h" +#endif /* CONFIG_BTDM_CTRL_MODE_BLE_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM */ #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #include "driver/uart.h" #endif - #ifdef __cplusplus extern "C" { #endif +#define ESP_BT_HCI_TL_MAGIC_VALUE 0xfadebead +#define ESP_BT_HCI_TL_VERSION 0x00010000 + +/** + * @brief Bluetooth audio data transport path + */ +typedef enum { + ESP_SCO_DATA_PATH_HCI = 0, /*!< data over HCI transport */ + ESP_SCO_DATA_PATH_PCM = 1, /*!< data over PCM interface */ +} esp_sco_data_path_t; + +/** + * @brief Type of controller HCI transport layer + */ +typedef enum { + ESP_BT_CTRL_HCI_TL_UART = 0, /*!< HCI UART h4 transport layer */ + ESP_BT_CTRL_HCI_TL_VHCI = 1, /*!< VHCI interface */ +} esp_bt_ctrl_hci_tl_t; + +#define ESP_BT_HCI_TL_STATUS_OK (0) /*!< HCI_TL Tx/Rx operation status OK */ + +/** + * @brief callback function for HCI Transport Layer send/receive operations + */ +typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); + +#if CONFIG_BT_CTRL_HCI_MODE_CHOICE_VHCI +#define CFG_HCI_TL_TYPE 1 +#else +#define CFG_HCI_TL_TYPE 0 +#endif + +/** + * @brief Controller HCI transport layer function structure + * This structure shall be registered when HCI transport layer is UART + */ +typedef struct { + uint32_t _magic; /* Magic number */ + uint32_t _version; /* version number of the defined structure */ + uint32_t _reserved; /* reserved for future use */ + int (* _open)(void); /* hci tl open */ + void (* _close)(void); /* hci tl close */ + void (* _finish_transfers)(void); /* hci tl finish transfers */ + void (* _recv)(uint8_t *buf, uint32_t len, esp_bt_hci_tl_callback_t callback, void* arg); /* hci tl recv */ + void (* _send)(uint8_t *buf, uint32_t len, esp_bt_hci_tl_callback_t callback, void* arg); /* hci tl send */ + bool (* _flow_off)(void); /* hci tl flow off */ + void (* _flow_on)(void); /* hci tl flow on */ +} esp_bt_hci_tl_t; + /** * @brief Bluetooth mode for controller enable/disable */ - typedef enum { ESP_BT_MODE_IDLE = 0x00, /*!< Bluetooth is not running */ ESP_BT_MODE_BLE = 0x01, /*!< Run BLE mode */ @@ -37,9 +89,8 @@ typedef enum { } esp_bt_mode_t; /** - * @brief Bluetooth controller enable/disable/initialised/de-initialised status + * @brief Bluetooth controller enable/disable/initialised/de-initialised status. */ - typedef enum { ESP_BT_CONTROLLER_STATUS_IDLE = 0, /*!< Controller is in idle state */ ESP_BT_CONTROLLER_STATUS_INITED, /*!< Controller is in initialising state */ @@ -77,25 +128,31 @@ typedef enum { * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm). */ typedef enum { - ESP_PWR_LVL_N27 = 0, /*!< Corresponding to -27dbm */ - ESP_PWR_LVL_N24 = 1, /*!< Corresponding to -24dbm */ - ESP_PWR_LVL_N21 = 2, /*!< Corresponding to -21dbm */ - ESP_PWR_LVL_N18 = 3, /*!< Corresponding to -18dbm */ - ESP_PWR_LVL_N15 = 4, /*!< Corresponding to -15dbm */ - ESP_PWR_LVL_N12 = 5, /*!< Corresponding to -12dbm */ - ESP_PWR_LVL_N9 = 6, /*!< Corresponding to -9dbm */ - ESP_PWR_LVL_N6 = 7, /*!< Corresponding to -6dbm */ - ESP_PWR_LVL_N3 = 8, /*!< Corresponding to -3dbm */ - ESP_PWR_LVL_N0 = 9, /*!< Corresponding to 0dbm */ - ESP_PWR_LVL_P3 = 10, /*!< Corresponding to +3dbm */ - ESP_PWR_LVL_P6 = 11, /*!< Corresponding to +6dbm */ - ESP_PWR_LVL_P9 = 12, /*!< Corresponding to +9dbm */ - ESP_PWR_LVL_P12 = 13, /*!< Corresponding to +12dbm */ - ESP_PWR_LVL_P15 = 14, /*!< Corresponding to +15dbm */ - ESP_PWR_LVL_P18 = 15, /*!< Corresponding to +18dbm */ - ESP_PWR_LVL_INVALID = 0xFF, /*!< Indicates an invalid value */ + ESP_PWR_LVL_N24 = 0, /*!< Corresponding to -24dbm */ + ESP_PWR_LVL_N21 = 1, /*!< Corresponding to -21dbm */ + ESP_PWR_LVL_N18 = 2, /*!< Corresponding to -18dbm */ + ESP_PWR_LVL_N15 = 3, /*!< Corresponding to -15dbm */ + ESP_PWR_LVL_N12 = 4, /*!< Corresponding to -12dbm */ + ESP_PWR_LVL_N9 = 5, /*!< Corresponding to -9dbm */ + ESP_PWR_LVL_N6 = 6, /*!< Corresponding to -6dbm */ + ESP_PWR_LVL_N3 = 7, /*!< Corresponding to -3dbm */ + ESP_PWR_LVL_N0 = 8, /*!< Corresponding to 0dbm */ + ESP_PWR_LVL_P3 = 9, /*!< Corresponding to +3dbm */ + ESP_PWR_LVL_P6 = 10, /*!< Corresponding to +6dbm */ + ESP_PWR_LVL_P9 = 11, /*!< Corresponding to +9dbm */ + ESP_PWR_LVL_P12 = 12, /*!< Corresponding to +12dbm */ + ESP_PWR_LVL_P15 = 13, /*!< Corresponding to +15dbm */ + ESP_PWR_LVL_P16 = 14, /*!< Corresponding to +16dbm */ + ESP_PWR_LVL_P17 = 15, /*!< Corresponding to +17dbm */ + ESP_PWR_LVL_P18 = 16, /*!< Corresponding to +18dbm */ + ESP_PWR_LVL_P19 = 17, /*!< Corresponding to +19dbm */ + ESP_PWR_LVL_P20 = 18, /*!< Corresponding to +20dbm */ + ESP_PWR_LVL_INVALID = 0xFF, /*!< Indicates an invalid value */ } esp_power_level_t; +/** + * @brief The enhanced type of which tx power, could set Advertising/Connection/Default and etc. + */ typedef enum { ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT = 0, ESP_BLE_ENHANCED_PWR_TYPE_ADV, @@ -105,11 +162,22 @@ typedef enum { ESP_BLE_ENHANCED_PWR_TYPE_MAX, } esp_ble_enhanced_power_type_t; +/** + * @brief Address type and address value. + */ typedef struct { - uint8_t type; - uint8_t val[6]; + uint8_t type; /*!< Type of the Bluetooth address (public, random, etc.) */ + uint8_t val[6]; /*!< Array containing the 6-byte Bluetooth address value */ } esp_ble_addr_t; +/** + * @brief Select buffers +*/ +typedef enum { + ESP_BLE_LOG_BUF_HCI = 0x02, + ESP_BLE_LOG_BUF_CONTROLLER = 0x05, +} esp_ble_log_buf_t; + /** * @brief Set BLE TX power * Connection Tx power should only be set after connection created. @@ -127,7 +195,6 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ */ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); - /** * @brief ENHANCED API for Setting BLE TX power * Connection Tx power should only be set after connection created. @@ -147,119 +214,250 @@ 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 0x20220824 -#define CONFIG_MAGIC 0x5A5AA5A5 +#define BLE_CONFIG_VERSION 0x20241029 +#define BLE_CONFIG_MAGIC 0x5A5AA5A5 + +#define BTDM_CONFIG_VERSION 0x20260127 +#define BTDM_CONFIG_MAGIC_VALUE 0x5a5aa5a5 + +/* Types definition + ************************************************************************ + */ +typedef struct { + uint32_t version; + uint16_t task_stack_size; /*!< Size of Bluetooth controller task stack */ + uint8_t task_prio; /*!< Priority of the Bluetooth controller task */ + uint8_t task_run_cpu; /*!< CPU number on which the Bluetooth controller task runs */ + uint8_t hci_cmd_num; /*!< HCI command buffer number */ + uint8_t hci_conn_num; /*!< HCI level connection number */ + uint8_t sleep_en; + uint8_t version_num; + uint8_t bluetooth_mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */ + uint32_t magic; +}esp_btdm_controller_config_t; /** * @brief Controller config options, depend on config mask. * Config mask indicate which functions enabled, this means * some options or parameters of some functions enabled by config mask. */ - typedef struct { - uint32_t config_version; - uint16_t ble_ll_resolv_list_size; - uint16_t ble_hci_evt_hi_buf_count; - uint16_t ble_hci_evt_lo_buf_count; - uint8_t ble_ll_sync_list_cnt; - uint8_t ble_ll_sync_cnt; - uint16_t ble_ll_rsp_dup_list_count; - uint16_t ble_ll_adv_dup_list_count; - uint8_t ble_ll_tx_pwr_dbm; - uint64_t rtc_freq; - uint16_t ble_ll_sca; - uint8_t ble_ll_scan_phy_number; - uint16_t ble_ll_conn_def_auth_pyld_tmo; - uint8_t ble_ll_jitter_usecs; - uint16_t ble_ll_sched_max_adv_pdu_usecs; - uint16_t ble_ll_sched_direct_adv_max_usecs; - uint16_t ble_ll_sched_adv_max_usecs; - uint16_t ble_scan_rsp_data_max_len; - uint8_t ble_ll_cfg_num_hci_cmd_pkts; - uint32_t ble_ll_ctrl_proc_timeout_ms; - uint16_t nimble_max_connections; - uint8_t ble_whitelist_size; - uint16_t ble_acl_buf_size; - uint16_t ble_acl_buf_count; - uint16_t ble_hci_evt_buf_size; - uint16_t ble_multi_adv_instances; - uint16_t ble_ext_adv_max_size; - uint16_t controller_task_stack_size; - uint8_t controller_task_prio; - uint8_t controller_run_cpu; - uint8_t enable_qa_test; - uint8_t enable_bqb_test; - uint8_t enable_uart_hci; - uint8_t ble_hci_uart_port; - uint32_t ble_hci_uart_baud; - uint8_t ble_hci_uart_data_bits; - uint8_t ble_hci_uart_stop_bits; - uint8_t ble_hci_uart_flow_ctrl; - uint8_t ble_hci_uart_uart_parity; - uint8_t enable_tx_cca; - uint8_t cca_rssi_thresh; - uint8_t sleep_en; - uint8_t coex_phy_coded_tx_rx_time_limit; - uint8_t dis_scan_backoff; - uint8_t ble_scan_classify_filter_enable; - uint8_t cca_drop_mode; - int8_t cca_low_tx_pwr; - uint8_t main_xtal_freq; - uint32_t config_magic; + struct { + uint32_t config_version; /*!< Version number of the defined structure */ + uint16_t ble_ll_resolv_list_size; /*!< Size of the resolvable private address list */ + uint16_t ble_hci_evt_hi_buf_count; /*!< Count of high buffers for HCI events */ + uint16_t ble_hci_evt_lo_buf_count; /*!< Count of low buffers for HCI events */ + uint8_t ble_ll_sync_list_cnt; /*!< Number of synchronization lists */ + uint8_t ble_ll_sync_cnt; /*!< Number of synchronizations */ + uint16_t ble_ll_rsp_dup_list_count; /*!< Count of duplicated lists for scan response packets */ + uint16_t ble_ll_adv_dup_list_count; /*!< Count of duplicated lists for advertising packets */ + uint8_t ble_ll_tx_pwr_dbm; /*!< Tx power (transmit power) in dBm */ + uint64_t rtc_freq; /*!< Frequency of RTC (Real-Time Clock) */ + uint16_t ble_ll_sca; /*!< Sleep Clock Accuracy (SCA) parameter */ + uint8_t ble_ll_scan_phy_number; /*!< Number of PHYs supported for scanning */ + uint16_t ble_ll_conn_def_auth_pyld_tmo; /*!< Connection default authentication payload timeout */ + uint8_t ble_ll_jitter_usecs; /*!< Jitter time in microseconds */ + uint16_t ble_ll_sched_max_adv_pdu_usecs; /*!< Maximum time in microseconds for advertising PDU scheduling */ + uint16_t ble_ll_sched_direct_adv_max_usecs; /*!< Maximum time in microseconds for directed advertising scheduling */ + uint16_t ble_ll_sched_adv_max_usecs; /*!< Maximum time in microseconds for advertising scheduling */ + uint16_t ble_scan_rsp_data_max_len; /*!< Maximum length of scan response data */ + uint8_t ble_ll_cfg_num_hci_cmd_pkts; /*!< Number of HCI command packets that can be queued */ + uint32_t ble_ll_ctrl_proc_timeout_ms; /*!< Control processing timeout in milliseconds */ + uint16_t nimble_max_connections; /*!< Maximum number of connections supported */ + uint8_t ble_whitelist_size; /*!< Size of the white list */ + uint16_t ble_acl_buf_size; /*!< Buffer size of ACL (Asynchronous Connection-Less) data */ + uint16_t ble_acl_buf_count; /*!< Buffer count of ACL data */ + uint16_t ble_hci_evt_buf_size; /*!< Buffer size for HCI event data */ + uint16_t ble_multi_adv_instances; /*!< Number of advertising instances */ + uint16_t ble_ext_adv_max_size; /*!< Maximum size of extended advertising data */ + uint16_t controller_task_stack_size; /*!< Size of Bluetooth controller task stack, to be removed */ + uint8_t controller_task_prio; /*!< Priority of the Bluetooth task, to be removed */ + uint8_t controller_run_cpu; /*!< CPU number on which the Bluetooth controller task runs, to be removed */ + uint8_t enable_qa_test; /*!< Enable for QA test */ + uint8_t enable_bqb_test; /*!< Enable for BQB test */ + uint8_t enable_tx_cca; /*!< Enable Clear Channel Assessment (CCA) when transmitting */ + uint8_t cca_rssi_thresh; /*!< RSSI threshold for CCA */ + uint8_t sleep_en; /*!< Enable sleep functionality */ + uint8_t coex_phy_coded_tx_rx_time_limit; /*!< Coexistence PHY coded TX and RX time limit */ + uint8_t dis_scan_backoff; /*!< Disable scan backoff */ + uint8_t ble_scan_classify_filter_enable; /*!< Enable classification filter for BLE scan */ + uint8_t cca_drop_mode; /*!< CCA drop mode */ + int8_t cca_low_tx_pwr; /*!< Low TX power setting for CCA */ + uint8_t main_xtal_freq; /*!< Main crystal frequency */ + uint8_t ignore_wl_for_direct_adv; /*!< Ignore the white list for directed advertising */ + uint8_t enable_pcl; /*!< Enable power control */ + uint8_t csa2_select; + uint8_t enable_csr; + int8_t backoff_rssi; + bool iso_enabled; + bool iso_bqb_test; + bool iso_fra_unseg; + bool iso_nsfc_en; + uint8_t iso_nsfc_num; + uint8_t iso_buf_count; + uint16_t iso_buf_size; + uint8_t iso_big_count; + uint16_t iso_bis_count; + uint8_t iso_bis_per_big; + uint8_t iso_cig_count; + uint16_t iso_cis_count; + uint8_t iso_cis_per_cig; + uint32_t config_magic; /*!< Configuration magic value */ + } ble; /* Bluetooth LE controller configuration options */ + + esp_btdm_controller_config_t btdm; /*!< BTDM controller common configuration options */ /*!< BTDM controller common configuration options */ } esp_bt_controller_config_t; +#if defined(CONFIG_BTDM_CTRL_MODE_BLE_ONLY) +#define BTDM_CONTROLLER_MODE_EFF ESP_BT_MODE_BLE +#elif defined(CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY) +#define BTDM_CONTROLLER_MODE_EFF ESP_BT_MODE_CLASSIC_BT +#else +#define BTDM_CONTROLLER_MODE_EFF ESP_BT_MODE_BTDM +#endif -#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ - .config_version = CONFIG_VERSION, \ - .ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE, \ - .ble_hci_evt_hi_buf_count = DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT, \ - .ble_hci_evt_lo_buf_count = DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT, \ - .ble_ll_sync_list_cnt = DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST, \ - .ble_ll_sync_cnt = DEFAULT_BT_LE_MAX_PERIODIC_SYNCS, \ - .ble_ll_rsp_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, \ - .ble_ll_adv_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, \ - .ble_ll_tx_pwr_dbm = BLE_LL_TX_PWR_DBM_N, \ - .rtc_freq = RTC_FREQ_N, \ - .ble_ll_sca = CONFIG_BT_LE_LL_SCA, \ - .ble_ll_scan_phy_number = BLE_LL_SCAN_PHY_NUMBER_N, \ - .ble_ll_conn_def_auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N, \ - .ble_ll_jitter_usecs = BLE_LL_JITTER_USECS_N, \ - .ble_ll_sched_max_adv_pdu_usecs = BLE_LL_SCHED_MAX_ADV_PDU_USECS_N, \ - .ble_ll_sched_direct_adv_max_usecs = BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N, \ - .ble_ll_sched_adv_max_usecs = BLE_LL_SCHED_ADV_MAX_USECS_N, \ - .ble_scan_rsp_data_max_len = DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N, \ - .ble_ll_cfg_num_hci_cmd_pkts = BLE_LL_CFG_NUM_HCI_CMD_PKTS_N, \ - .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N, \ - .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS, \ - .ble_whitelist_size = DEFAULT_BT_NIMBLE_WHITELIST_SIZE, \ - .ble_acl_buf_size = DEFAULT_BT_LE_ACL_BUF_SIZE, \ - .ble_acl_buf_count = DEFAULT_BT_LE_ACL_BUF_COUNT, \ - .ble_hci_evt_buf_size = DEFAULT_BT_LE_HCI_EVT_BUF_SIZE, \ - .ble_multi_adv_instances = DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES, \ - .ble_ext_adv_max_size = DEFAULT_BT_LE_EXT_ADV_MAX_SIZE, \ - .controller_task_stack_size = NIMBLE_LL_STACK_SIZE, \ - .controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \ - .controller_run_cpu = 0, \ - .enable_qa_test = RUN_QA_TEST, \ - .enable_bqb_test = RUN_BQB_TEST, \ - .enable_uart_hci = HCI_UART_EN, \ - .ble_hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT, \ - .ble_hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD, \ - .ble_hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS, \ - .ble_hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS, \ - .ble_hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL, \ - .ble_hci_uart_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY, \ - .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, \ - .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, \ - .cca_drop_mode = 0, \ - .cca_low_tx_pwr = 0, \ - .sleep_en = NIMBLE_SLEEP_ENABLE, \ - .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF, \ - .ble_scan_classify_filter_enable = 0, \ - .main_xtal_freq = CONFIG_XTAL_FREQ, \ - .config_magic = CONFIG_MAGIC, \ +#if defined(CONFIG_BT_CTRL_BR_EDR_TEST_MODE_EN) +#define BT_CTRL_BR_EDR_TEST_MODE_EN 1 +#else +#define BT_CTRL_BR_EDR_TEST_MODE_EN 0 +#endif + +#ifndef CONFIG_BT_CTRL_BR_EDR_DTM_EN_EFF +#define CONFIG_BT_CTRL_BR_EDR_DTM_EN_EFF false +#endif + +#if defined(CONFIG_BT_CTRL_BR_EDR_TX_CCA_ENABLED) + #define BT_CTRL_BR_EDR_TX_CCA_ENABLED (CONFIG_BT_CTRL_BR_EDR_TX_CCA_ENABLED) +#else + #define BT_CTRL_BR_EDR_TX_CCA_ENABLED (0) +#endif + +#if defined(CONFIG_BT_CTRL_BR_EDR_CCA_RSSI_THRESH) + #define BT_CTRL_BR_EDR_CCA_RSSI_THRESH (CONFIG_BT_CTRL_BR_EDR_CCA_RSSI_THRESH) +#else + #define BT_CTRL_BR_EDR_CCA_RSSI_THRESH (50) +#endif + +#if defined(CONFIG_BT_LE_ISO_SUPPORT) +#define DEFAULT_BT_LE_ISO_ENABLED 1 +#if defined(CONFIG_BT_LE_ISO_FRA_UNSEG) +#define DEFAULT_BT_LE_ISO_FRA_UNSEG CONFIG_BT_LE_ISO_FRA_UNSEG +#else +#define DEFAULT_BT_LE_ISO_FRA_UNSEG (0) +#endif +#if defined(CONFIG_BT_LE_ISO_NSFC_EN) +#define DEFAULT_BT_LE_ISO_NSFC_EN CONFIG_BT_LE_ISO_NSFC_EN +#define DEFAULT_BT_LE_ISO_NSFC_NUM CONFIG_BT_LE_ISO_NSFC_NUM +#else +#define DEFAULT_BT_LE_ISO_NSFC_EN (0) +#define DEFAULT_BT_LE_ISO_NSFC_NUM (0) +#endif +#define DEFAULT_BT_LE_ISO_BUF_COUNT CONFIG_BT_LE_ISO_BUF_COUNT +#define DEFAULT_BT_LE_ISO_BUF_SIZE CONFIG_BT_LE_ISO_BUF_SIZE +#define DEFAULT_BT_LE_ISO_BIG CONFIG_BT_LE_ISO_BIG +#define DEFAULT_BT_LE_ISO_BIS CONFIG_BT_LE_ISO_BIS +#define DEFAULT_BT_LE_ISO_BIS_PER_BIG CONFIG_BT_LE_ISO_BIS_PER_BIG +#define DEFAULT_BT_LE_ISO_CIG CONFIG_BT_LE_ISO_CIG +#define DEFAULT_BT_LE_ISO_CIS CONFIG_BT_LE_ISO_CIS +#define DEFAULT_BT_LE_ISO_CIS_PER_CIG CONFIG_BT_LE_ISO_CIS_PER_CIG +#else +#define DEFAULT_BT_LE_ISO_ENABLED 0 +#define DEFAULT_BT_LE_ISO_FRA_UNSEG 0 +#define DEFAULT_BT_LE_ISO_NSFC_EN 0 +#define DEFAULT_BT_LE_ISO_NSFC_NUM 0 +#define DEFAULT_BT_LE_ISO_BUF_COUNT 0 +#define DEFAULT_BT_LE_ISO_BUF_SIZE 0 +#define DEFAULT_BT_LE_ISO_BIG 0 +#define DEFAULT_BT_LE_ISO_BIS 0 +#define DEFAULT_BT_LE_ISO_BIS_PER_BIG 0 +#define DEFAULT_BT_LE_ISO_CIG 0 +#define DEFAULT_BT_LE_ISO_CIS 0 +#define DEFAULT_BT_LE_ISO_CIS_PER_CIG 0 +#endif + +#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ + .ble = { \ + .config_version = BLE_CONFIG_VERSION, \ + .ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE, \ + .ble_hci_evt_hi_buf_count = DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT, \ + .ble_hci_evt_lo_buf_count = DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT, \ + .ble_ll_sync_list_cnt = DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST, \ + .ble_ll_sync_cnt = DEFAULT_BT_LE_MAX_PERIODIC_SYNCS, \ + .ble_ll_rsp_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, \ + .ble_ll_adv_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, \ + .ble_ll_tx_pwr_dbm = 0, \ + .rtc_freq = 32000, \ + .ble_ll_sca = CONFIG_BT_LE_LL_SCA, \ + .ble_ll_scan_phy_number = BLE_LL_SCAN_PHY_NUMBER_N, \ + .ble_ll_conn_def_auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N, \ + .ble_ll_jitter_usecs = BLE_LL_JITTER_USECS_N, \ + .ble_ll_sched_max_adv_pdu_usecs = BLE_LL_SCHED_MAX_ADV_PDU_USECS_N, \ + .ble_ll_sched_direct_adv_max_usecs = BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N, \ + .ble_ll_sched_adv_max_usecs = BLE_LL_SCHED_ADV_MAX_USECS_N, \ + .ble_scan_rsp_data_max_len = DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N, \ + .ble_ll_cfg_num_hci_cmd_pkts = BLE_LL_CFG_NUM_HCI_CMD_PKTS_N, \ + .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N, \ + .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS, \ + .ble_whitelist_size = DEFAULT_BT_NIMBLE_WHITELIST_SIZE, \ + .ble_acl_buf_size = DEFAULT_BT_LE_ACL_BUF_SIZE, \ + .ble_acl_buf_count = DEFAULT_BT_LE_ACL_BUF_COUNT, \ + .ble_hci_evt_buf_size = DEFAULT_BT_LE_HCI_EVT_BUF_SIZE, \ + .ble_multi_adv_instances = DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES, \ + .ble_ext_adv_max_size = DEFAULT_BT_LE_EXT_ADV_MAX_SIZE, \ + .controller_task_stack_size = UC_BT_CTRL_TASK_STACK_SIZE, \ + .controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \ + .controller_run_cpu = 0, \ + .enable_qa_test = RUN_QA_TEST, \ + .enable_bqb_test = RUN_BQB_TEST, \ + .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, \ + .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, \ + .sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \ + .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF, \ + .dis_scan_backoff = NIMBLE_DISABLE_SCAN_BACKOFF, \ + .ble_scan_classify_filter_enable = 1, \ + .main_xtal_freq = CONFIG_XTAL_FREQ, \ + .ignore_wl_for_direct_adv = 0, \ + .enable_pcl = 0, \ + .csa2_select = 1, \ + .enable_csr = 0, \ + .backoff_rssi = -100, \ + .iso_enabled = DEFAULT_BT_LE_ISO_ENABLED, \ + .iso_bqb_test = false, \ + .iso_fra_unseg = DEFAULT_BT_LE_ISO_FRA_UNSEG, \ + .iso_nsfc_en = DEFAULT_BT_LE_ISO_NSFC_EN, \ + .iso_nsfc_num = DEFAULT_BT_LE_ISO_NSFC_NUM, \ + .iso_buf_count = DEFAULT_BT_LE_ISO_BUF_COUNT, \ + .iso_buf_size = DEFAULT_BT_LE_ISO_BUF_SIZE, \ + .iso_big_count = DEFAULT_BT_LE_ISO_BIG, \ + .iso_bis_count = DEFAULT_BT_LE_ISO_BIS, \ + .iso_bis_per_big = DEFAULT_BT_LE_ISO_BIS_PER_BIG, \ + .iso_cig_count = DEFAULT_BT_LE_ISO_CIG, \ + .iso_cis_count = DEFAULT_BT_LE_ISO_CIS, \ + .iso_cis_per_cig = DEFAULT_BT_LE_ISO_CIS_PER_CIG, \ + .config_magic = BLE_CONFIG_MAGIC, \ + }, \ + .btdm = { \ + .version = BTDM_CONFIG_VERSION, \ + .task_stack_size = UC_BT_CTRL_TASK_STACK_SIZE, \ + .task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \ + .task_run_cpu = CONFIG_BT_CTRL_PINNED_TO_CORE, \ + .hci_cmd_num = CONFIG_BT_CTRL_HCI_CMD_NUM, \ + .hci_conn_num = DEFAULT_BT_LE_MAX_CONNECTIONS + DEFAULT_BT_LE_ISO_CIS + DEFAULT_BT_LE_ISO_BIS, \ + .sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \ + .version_num = 0, \ + .bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \ + .magic = BTDM_CONFIG_MAGIC_VALUE, \ + }, \ } + +/** + * @brief Initialize BT controller to allocate task and other resource. + * This function should be called only once, before any other BT functions are called. + * @param cfg: Initial configuration of BT controller. Different from previous version, there's a mode and some + * connection configuration in "cfg" to configure controller work mode and allocate the resource which is needed. + * @return ESP_OK - success, other - failed + */ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg); /** @@ -267,11 +465,53 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg); * @return status value */ esp_bt_controller_status_t esp_bt_controller_get_status(void); + +/** + * @brief Get BLE TX power + * Connection Tx power should only be get after connection created. + * @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc + * @return >= 0 - Power level, < 0 - Invalid + */ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); + +/** + * @brief De-initialize BT controller to free resource and delete task. + * You should stop advertising and scanning, as well as + * disconnect all existing connections before de-initializing BT controller. + * + * This function should be called only once, after any other BT functions are called. + * This function is not whole completed, esp_bt_controller_init cannot called after this function. + * @return ESP_OK - success, other - failed + */ esp_err_t esp_bt_controller_deinit(void); + +/** + * @brief Enable BT controller. + * Due to a known issue, you cannot call esp_bt_controller_enable() a second time + * to change the controller mode dynamically. To change controller mode, call + * esp_bt_controller_disable() and then call esp_bt_controller_enable() with the new mode. + * @param mode : the mode(BLE/BT/BTDM) to enable. For compatible of API, retain this argument. This mode must be + * equal as the mode in "cfg" of esp_bt_controller_init(). + * @return ESP_OK - success, other - failed + */ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode); + +/** + * @brief Disable BT controller + * @return ESP_OK - success, other - failed + */ esp_err_t esp_bt_controller_disable(void); +/** + * @brief Get BT controller is initialised/de-initialised/enabled/disabled + * @return status value + */ +esp_bt_controller_status_t esp_bt_controller_get_status(void); + + +/** @brief esp_vhci_host_callback + * used for vhci call host function to notify what host need to do + */ typedef struct esp_vhci_host_callback { void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */ int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the controller has a packet to send to the host*/ @@ -359,9 +599,20 @@ esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); */ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode); -/* Returns random static address or -1 if not present */ +/** + * @brief Returns random static address or -1 if not present. + * @return ESP_OK - success, other - failed + */ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +/** + * @brief dump all log information cached in buffers. + * @param output : true for log dump, false will take no effect + */ +void esp_ble_controller_log_dump_all(bool output); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + #ifdef __cplusplus } #endif diff --git a/components/bt/include/esp32h4/include/esp_bt_vs.h b/components/bt/include/esp32h4/include/esp_bt_vs.h new file mode 100644 index 0000000000..3cbed92583 --- /dev/null +++ b/components/bt/include/esp32h4/include/esp_bt_vs.h @@ -0,0 +1,360 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// @brief HCI VS Commands for Espressif's Bluetooth Host +// +// @note The following vendor-specific HCI commands are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these commands will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS commands are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief Config scanning duplicate exceptional list (OCF: 0x0108) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_CONFIG_DUP_EXC_LIST_OCF (0x0108) +/** +* @brief Update exception list cmd parameters +*/ +struct bt_hci_vs_update_exc_list { + uint8_t subcode; /*!< Add, remove or clear exception list */ + uint32_t type; /*!< device type */ + uint8_t device_info[6]; /*!< device information */ +}; + +/** + * @brief Enable/disable advertising report flow control (OCF: 0x0109) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_ADV_REPORT_FLOW_CTRL_OCF (0x0109) +/** +* @brief Init ADV flow control cmd parameters +*/ +struct bt_hci_vs_init_adv_flow_ctrl { + uint8_t enable; /*!< Enable ADV flow control */ + uint16_t num; /*!< ADV buffer maximum value */ + uint16_t adv_lost_threshold; /*!< ADV lost event triggered threshold */ +}; + +/** + * @brief Update the number of advertising report in ADV flow control (OCF: 0x010A) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_UPD_ADV_REPORT_FLOW_CTRL_NUM_OCF (0x010a) +/** +* @brief Update ADV flow control cmd parameters +*/ +struct bt_hci_vs_update_adv_flow_ctrl { + uint16_t num; /*!< The number of ADV report processed */ +}; + +/** + * @brief Clear legacy advertising (same as HCI_LE_Clear_Advertising_Sets) (OCF: 0x010C) + * + * @note The init function is `adv_stack_enableClearLegacyAdvVsCmd(true)` + */ +#define ESP_BT_VS_CLR_LEGACY_ADV_OCF (0x010c) +/** +* @brief Clear legacy ADV cmd parameters +*/ +struct bt_hci_vs_ble_clr_legacy_adv { + // no parameters +}; + +/** + * @brief Set parameters of duplicate list (OCF: 0x010D) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_SET_DUP_LIST_PARAMS_OCF (0x010d) +/** +* @brief Set duplicate list cmd parameters +*/ +struct bt_hci_vs_ble_set_dup_params { + uint8_t dup_mode; /*!< Duplicate mode */ + uint8_t dup_ad_type; /*!< Duplicate data type */ + uint16_t ring_list_max_num; /*!< Duplicate list size */ +}; + +/** + * @brief Enable/disable duplicate and exception list (OCF: 0x010E) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_ENABLE_DUP_EXC_LIST_OCF (0x010e) +/** +* @brief Enable duplicate and exception list cmd parameters +*/ +struct bt_hci_vs_ble_enable_dup_exc { + uint8_t enable; /*!< Enable or disable */ + uint8_t ring_list_reset; /*!< Reset list */ +}; + +/** + * @brief Enable optimization of multiple connections (OCF: 0x010F) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_ARRANGEMENT_OCF (0x010f) +/** +* @brief Multiple connections optimization cmd parameters +*/ +struct bt_hci_vs_ble_enable_arrangement { + uint32_t common_factor; /*!< The greatest common factor of connection interval */ + uint8_t enable; /*!< Enable or disable */ +}; + +/** + * @brief Set scheduling length for a certain role (OCF: 0x0110) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_SET_SCHED_ROLE_LEN_OCF (0x0110) +/** +* @brief Scheduling length cmd parameters +*/ +struct bt_hci_vs_ble_set_sched_role_len { + uint8_t role; /*!< BLE role; 0: central; 1: peripheral */ + uint32_t len; /*!< Length is us */ +}; + +/** + * @brief Set RSSI threshold for automatic power control (OCF: 0x0111) + * + * @note The init function is `pcl_stack_enableSetRssiThreshVsCmd(true)` + */ +#define ESP_BT_VS_SET_PCL_RSSI_THRESH_OCF (0x0111) +/** +* @brief PCL RSSI threshold cmd parameters +*/ +struct bt_hci_vs_ble_set_pcl_rssi_thresh { + uint16_t conn_handle; /*!< Connection handle */ + uint8_t rssi_thresh_min_1M; /*!< Lower limit for 1M */ + uint8_t rssi_thresh_max_1M; /*!< Upper limit for 1M */ + uint8_t rssi_thresh_min_2M; /*!< Lower limit for 2M */ + uint8_t rssi_thresh_max_2M; /*!< Upper limit for 2M */ + uint8_t rssi_thresh_min_s2coded; /*!< Lower limit for s2 coded */ + uint8_t rssi_thresh_max_s2coded; /*!< Upper limit for s2 coded */ + uint8_t rssi_thresh_min_s8coded; /*!< Lower limit for s8 coded */ + uint8_t rssi_thresh_max_s8coded; /*!< Upper limit for s8 coded */ +}; + +/** + * @brief Enable/disable channel selection algorithm #2 (OCF: 0x0112) + * + * @note The init function is `chanSel_stack_enableSetCsaVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_CSA2_OCF (0x0112) +/** +* @brief Enable/disable channel selection algorithm #2 cmd parameters +*/ +struct bt_hci_vs_ble_csa_enable { + uint8_t csa2_select; /*!< Select CSA2 */ +}; + +/** + * @brief Set parameters of controller logs (OCF: 0x0114) + * + * @note The init function is `log_stack_enableLogsRelatedVsCmd(true)` + */ +#define ESP_BT_VS_SET_LOG_PARAMS_OCF (0x0114) +/** +* @brief Controller logs cmd parameters +*/ +struct bt_hci_vs_ble_log_params { + uint8_t type; /*!< Operation type */ + uint32_t output_enable; /*!< Enable/disable output */ + uint8_t buffer_optoin /*!< Select log buffers */ +}; + +/** + * @brief Set BLE vendor events mask (OCF: 0x0116) + * + * @note The init function is `hci_stack_enableSetVsEvtMaskVsCmd(true)` + */ +#define ESP_BT_VS_SET_LE_VENDOR_EVTS_MASK_OCF (0x0116) +/** +* @brief Set BLE vendor events mask cmd parameters +*/ +struct bt_hci_vs_ble_set_vs_evts_mask { + uint32_t evt_masks; /*!< BLE vendor events Mask */ +}; + +/** + * @brief Set peer sleep clock accuracy to a constant value (OCF: 0x0118) + * + * @note The init function is `winWiden_stack_enableSetConstPeerScaVsCmd(true)` + */ +#define ESP_BT_VS_SET_CONST_PEER_SCA_OCF (0x0118) +/** +* @brief Peer constant SCA cmd parameters +*/ +struct bt_hci_vs_ble_set_const_peer_sca { + uint16_t peer_sca; /*!< Peer SCA */ +}; + +// @brief HCI VS Events for Espressif's Bluetooth Host +// +// @note The following HCI VS events are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these events will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS events are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief BLE Scan/Connect Request, Aux Connect Response received event (EVTCODE: 0xFF, SUBCODE: 0xC0) + * + * @note The init function is `adv_stack_enableScanReqRxdVsEvent(true)` + */ +#define ESP_BT_VS_LE_CONN_SCAN_REQ_RXED_EVT_SUBCODE (0xC0) +/** +* @brief BLE Scan/Connect Request, Aux Connect Response received event parameters +*/ +struct bt_hci_vs_le_conn_scan_req_rxed_evt { + uint8_t evt_type; /*!< Event type; 0: SCAN_REQ; 1: CONN_IND */ + uint8_t handle; /*!< Advertisement handle */ + uint8_t peer_addr_type; /*!< Peer address type */ + uint8_t peer_addr[6]; /*!< Peer address */ +}; + +/** + * @brief BLE Channel Map Update Completion event (EVTCODE: 0xFF, SUBCODE: 0xC1) + * + * @note The init function is `conn_stack_enableChanMapUpdCompVsEvent(true)` + */ +#define ESP_BT_VS_LE_CHAN_UPDATE_COMP_EVT_SUBCODE (0xC1) +/** +* @brief BLE Channel Map Update Completion event parameters +*/ +struct bt_hci_vs_le_chan_update_comp_evt { + uint8_t status; /*!< Controller error code */ + uint16_t handle; /*!< Connection handle */ + uint8_t ch_map[5]; /*!< Updated channel map */ +}; + +/** + * @brief BLE Wakeup From Sleep event (EVTCODE: 0xFF, SUBCODE: 0xC3) + * + * @note The init function is `sleep_stack_enableWakeupVsEvent(true)` + */ +#define ESP_BT_VS_LE_SLEEP_WAKEUP_EVT_SUBCODE (0xC3) +/** +* @brief BLE wakeup event parameters +*/ +struct bt_hci_vs_le_sleep_wakeup_evt { + // no parameters +}; + +/** + * @brief BLE advertising report lost event for flow control (EVTCODE: 0x3E, SUBCODE: 0xF0) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LE_ADV_LOST_EVT_SUBCODE (0xF0) +/** +* @brief ADV lost event parameters +*/ +struct bt_hci_vs_le_adv_lost_evt { + uint32_t nb_lost; /*!< The number of ADV report discarded */ +}; + +// +// @brief HCI VS Commands for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging commands are implemented in Bluetooth controller pre-compiled libraries. +// These commands are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// They are intended for Espressif's internal use only. Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_CFG_TEST_RELATED_OCF (0x0113) + #define ESP_BT_VS_CFG_TEST_ENABLE_SUBCMD (0X00) + #define ESP_BT_VS_CFG_TEST_ENABLE_ADV_DELAY_SUBCMD (0X01) + #define ESP_BT_VS_CFG_TEST_SET_PREF_CODED_SUBCMD (0X02) + #define ESP_BT_VS_CFG_TEST_SET_DEFAULT_PRIV_MODE_SUBCMD (0X03) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_FOREVER_SUBCMD (0X04) + #define ESP_BT_VS_CFG_TEST_SET_EXPECTED_PEER_SUBCMD (0X05) + #define ESP_BT_VS_CFG_TEST_GET_ADV_TXED_CNT_SUBCMD (0X06) + #define ESP_BT_VS_CFG_TEST_GET_SCAN_RXED_CNT_SUBCMD (0X07) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_SUBCMD (0X08) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_SUBCMD (0X09) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_ENH_SUBCMD (0X0a) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_ENH_SUBCMD (0X0b) + #define ESP_BT_VS_CFG_TEST_IGNORE_WL_FOR_DIR_ADV_SUBCMD (0X0c) + #define ESP_BT_VS_CFG_TEST_GET_ADV_RXED_RSSI_SUBCMD (0X0d) + #define ESP_BT_VS_CFG_TEST_ENABLE_CCA_SUBCMD (0X0e) + #define ESP_BT_VS_CFG_TEST_SET_CCA_WIN_SUBCMD (0X0f) + #define ESP_BT_VS_CFG_TEST_READ_CCA_DATA_SUBCM (0X10) + #define ESP_BT_VS_CFG_TEST_CLEAR_RAND_ADDR_SUBCMD (0X11) + #define ESP_BT_VS_CFG_TEST_GET_MAX_TXPWR_SUBCMD (0X12) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_RANGE_SUBCMD (0X13) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_AA_SUBCMD (0X14) + #define ESP_BT_VS_CFG_TEST_SET_ADV_AA_SUBCMD (0X15) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_CHAN_SUBCMD (0X16) + #define ESP_BT_VS_CFG_TEST_SKIP_LIGHT_SLEEP_CHECK_SUBCMD (0X17) + #define ESP_BT_VS_CFG_TEST_SET_WAKEUP_OVERHEAD_SUBCMD (0X18) + #define ESP_BT_VS_CFG_TEST_GET_ADV_MIN_ITVL_SUBCMD (0X19) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_STATUS_SUBCMD (0X1a) + #define ESP_BT_VS_CFG_TEST_SET_CONN_PHY_TXPWR_SUBCMD (0X1b) + #define ESP_BT_VS_CFG_TEST_GET_CONN_PHY_TXPWR_SUBCMD (0X1c) + #define ESP_BT_VS_CFG_TEST_GET_RXBUF_EMPTY_CNT_SUBCMD (0X1d) + #define ESP_BT_VS_CFG_TEST_RESTART_SUBCMD (0X1e) + #define ESP_BT_VS_CFG_TEST_ENABLE_RECODE_RX_STATE_SUBCMD (0X1f) + #define ESP_BT_VS_CFG_TEST_GET_RECODE_CNT_SUBCMD (0X20) + #define ESP_BT_VS_CFG_TEST_CLR_RECODE_CNT_SUBCMD (0X21) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_COMPILE_VER_SUBCMD (0X24) + #define ESP_BT_VS_CFG_TEST_SET_AUX_ADV_OFFSET_SUBCMD (0X25) + #define ESP_BT_VS_CFG_TEST_INIT_FLEXIBLE_MODE_SUBCMD (0X26) + #define ESP_BT_VS_CFG_TEST_ENABLE_FLEXIBLE_MODE_SUBCMD (0X27) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_CONN_ERR_SUBCMD (0X28) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_ADV_ERR_SUBCMD (0X29) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_SCAN_ERR_SUBCMD (0X2a) + #define ESP_BT_VS_CFG_TEST_GET_TXED_CRCERR_SUBCMD (0X2c) + #define ESP_BT_VS_CFG_TEST_GET_BACKOFF_UPLIMIT_SUBCMD (0X2d) + #define ESP_BT_VS_CFG_TEST_GET_RXED_ADV_ADI_SUBCMD (0X2f) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_MODE_SUBCMD (0X30) + #define ESP_BT_VS_CFG_TEST_SET_RX_SENS_THRESH_SUBCMD (0X31) + #define ESP_BT_VS_CFG_TEST_CHECK_MSYS_BUF_SUBCMD (0X32) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_TIMER_SUBCMD (0X33) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_RTC_SUBCMD (0X34) + #define ESP_BT_VS_CFG_TEST_SET_LOCKED_MEM_NUM_SUBCMD (0X35) + #define ESP_BT_VS_CFG_TEST_ALLOW_MEM_ALLOC_SUBCMD (0X36) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_INFO_PTR_SUBCMD (0X37) + #define ESP_BT_VS_CFG_TEST_SET_DIAG_IO_SUBCMD (0X38) + #define ESP_BT_VS_CFG_TEST_SET_AGC_MAX_GAIN_SUBCMD (0X39) + #define ESP_BT_VS_CFG_TEST_ENABLE_CHAN_ASSESS_SUBCMD (0X40) + #define ESP_BT_VS_CFG_TEST_SET_BACKOFF_UPLIMIT_SUBCMD (0X41) + #define ESP_BT_VS_CFG_TEST_SET_CONN_TOP_PRIO_RESV_THRESH_SUBCMD (0X42) + #define ESP_BT_VS_CFG_TEST_SET_TEST_EVT_MSK_SUBCMD (0X43) + #define ESP_BT_VS_CFG_TEST_GET_WAKEUP_TIMEOUT_SUBCMD (0X45) + #define ESP_BT_VS_CFG_TEST_RELATED_SUBCMD_MAX (0Xff) + +// +// @brief HCI VS Events for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging events are implemented in Bluetooth controller pre-compiled libraries. +// These events are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_LE_RUNNING_STATUS_EVT_SUBCODE (0xC3) + + +#ifdef __cplusplus +} +#endif diff --git a/components/bt/porting/include/bt_osi_mem.h b/components/bt/porting/include/bt_osi_mem.h index 8a8c448b1d..3725afc4db 100644 --- a/components/bt/porting/include/bt_osi_mem.h +++ b/components/bt/porting/include/bt_osi_mem.h @@ -10,101 +10,19 @@ #include "esp_attr.h" #include "esp_heap_caps.h" -void *bt_osi_mem_malloc(size_t size); - -void *bt_osi_mem_calloc(size_t n, size_t size); void *bt_osi_mem_malloc_internal(size_t size); void *bt_osi_mem_calloc_internal(size_t n, size_t size); -void bt_osi_mem_free(void *ptr); - void bt_osi_mem_free_internal(void *ptr); + #if CONFIG_BT_LE_MEM_CHECK_ENABLED void bt_osi_mem_count_limit_set(uint16_t count_limit); #endif // CONFIG_BT_LE_MEM_CHECK_ENABLED #if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED size_t bt_osi_mem_internal_used_size_get(void); +// TODO: Remove it. bt_osi_mem_used_size_get has been defined in esp_nimble_mem.h. 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 e020abbf77..c80bb01458 100644 --- a/components/bt/porting/mem/bt_osi_mem.c +++ b/components/bt/porting/mem/bt_osi_mem.c @@ -10,311 +10,17 @@ #include "esp_log.h" #include -static uint8_t log_count; #if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED static size_t controller_mem_used_size = 0; -static size_t host_mem_used_size = 0; #endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED + #if CONFIG_BT_LE_MEM_CHECK_ENABLED static uint16_t mem_count_limit = 0; static uint16_t curr_mem_count; #endif // CONFIG_BT_LE_MEM_CHECK_ENABLED -#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 - mem = heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL - mem = heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT - mem = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#else - mem = malloc(size); -#endif - if (!mem) { - log_count ++; - if ((log_count % 100) == 0) { - ESP_EARLY_LOGI("ESP_LOG_INFO","malloc failed (size %zu)",size); - log_count = 0; - } - assert(mem != NULL); - } -#if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED - if(mem) { - host_mem_used_size += heap_caps_get_allocated_size(mem); - } -#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED - return mem; -} - -#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 - mem = heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL - mem = heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT - mem = heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#else - mem = calloc(n, size); -#endif -#if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED - if(mem) { - host_mem_used_size += heap_caps_get_allocated_size(mem); - } -#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED - return mem; -} - -#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE -IRAM_ATTR -#endif -void *bt_osi_mem_malloc_internal(size_t size) +void * +bt_osi_mem_malloc_internal(size_t size) { void *mem_ptr; #if CONFIG_BT_LE_MEM_CHECK_ENABLED @@ -334,10 +40,9 @@ void *bt_osi_mem_malloc_internal(size_t size) return mem_ptr; } -#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE -IRAM_ATTR -#endif -void *bt_osi_mem_calloc_internal(size_t n, size_t size) + +void * +bt_osi_mem_calloc_internal(size_t n, size_t size) { void *mem_ptr; #if CONFIG_BT_LE_MEM_CHECK_ENABLED @@ -357,10 +62,8 @@ void *bt_osi_mem_calloc_internal(size_t n, size_t size) return mem_ptr; } -#if !CONFIG_BT_NIMBLE_LOW_SPEED_MODE -IRAM_ATTR -#endif -void bt_osi_mem_free_internal(void *ptr) +void +bt_osi_mem_free_internal(void *ptr) { #if CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED if (ptr) { @@ -374,23 +77,6 @@ void bt_osi_mem_free_internal(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) { - size_t alloc_size = heap_caps_get_allocated_size(ptr); - // assert(host_mem_used_size >= alloc_size); - host_mem_used_size -= alloc_size; - } -#endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED - if (ptr) { - heap_caps_free(ptr); - } -} - #if CONFIG_BT_LE_MEM_CHECK_ENABLED void bt_osi_mem_count_limit_set(uint16_t count_limit) { @@ -406,21 +92,8 @@ bt_osi_mem_internal_used_size_get(void) return controller_mem_used_size; } -size_t -bt_osi_mem_used_size_get(void) -{ - return host_mem_used_size; -} - uint32_t esp_ble_controller_used_heap_size_get(void) { return bt_osi_mem_internal_used_size_get(); } - -#if CONFIG_BT_NIMBLE_ENABLED -uint32_t esp_host_used_heap_size_get(void) -{ - return bt_osi_mem_used_size_get(); -} -#endif // CONFIG_BT_NIMBLE_ENABLED #endif // CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED diff --git a/components/bt/porting_btdm/CMakeLists.txt b/components/bt/porting_btdm/CMakeLists.txt new file mode 100644 index 0000000000..51d5f519be --- /dev/null +++ b/components/bt/porting_btdm/CMakeLists.txt @@ -0,0 +1,56 @@ +set(porting_btdm_srcs "") +set(porting_btdm_include_dirs "") + +# btdm_common +file(GLOB_RECURSE BTDM_COMMON_SRCS "controller/btdm_common/src/*.c") +list(APPEND porting_btdm_srcs ${BTDM_COMMON_SRCS}) +list(APPEND porting_btdm_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/btdm_common/include") + +# ble +if(CONFIG_BTDM_CTRL_MODE_BLE_ONLY OR CONFIG_BTDM_CTRL_MODE_BTDM) + file(GLOB_RECURSE BLE_SRCS "controller/ble/src/*.c") + list(APPEND porting_btdm_srcs ${BLE_SRCS}) + list(APPEND porting_btdm_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/ble/include") +endif() + +# bredr +if(CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY OR CONFIG_BTDM_CTRL_MODE_BTDM) + file(GLOB_RECURSE BREDR_SRCS "controller/bredr/src/*.c") + list(APPEND porting_btdm_srcs ${BREDR_SRCS}) + list(APPEND porting_btdm_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/controller/bredr/include") +endif() + +# transport +file(GLOB_RECURSE TRANSPORT_SRCS "transport/src/*.c") +list(APPEND porting_btdm_srcs ${TRANSPORT_SRCS}) +list(APPEND porting_btdm_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/transport/include") +if(CONFIG_BT_CTRL_HCI_INTERFACE_USE_RAM) + if(CONFIG_BT_NIMBLE_ENABLED) + list(APPEND porting_btdm_srcs + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/vhci/hci_driver_nimble.c" + ) + else() + list(APPEND porting_btdm_srcs + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/vhci/hci_driver_standard.c" + ) + endif() +elseif(CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART) + list(APPEND porting_btdm_srcs + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/common/hci_driver_util.c" + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/common/hci_driver_h4.c" + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/common/hci_driver_mem.c" + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/uart/hci_driver_uart_config.c" + ) + if(CONFIG_BT_CTRL_UART_HCI_NO_DMA_MODE) + list(APPEND porting_btdm_srcs + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/uart/hci_driver_uart.c" + ) + else() + list(APPEND porting_btdm_srcs + "${CMAKE_CURRENT_SOURCE_DIR}/transport/driver/uart/hci_driver_uart_dma.c" + ) + endif() +endif() + +set(porting_btdm_srcs ${porting_btdm_srcs} PARENT_SCOPE) +set(porting_btdm_include_dirs ${porting_btdm_include_dirs} PARENT_SCOPE) diff --git a/components/bt/porting_btdm/controller/ble/include/ble_mbuf.h b/components/bt/porting_btdm/controller/ble/include/ble_mbuf.h new file mode 100644 index 0000000000..d802b2404d --- /dev/null +++ b/components/bt/porting_btdm/controller/ble/include/ble_mbuf.h @@ -0,0 +1,721 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _BLE_MBUF_H +#define _BLE_MBUF_H + +#include "btdm_mempool.h" +#include "queue.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A mbuf pool from which to allocate mbufs. This contains a pointer to the os + * mempool to allocate mbufs out of, the total number of elements in the pool, + * and the amount of "user" data in a non-packet header mbuf. The total pool + * size, in bytes, should be: + * ble_mbuf_count * (omp_databuf_len + sizeof(struct ble_mbuf)) + */ +struct ble_mbuf_pool { + /** + * Total length of the databuf in each mbuf. This is the size of the + * mempool block, minus the mbuf header + */ + uint16_t omp_databuf_len; + /** + * The memory pool which to allocate mbufs out of + */ + struct btdm_mempool *omp_pool; + + STAILQ_ENTRY(ble_mbuf_pool) omp_next; +}; + +/** + * A packet header structure that precedes the mbuf packet headers. + */ +struct ble_mbuf_pkthdr { + /** + * Overall length of the packet. + */ + uint16_t omp_len; + /** + * Flags + */ + uint16_t omp_flags; + + STAILQ_ENTRY(ble_mbuf_pkthdr) omp_next; +}; + +/** + * Chained memory buffer. + */ +struct ble_mbuf { + /** + * Current pointer to data in the structure + */ + uint8_t *om_data; + /** + * Flags associated with this buffer, see BLE_MBUF_F_* definitions + */ + uint8_t om_flags; + /** + * Length of packet header + */ + uint8_t om_pkthdr_len; + /** + * Length of data in this buffer + */ + uint16_t om_len; + + /** + * The mbuf pool this mbuf was allocated out of + */ + struct ble_mbuf_pool *om_omp; + + SLIST_ENTRY(ble_mbuf) om_next; + + /** + * Pointer to the beginning of the data, after this buffer + */ + uint8_t om_databuf[0]; +}; + +/* + * Checks whether a given mbuf is a packet header mbuf + * + * @param __om The mbuf to check + */ +#define BLE_MBUF_IS_PKTHDR(__om) ((__om)->om_pkthdr_len >= sizeof(struct ble_mbuf_pkthdr)) + +/** Get a packet header pointer given an mbuf pointer */ +#define BLE_MBUF_PKTHDR(__om) \ + ((struct ble_mbuf_pkthdr *)(uintptr_t)(void *)((uint8_t *)&(__om)->om_data + \ + sizeof(struct ble_mbuf))) + +/** Given a mbuf packet header pointer, return a pointer to the mbuf */ +#define BLE_MBUF_PKTHDR_TO_MBUF(__hdr) \ + (struct ble_mbuf *)(uintptr_t)((uint8_t *)(__hdr) - sizeof(struct ble_mbuf)) + +/** + * Gets the length of an entire mbuf chain. The specified mbuf must have a + * packet header. + */ +#define BLE_MBUF_PKTLEN(__om) (BLE_MBUF_PKTHDR(__om)->omp_len) + +/** + * Access the data of a mbuf, and cast it to type + * + * @param __om The mbuf to access, and cast + * @param __type The type to cast it to + */ +#define BLE_MBUF_DATA(__om, __type) (__type)((__om)->om_data) + +/** + * Access the "user header" in the head of an mbuf chain. + * + * @param om Pointer to the head of an mbuf chain. + */ +#define BLE_MBUF_USRHDR(om) \ + (void *)((uint8_t *)om + sizeof(struct ble_mbuf) + sizeof(struct ble_mbuf_pkthdr)) + +/** + * Retrieves the length of the user header in an mbuf. + * + * @param om Pointer to the mbuf to query. + */ +#define BLE_MBUF_USRHDR_LEN(om) ((om)->om_pkthdr_len - sizeof(struct ble_mbuf_pkthdr)) + +/* + * Called by BLE_MBUF_LEADINGSPACE() macro + */ +static inline uint16_t +_ble_mbuf_leadingspace(struct ble_mbuf *om) +{ + extern uint16_t r_os_mbuf_leadingspace(struct ble_mbuf * om); + return r_os_mbuf_leadingspace(om); +} + +/** + * Returns the leading space (space at the beginning) of the mbuf. + * Works on both packet header, and regular mbufs, as it accounts + * for the additional space allocated to the packet header. + * + * @param __omp Is the mbuf pool (which contains packet header length.) + * @param __om Is the mbuf in that pool to get the leadingspace for + * + * @return Amount of leading space available in the mbuf + */ +#define BLE_MBUF_LEADINGSPACE(__om) _ble_mbuf_leadingspace(__om) + +/** @cond INTERNAL_HIDDEN */ + +/* Called by BLE_MBUF_TRAILINGSPACE() macro. */ +static inline uint16_t +_ble_mbuf_trailingspace(struct ble_mbuf *om) +{ + extern uint16_t r_os_mbuf_trailingspace(struct ble_mbuf * om); + return r_os_mbuf_trailingspace(om); +} + +/** @endcond */ + +/** + * Returns the trailing space (space at the end) of the mbuf. + * Works on both packet header and regular mbufs. + * + * @param __omp The mbuf pool for this mbuf + * @param __om Is the mbuf in that pool to get trailing space for + * + * @return The amount of trailing space available in the mbuf + */ +#define BLE_MBUF_TRAILINGSPACE(__om) _ble_mbuf_trailingspace(__om) + +/** + * MSYS is a system level mbuf registry. Allows the system to share + * packet buffers amongst the various networking stacks that can be running + * simultaeneously. + * + * Mbuf pools are created in the system initialization code, and then when + * a mbuf is allocated out of msys, it will try and find the best fit based + * upon estimated mbuf size. + * + * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to + * allocate mbufs out of it. + * + * @param new_pool The pool to register with MSYS + * + * @return 0 on success, non-zero on failure + */ +static inline int +ble_msys_register(struct ble_mbuf_pool *mp) +{ + extern int r_os_msys_register(struct ble_mbuf_pool * mp); + return r_os_msys_register(mp); +} + +/** + * Allocate a mbuf from msys. Based upon the data size requested, + * os_msys_get() will choose the mbuf pool that has the best fit. + * + * @param dsize The estimated size of the data being stored in the mbuf + * @param leadingspace The amount of leadingspace to allocate in the mbuf + * + * @return A freshly allocated mbuf on success, NULL on failure. + */ +static inline struct ble_mbuf * +ble_msys_get(uint16_t dsize, uint16_t leadingspace) +{ + extern struct ble_mbuf *r_os_msys_get(uint16_t dsize, uint16_t leadingspace); + return r_os_msys_get(dsize, leadingspace); +} + +/** + * De-registers all mbuf pools from msys. + */ +static inline void +ble_msys_reset(void) +{ + extern void r_os_msys_reset(void); + r_os_msys_reset(); +} + +/** + * Allocate a packet header structure from the MSYS pool. See + * os_msys_register() for a description of MSYS. + * + * @param dsize The estimated size of the data being stored in the mbuf + * @param user_hdr_len The length to allocate for the packet header structure + * + * @return A freshly allocated mbuf on success, NULL on failure. + */ +static inline struct ble_mbuf * +ble_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len) +{ + extern struct ble_mbuf *r_os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len); + return r_os_msys_get_pkthdr(dsize, user_hdr_len); +} + +/** + * Count the number of blocks in all the mbuf pools that are allocated. + * + * @return total number of blocks allocated in Msys + */ +static inline int +ble_msys_count(void) +{ + extern int r_os_msys_count(void); + return r_os_msys_count(); +} + +/** + * Return the number of free blocks in Msys + * + * @return Number of free blocks available in Msys + */ +static inline int +ble_msys_num_free(void) +{ + extern int r_os_msys_num_free(void); + return r_os_msys_num_free(); +} + +/** + * Initialize a pool of mbufs. + * + * @param omp The mbuf pool to initialize + * @param mp The memory pool that will hold this mbuf pool + * @param buf_len The length of the buffer itself. + * @param nbufs The number of buffers in the pool + * + * @return 0 on success, error code on failure. + */ +static inline int +ble_mbuf_pool_init(struct ble_mbuf_pool *omp, struct btdm_mempool *mp, uint16_t buf_len, + uint16_t nbufs) +{ + extern int r_os_mbuf_pool_init(struct ble_mbuf_pool *, struct btdm_mempool * mp, uint16_t, + uint16_t); + return r_os_mbuf_pool_init(omp, mp, buf_len, nbufs); +} + +/** + * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized + * prior to being returned. + * + * @param omp The mbuf pool to return the packet from + * @param leadingspace The amount of leadingspace to put before the data + * section by default. + * + * @return An initialized mbuf on success, and NULL on failure. + */ +static inline struct ble_mbuf * +ble_mbuf_get(struct ble_mbuf_pool *omp, uint16_t leadingspace) +{ + extern struct ble_mbuf *r_os_mbuf_get(struct ble_mbuf_pool * omp, uint16_t leadingspace); + return r_os_mbuf_get(omp, leadingspace); +} + +/** + * Allocate a new packet header mbuf out of the os_mbuf_pool. + * + * @param omp The mbuf pool to allocate out of + * @param user_pkthdr_len The packet header length to reserve for the caller. + * + * @return A freshly allocated mbuf on success, NULL on failure. + */ +static inline struct ble_mbuf * +ble_mbuf_get_pkthdr(struct ble_mbuf_pool *omp, uint8_t user_pkthdr_len) +{ + extern struct ble_mbuf *r_os_mbuf_get_pkthdr(struct ble_mbuf_pool * omp, + uint8_t user_pkthdr_len); + return r_os_mbuf_get_pkthdr(omp, user_pkthdr_len); +} + +/** + * Duplicate a chain of mbufs. Return the start of the duplicated chain. + * + * @param omp The mbuf pool to duplicate out of + * @param om The mbuf chain to duplicate + * + * @return A pointer to the new chain of mbufs + */ +static inline struct ble_mbuf * +ble_mbuf_dup(struct ble_mbuf *m) +{ + extern struct ble_mbuf *r_os_mbuf_dup(struct ble_mbuf * m); + return r_os_mbuf_dup(m); +} + +/** + * Locates the specified absolute offset within an mbuf chain. The offset + * can be one past than the total length of the chain, but no greater. + * + * @param om The start of the mbuf chain to seek within. + * @param off The absolute address to find. + * @param out_off On success, this points to the relative offset + * within the returned mbuf. + * + * @return The mbuf containing the specified offset on + * success. + * NULL if the specified offset is out of bounds. + */ +static inline struct ble_mbuf * +ble_mbuf_off(const struct ble_mbuf *om, int off, uint16_t *out_off) +{ + extern struct ble_mbuf *r_os_mbuf_off(const struct ble_mbuf *om, int off, uint16_t *out_off); + return r_os_mbuf_off(om, off, out_off); +} + +/* + * Copy data from an mbuf chain starting "off" bytes from the beginning, + * continuing for "len" bytes, into the indicated buffer. + * + * @param m The mbuf chain to copy from + * @param off The offset into the mbuf chain to begin copying from + * @param len The length of the data to copy + * @param dst The destination buffer to copy into + * + * @return 0 on success; + * -1 if the mbuf does not contain enough data. + */ +static inline int +ble_mbuf_copydata(const struct ble_mbuf *m, int off, int len, void *dst) +{ + extern int r_os_mbuf_copydata(const struct ble_mbuf *m, int off, int len, void *dst); + return r_os_mbuf_copydata(m, off, len, dst); +} + +/** + * @brief Calculates the length of an mbuf chain. + * + * Calculates the length of an mbuf chain. If the mbuf contains a packet + * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to + * this function. + * + * @param om The mbuf to measure. + * + * @return The length, in bytes, of the provided mbuf + * chain. + */ +static inline uint16_t +ble_mbuf_len(const struct ble_mbuf *om) +{ + extern uint16_t r_os_mbuf_len(const struct ble_mbuf *om); + return r_os_mbuf_len(om); +} + +/** + * Append data onto a mbuf + * + * @param om The mbuf to append the data onto + * @param data The data to append onto the mbuf + * @param len The length of the data to append + * + * @return 0 on success, and an error code on failure + */ +static inline int +ble_mbuf_append(struct ble_mbuf *m, const void *data, uint16_t len) +{ + extern int r_os_mbuf_append(struct ble_mbuf * m, const void *, uint16_t); + return r_os_mbuf_append(m, data, len); +} + +/** + * Reads data from one mbuf and appends it to another. On error, the specified + * data range may be partially appended. Neither mbuf is required to contain + * an mbuf packet header. + * + * @param dst The mbuf to append to. + * @param src The mbuf to copy data from. + * @param src_off The absolute offset within the source mbuf + * chain to read from. + * @param len The number of bytes to append. + * + * @return 0 on success; + * OS_EINVAL if the specified range extends beyond + * the end of the source mbuf chain. + */ +static inline int +ble_mbuf_appendfrom(struct ble_mbuf *dst, const struct ble_mbuf *src, uint16_t src_off, + uint16_t len) +{ + extern int r_os_mbuf_appendfrom(struct ble_mbuf * dst, const struct ble_mbuf *src, + uint16_t src_off, uint16_t len); + return r_os_mbuf_appendfrom(dst, src, src_off, len); +} +/** + * Release a mbuf back to the pool + * + * @param mb The Mbuf to release back to the pool + * + * @return 0 on success, -1 on failure + */ +static inline int +ble_mbuf_free(struct ble_mbuf *mb) +{ + extern int r_os_mbuf_free(struct ble_mbuf * mb); + return r_os_mbuf_free(mb); +} +/** + * Free a chain of mbufs + * + * @param om The starting mbuf of the chain to free back into the pool + * + * @return 0 on success, -1 on failure + */ +static inline int +ble_mbuf_free_chain(struct ble_mbuf *om) +{ + extern int r_os_mbuf_free_chain(struct ble_mbuf * om); + return r_os_mbuf_free_chain(om); +} + +/** + * Adjust the length of a mbuf, trimming either from the head or the tail + * of the mbuf. + * + * @param mp The mbuf chain to adjust + * @param req_len The length to trim from the mbuf. If positive, trims + * from the head of the mbuf, if negative, trims from the + * tail of the mbuf. + */ +static inline void +ble_mbuf_adj(struct ble_mbuf *mp, int req_len) +{ + extern void r_os_mbuf_adj(struct ble_mbuf * mp, int req_len); + r_os_mbuf_adj(mp, req_len); +} + +/** + * Performs a memory compare of the specified region of an mbuf chain against a + * flat buffer. + * + * @param om The start of the mbuf chain to compare. + * @param off The offset within the mbuf chain to start the + * comparison. + * @param data The flat buffer to compare. + * @param len The length of the flat buffer. + * + * @return 0 if both memory regions are identical; + * A memcmp return code if there is a mismatch; + * INT_MAX if the mbuf is too short. + */ +static inline int +ble_mbuf_cmpf(const struct ble_mbuf *om, int off, const void *data, int len) +{ + extern int r_os_mbuf_cmpf(const struct ble_mbuf *om, int off, const void *data, int len); + return r_os_mbuf_cmpf(om, off, data, len); +} + +/** + * Compares the contents of two mbuf chains. The ranges of the two chains to + * be compared are specified via the two offset parameters and the len + * parameter. Neither mbuf chain is required to contain a packet header. + * + * @param om1 The first mbuf chain to compare. + * @param offset1 The absolute offset within om1 at which to + * start the comparison. + * @param om2 The second mbuf chain to compare. + * @param offset2 The absolute offset within om2 at which to + * start the comparison. + * @param len The number of bytes to compare. + * + * @return 0 if both mbuf segments are identical; + * A memcmp() return code if the segment contents + * differ; + * INT_MAX if a specified range extends beyond the + * end of its corresponding mbuf chain. + */ +static inline int +ble_mbuf_cmpm(const struct ble_mbuf *om1, uint16_t offset1, const struct ble_mbuf *om2, + uint16_t offset2, uint16_t len) +{ + extern int r_os_mbuf_cmpm(const struct ble_mbuf *om1, uint16_t offset1, + const struct ble_mbuf *om2, uint16_t offset2, uint16_t len); + return r_os_mbuf_cmpm(om1, offset1, om2, offset2, len); +} + +/** + * Increases the length of an mbuf chain by adding data to the front. If there + * is insufficient room in the leading mbuf, additional mbufs are allocated and + * prepended as necessary. If this function fails to allocate an mbuf, the + * entire chain is freed. + * + * The specified mbuf chain does not need to contain a packet header. + * + * @param omp The mbuf pool to allocate from. + * @param om The head of the mbuf chain. + * @param len The number of bytes to prepend. + * + * @return The new head of the chain on success; + * NULL on failure. + */ +static inline struct ble_mbuf * +ble_mbuf_prepend(struct ble_mbuf *om, int len) +{ + extern struct ble_mbuf *r_os_mbuf_prepend(struct ble_mbuf * om, int len); + return r_os_mbuf_prepend(om, len); +} + +/** + * Prepends a chunk of empty data to the specified mbuf chain and ensures the + * chunk is contiguous. If either operation fails, the specified mbuf chain is + * freed and NULL is returned. + * + * @param om The mbuf chain to prepend to. + * @param len The number of bytes to prepend and pullup. + * + * @return The modified mbuf on success; + * NULL on failure (and the mbuf chain is freed). + */ +static inline struct ble_mbuf * +ble_mbuf_prepend_pullup(struct ble_mbuf *om, uint16_t len) +{ + extern struct ble_mbuf *r_os_mbuf_prepend_pullup(struct ble_mbuf * om, uint16_t len); + return r_os_mbuf_prepend_pullup(om, len); +} + +/** + * Copies the contents of a flat buffer into an mbuf chain, starting at the + * specified destination offset. If the mbuf is too small for the source data, + * it is extended as necessary. If the destination mbuf contains a packet + * header, the header length is updated. + * + * @param om The mbuf chain to copy into. + * @param off The offset within the chain to copy to. + * @param src The source buffer to copy from. + * @param len The number of bytes to copy. + * + * @return 0 on success; nonzero on failure. + */ +static inline int +ble_mbuf_copyinto(struct ble_mbuf *om, int off, const void *src, int len) +{ + extern int r_os_mbuf_copyinto(struct ble_mbuf * om, int off, const void *src, int len); + return r_os_mbuf_copyinto(om, off, src, len); +} + +/** + * Attaches a second mbuf chain onto the end of the first. If the first chain + * contains a packet header, the header's length is updated. If the second + * chain has a packet header, its header is cleared. + * + * @param first The mbuf chain being attached to. + * @param second The mbuf chain that gets attached. + */ +static inline void +ble_mbuf_concat(struct ble_mbuf *first, struct ble_mbuf *second) +{ + extern void r_os_mbuf_concat(struct ble_mbuf * first, struct ble_mbuf * second); + r_os_mbuf_concat(first, second); +} + +/** + * Increases the length of an mbuf chain by the specified amount. If there is + * not sufficient room in the last buffer, a new buffer is allocated and + * appended to the chain. It is an error to request more data than can fit in + * a single buffer. + * + * @param om The head of the chain to extend. + * @param len The number of bytes to extend by. + * + * @return A pointer to the new data on success; + * NULL on failure. + */ +static inline void * +ble_mbuf_extend(struct ble_mbuf *om, uint16_t len) +{ + extern void *r_os_mbuf_extend(struct ble_mbuf * om, uint16_t len); + return r_os_mbuf_extend(om, len); +} + +/** + * Rearrange a mbuf chain so that len bytes are contiguous, + * and in the data area of an mbuf (so that OS_MBUF_DATA() will + * work on a structure of size len.) Returns the resulting + * mbuf chain on success, free's it and returns NULL on failure. + * + * If there is room, it will add up to "max_protohdr - len" + * extra bytes to the contiguous region, in an attempt to avoid being + * called next time. + * + * @param om The mbuf chain to make contiguous + * @param len The number of bytes in the chain to make contiguous + * + * @return The contiguous mbuf chain on success, NULL on failure. + */ +static inline struct ble_mbuf * +ble_mbuf_pullup(struct ble_mbuf *om, uint16_t len) +{ + extern struct ble_mbuf *r_os_mbuf_pullup(struct ble_mbuf * om, uint16_t len); + return r_os_mbuf_pullup(om, len); +} + +/** + * Removes and frees empty mbufs from the front of a chain. If the chain + * contains a packet header, it is preserved. + * + * @param om The mbuf chain to trim. + * + * @return The head of the trimmed mbuf chain. + */ +static inline struct ble_mbuf * +ble_mbuf_trim_front(struct ble_mbuf *om) +{ + extern struct ble_mbuf *r_os_mbuf_trim_front(struct ble_mbuf * om); + return r_os_mbuf_trim_front(om); +} + +/** + * Increases the length of an mbuf chain by inserting a gap at the specified + * offset. The contents of the gap are indeterminate. If the mbuf chain + * contains a packet header, its total length is increased accordingly. + * + * This function never frees the provided mbuf chain. + * + * @param om The mbuf chain to widen. + * @param off The offset at which to insert the gap. + * @param len The size of the gap to insert. + * + * @return 0 on success; SYS_[...] error code on failure. + */ +static inline int +ble_mbuf_widen(struct ble_mbuf *om, uint16_t off, uint16_t len) +{ + extern int r_os_mbuf_widen(struct ble_mbuf * om, uint16_t off, uint16_t len); + return r_os_mbuf_widen(om, off, len); +} + +/** + * Creates a single chained mbuf from m1 and m2 utilizing all + * the available buffer space in all mbufs in the resulting + * chain. In other words, ensures there is no leading space in + * any mbuf in the resulting chain and trailing space only in + * the last mbuf in the chain. Mbufs from either chain may be + * freed if not needed. No mbufs are allocated. Note that mbufs + * from m2 are added to the end of m1. If m1 has a packet + * header, it is retained and length updated. If m2 has a packet + * header it is discarded. If m1 is NULL, NULL is returned and + * m2 is left untouched. + * + * @param m1 Pointer to first mbuf chain to pack + * @param m2 Pointer to second mbuf chain to pack + * + * @return struct os_mbuf* Pointer to resulting mbuf chain + */ +static inline struct ble_mbuf * +ble_mbuf_pack_chains(struct ble_mbuf *m1, struct ble_mbuf *m2) +{ + extern struct ble_mbuf *r_os_mbuf_pack_chains(struct ble_mbuf * m1, struct ble_mbuf * m2); + return r_os_mbuf_pack_chains(m1, m2); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MBUF_H */ diff --git a/components/bt/porting_btdm/controller/ble/include/ble_msys.h b/components/bt/porting_btdm/controller/ble/include/ble_msys.h new file mode 100644 index 0000000000..d87ae1ff2d --- /dev/null +++ b/components/bt/porting_btdm/controller/ble/include/ble_msys.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BLE_MSYS_H_ +#define _BLE_MSYS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int ble_msys_init(void); + +void ble_msys_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MSYS_H_ */ diff --git a/components/bt/porting_btdm/controller/ble/include/ble_priv.h b/components/bt/porting_btdm/controller/ble/include/ble_priv.h new file mode 100644 index 0000000000..0abc7ed3b7 --- /dev/null +++ b/components/bt/porting_btdm/controller/ble/include/ble_priv.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _ESP_BLE_PRIV_H_ +#define _ESP_BLE_PRIV_H_ + +#include "btdm_osal.h" + +int ble_stack_init(esp_bt_controller_config_t *cfg); + +void ble_stack_deinit(void); + +int ble_stack_enable(void); + +void ble_stack_disable(void); + +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +esp_err_t sleep_modem_ble_mac_modem_state_init(void); +#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE + +void ble_osal_elem_calc(esp_bt_controller_config_t *cfg, btdm_osal_elem_num_t *elem); + +#endif // _ESP_BLE_PRIV_H_ diff --git a/components/bt/include/esp32h4/include/esp_bt_cfg.h b/components/bt/porting_btdm/controller/ble/include/ble_user_cfg.h similarity index 67% rename from components/bt/include/esp32h4/include/esp_bt_cfg.h rename to components/bt/porting_btdm/controller/ble/include/ble_user_cfg.h index 1f8caaeca8..61f5e5691f 100644 --- a/components/bt/include/esp32h4/include/esp_bt_cfg.h +++ b/components/bt/porting_btdm/controller/ble/include/ble_user_cfg.h @@ -1,16 +1,14 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __ESP_BT_CFG_H__ -#define __ESP_BT_CFG_H__ +#ifndef __BLE_USER_CFG_H__ +#define __BLE_USER_CFG_H__ #include #include -#include "esp_err.h" -#include "sdkconfig.h" #ifdef __cplusplus extern "C" { @@ -20,8 +18,6 @@ extern "C" { #include "syscfg/syscfg.h" #endif -#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE - #if CONFIG_BT_NIMBLE_ENABLED #if CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY @@ -29,7 +25,6 @@ extern "C" { #else #define BLE_LL_SCAN_PHY_NUMBER_N (1) #endif - #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST) #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS) #define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS) @@ -41,7 +36,8 @@ extern "C" { #define DEFAULT_BT_NIMBLE_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT) - + #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF + #define DEFAULT_BT_LE_POWER_CONTROL_ENABLED MYNEWT_VAL(BLE_POWER_CONTROL) #else #if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY @@ -116,35 +112,15 @@ extern "C" { #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (8) #endif - #if defined (CONFIG_BT_LE_HCI_UART_FLOWCTRL) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOWCTRL) - #if DEFAULT_BT_LE_HCI_UART_FLOW_CTRL - #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (CONFIG_BT_LE_HCI_UART_CTS_PIN) - #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (CONFIG_BT_LE_HCI_UART_RTS_PIN) - #else - #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) - #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) - #endif + #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF + + #if defined(CONFIG_BT_LE_POWER_CONTROL_ENABLED) + #define DEFAULT_BT_LE_POWER_CONTROL_ENABLED (CONFIG_BT_LE_POWER_CONTROL_ENABLED) #else - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) - #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) - #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #define DEFAULT_BT_LE_POWER_CONTROL_ENABLED (0) #endif #endif -#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF - -#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART -#define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART -#else -#define HCI_UART_EN 0 // hci ram mode -#endif - -#ifdef CONFIG_BT_LE_SLEEP_ENABLE -#define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE -#else -#define NIMBLE_SLEEP_ENABLE 0 -#endif #ifdef CONFIG_BT_LE_TX_CCA_ENABLED @@ -162,24 +138,6 @@ extern "C" { #define DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N DEFAULT_BT_LE_EXT_ADV_MAX_SIZE -#if HCI_UART_EN - #define DEFAULT_BT_LE_HCI_UART_TX_PIN (CONFIG_BT_LE_HCI_UART_TX_PIN) - #define DEFAULT_BT_LE_HCI_UART_RX_PIN (CONFIG_BT_LE_HCI_UART_RX_PIN) - #define DEFAULT_BT_LE_HCI_UART_PORT (CONFIG_BT_LE_HCI_UART_PORT) - #define DEFAULT_BT_LE_HCI_UART_BAUD (CONFIG_BT_LE_HCI_UART_BAUD) - #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS) - #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1) - #define DEFAULT_BT_LE_HCI_UART_PARITY (0) -#else - #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0) - #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0) - #define DEFAULT_BT_LE_HCI_UART_PORT (0) - #define DEFAULT_BT_LE_HCI_UART_BAUD (0) - #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0) - #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0) - #define DEFAULT_BT_LE_HCI_UART_PARITY (0) -#endif - /* Unchanged configuration */ #define BLE_LL_CTRL_PROC_TIMEOUT_MS_N (40000) /* ms */ @@ -200,26 +158,21 @@ extern "C" { #define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N (3000) -#if CONFIG_RTC_CLK_SRC_EXT_CRYS #define RTC_FREQ_N (32768) /* in Hz */ + +#define BLE_LL_TX_PWR_DBM_N (9) + +#ifdef CONFIG_BT_LE_BQB_TEST_EN +#define RUN_BQB_TEST (CONFIG_BT_LE_BQB_TEST_EN) #else -#define RTC_FREQ_N (32000) /* in Hz */ -#if CONFIG_RTC_CLK_SRC_EXT_OSC || CONFIG_RTC_CLK_SRC_INT_RC32K -#pragma message "RTC clock source may not available" -#endif -#endif - - -#define BLE_LL_TX_PWR_DBM_N (0) - - #define RUN_BQB_TEST (0) +#endif // CONFIG_BT_LE_BQB_TEST_EN + #define RUN_QA_TEST (0) #define NIMBLE_DISABLE_SCAN_BACKOFF (0) - #ifdef __cplusplus } #endif -#endif /* __ESP_BT_CFG_H__ */ +#endif /* __BLE_USER_CFG_H__ */ diff --git a/components/bt/porting_btdm/controller/ble/include/os/os_mempool.h b/components/bt/porting_btdm/controller/ble/include/os/os_mempool.h new file mode 100644 index 0000000000..05da058d1f --- /dev/null +++ b/components/bt/porting_btdm/controller/ble/include/os/os_mempool.h @@ -0,0 +1,425 @@ +/* + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * @addtogroup OSKernel + * @{ + * @defgroup OSMempool Memory Pools + * @{ + */ + + +#ifndef _OS_MEMPOOL_H_ +#define _OS_MEMPOOL_H_ + +#include +#include "os/os.h" +#include "os/queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A memory block structure. This simply contains a pointer to the free list + * chain and is only used when the block is on the free list. When the block + * has been removed from the free list the entire memory block is usable by the + * caller. + */ +struct os_memblock { + SLIST_ENTRY(os_memblock) mb_next; +}; + +/* XXX: Change this structure so that we keep the first address in the pool? */ +/* XXX: add memory debug structure and associated code */ +/* XXX: Change how I coded the SLIST_HEAD here. It should be named: + SLIST_HEAD(,os_memblock) mp_head; */ + +/** + * Memory pool + */ +struct os_mempool { + /** Size of the memory blocks, in bytes. */ + uint32_t mp_block_size; + /** The number of memory blocks. */ + uint16_t mp_num_blocks; + /** The number of free blocks left */ + uint16_t mp_num_free; + /** The lowest number of free blocks seen */ + uint16_t mp_min_free; + /** Bitmap of OS_MEMPOOL_F_[...] values. */ + uint8_t mp_flags; + /** Address of memory buffer used by pool */ + uint32_t mp_membuf_addr; + STAILQ_ENTRY(os_mempool) mp_list; + SLIST_HEAD(,os_memblock); + /** Name for memory block */ + const char *name; + /** The number of allocated blocks. */ + uint32_t mp_alloc_blocks; +}; + +/** + * Indicates an extended mempool. Address can be safely cast to + * (struct os_mempool_ext *). + */ +#define OS_MEMPOOL_F_EXT 0x01 +/* Flag to indicate runtime allocation mode */ +#define OS_MEMPOOL_F_RUNTIME 0x02 +/* Flag to indicate reuse block for runtime allocation mode */ +#define OS_MEMPOOL_F_REUSED 0x04 + +struct os_mempool_ext; + +/** + * Block put callback function. If configured, this callback gets executed + * whenever a block is freed to the corresponding extended mempool. Note: The + * os_memblock_put() function calls this callback instead of freeing the block + * itself. Therefore, it is the callback's responsibility to free the block + * via a call to os_memblock_put_from_cb(). + * + * @param ome The extended mempool that a block is being + * freed back to. + * @param data The block being freed. + * @param arg Optional argument configured along with the + * callback. + * + * @return Indicates whether the block was successfully + * freed. A non-zero value should only be + * returned if the block was not successfully + * released back to its pool. + */ +typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data, + void *arg); + +struct os_mempool_ext { + struct os_mempool mpe_mp; + + /* Callback that is executed immediately when a block is freed. */ + os_mempool_put_fn *mpe_put_cb; + void *mpe_put_arg; +}; + +#define OS_MEMPOOL_INFO_NAME_LEN (32) + +/** + * Information describing a memory pool, used to return OS information + * to the management layer. + */ +struct os_mempool_info { + /** Size of the memory blocks in the pool */ + int omi_block_size; + /** Number of memory blocks in the pool */ + int omi_num_blocks; + /** Number of free memory blocks */ + int omi_num_free; + /** Minimum number of free memory blocks ever */ + int omi_min_free; + /** Name of the memory pool */ + char omi_name[OS_MEMPOOL_INFO_NAME_LEN]; +}; + +/** + * Get information about the next system memory pool. + * + * @param mempool The current memory pool, or NULL if starting iteration. + * @param info A pointer to the structure to return memory pool information + * into. + * + * @return The next memory pool in the list to get information about, or NULL + * when at the last memory pool. + */ +struct os_mempool *os_mempool_info_get_next(struct os_mempool *, + struct os_mempool_info *); + +/* + * To calculate size of the memory buffer needed for the pool. NOTE: This size + * is NOT in bytes! The size is the number of os_membuf_t elements required for + * the memory pool. + */ +#if MYNEWT_VAL(OS_MEMPOOL_GUARD) +/* + * Leave extra 4 bytes of guard area at the end. + */ +#define OS_MEMPOOL_BLOCK_SZ(sz) ((sz) + sizeof(os_membuf_t)) +#else +#define OS_MEMPOOL_BLOCK_SZ(sz) (sz) +#endif +#if (OS_ALIGNMENT == 4) +typedef uint32_t os_membuf_t; +#elif (OS_ALIGNMENT == 8) +typedef uint64_t os_membuf_t; +#elif (OS_ALIGNMENT == 16) +typedef __uint128_t os_membuf_t; +#else +#error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`" +#endif /* OS_ALIGNMENT == * */ +#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n)) + +/** Calculates the number of bytes required to initialize a memory pool. */ +#define OS_MEMPOOL_BYTES(n,blksize) \ + (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize))) + +#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED +/** + * Initialize a memory pool. + * + * @param mp Pointer to a pointer to a mempool + * @param blocks The number of blocks in the pool + * @param blocks_size The size of the block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return os_error_t + */ +os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks, + uint32_t block_size, void *membuf, const char *name); +#define os_mempool_init r_os_mempool_init +/** + * Initializes an extended memory pool. Extended attributes (e.g., callbacks) + * are not specified when this function is called; they are assigned manually + * after initialization. + * + * @param mpe The extended memory pool to initialize. + * @param blocks The number of blocks in the pool. + * @param block_size The size of each block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return os_error_t + */ +os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, + uint32_t block_size, void *membuf, const char *name); +#define os_mempool_ext_init r_os_mempool_ext_init +/** + * Removes the specified mempool from the list of initialized mempools. + * + * @param mp The mempool to unregister. + * + * @return 0 on success; + * OS_INVALID_PARM if the mempool is not + * registered. + */ +// os_error_t r_os_mempool_unregister(struct os_mempool *mp); +#define os_mempool_unregister(mp) + + +/** + * Clears a memory pool. + * + * @param mp The mempool to clear. + * + * @return os_error_t + */ +os_error_t r_os_mempool_clear(struct os_mempool *mp); +#define os_mempool_clear r_os_mempool_clear + + +/** + * Performs an integrity check of the specified mempool. This function + * attempts to detect memory corruption in the specified memory pool. + * + * @param mp The mempool to check. + * + * @return true if the memory pool passes the integrity + * check; + * false if the memory pool is corrupt. + */ +bool r_os_mempool_is_sane(const struct os_mempool *mp); +#define os_mempool_is_sane r_os_mempool_is_sane + + +/** + * Checks if a memory block was allocated from the specified mempool. + * + * @param mp The mempool to check as parent. + * @param block_addr The memory block to check as child. + * + * @return 0 if the block does not belong to the mempool; + * 1 if the block does belong to the mempool. + */ +int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr); +#define os_memblock_from r_os_memblock_from + + +/** + * Get a memory block from a memory pool + * + * @param mp Pointer to the memory pool + * + * @return void* Pointer to block if available; NULL otherwise + */ +void *r_os_memblock_get(struct os_mempool *mp); +#define os_memblock_get r_os_memblock_get +/** + * Puts the memory block back into the pool, ignoring the put callback, if any. + * This function should only be called from a put callback to free a block + * without causing infinite recursion. + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return os_error_t + */ +os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); +#define os_memblock_put_from_cb r_os_memblock_put_from_cb + + +/** + * Puts the memory block back into the pool + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return os_error_t + */ +os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr); +#define os_memblock_put r_os_memblock_put + +#else +/** + * Initialize a memory pool. + * + * @param mp Pointer to a pointer to a mempool + * @param blocks The number of blocks in the pool + * @param blocks_size The size of the block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return os_error_t + */ +os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks, + uint32_t block_size, void *membuf, const char *name); + +/** + * Initializes an extended memory pool. Extended attributes (e.g., callbacks) + * are not specified when this function is called; they are assigned manually + * after initialization. + * + * @param mpe The extended memory pool to initialize. + * @param blocks The number of blocks in the pool. + * @param block_size The size of each block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return os_error_t + */ +os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, + uint32_t block_size, void *membuf, const char *name); + +/** + * Removes the specified mempool from the list of initialized mempools. + * + * @param mp The mempool to unregister. + * + * @return 0 on success; + * OS_INVALID_PARM if the mempool is not + * registered. + */ +os_error_t os_mempool_unregister(struct os_mempool *mp); + +/** + * Clears a memory pool. + * + * @param mp The mempool to clear. + * + * @return os_error_t + */ +os_error_t os_mempool_clear(struct os_mempool *mp); + +/** + * Clears an extended memory pool. + * + * @param mpe The extended memory pool to clear. + * + * @return os_error_t + */ +os_error_t os_mempool_ext_clear(struct os_mempool_ext *mpe); + +/** + * Performs an integrity check of the specified mempool. This function + * attempts to detect memory corruption in the specified memory pool. + * + * @param mp The mempool to check. + * + * @return true if the memory pool passes the integrity + * check; + * false if the memory pool is corrupt. + */ +bool os_mempool_is_sane(const struct os_mempool *mp); + +/** + * Checks if a memory block was allocated from the specified mempool. + * + * @param mp The mempool to check as parent. + * @param block_addr The memory block to check as child. + * + * @return 0 if the block does not belong to the mempool; + * 1 if the block does belong to the mempool. + */ +int os_memblock_from(const struct os_mempool *mp, const void *block_addr); + +/** + * Get a memory block from a memory pool + * + * @param mp Pointer to the memory pool + * + * @return void* Pointer to block if available; NULL otherwise + */ +void *os_memblock_get(struct os_mempool *mp); + +/** + * Puts the memory block back into the pool, ignoring the put callback, if any. + * This function should only be called from a put callback to free a block + * without causing infinite recursion. + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return os_error_t + */ +os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); + +/** + * Puts the memory block back into the pool + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return os_error_t + */ +os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _OS_MEMPOOL_H_ */ + + +/** + * @} OSMempool + * @} OSKernel + */ diff --git a/components/bt/porting_btdm/controller/ble/src/ble_msys.c b/components/bt/porting_btdm/controller/ble/src/ble_msys.c new file mode 100644 index 0000000000..1924de4298 --- /dev/null +++ b/components/bt/porting_btdm/controller/ble/src/ble_msys.c @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_err.h" +#include "queue.h" +#include "sdkconfig.h" + +#if CONFIG_BT_NIMBLE_ENABLED +#include "syscfg/syscfg.h" +#endif + +/* + *************************************************************************************************** + * Local Defined Macros + *************************************************************************************************** + */ +#define BLE_MSYS_ALIGN(__n, __a) \ + ((((__n) & ((__a) - 1)) == 0) ? (__n) : ((__n) + ((__a) - ((__n) & ((__a) - 1))))) + +#if CONFIG_BT_NIMBLE_ENABLED +#define BLE_MSYS_1_BLOCK_COUNT MYNEWT_VAL(MSYS_1_BLOCK_COUNT) +#define BLE_MSYS_1_BLOCK_SIZE MYNEWT_VAL(MSYS_1_BLOCK_SIZE) +#define BLE_MSYS_2_BLOCK_COUNT MYNEWT_VAL(MSYS_2_BLOCK_COUNT) +#define BLE_MSYS_2_BLOCK_SIZE MYNEWT_VAL(MSYS_2_BLOCK_SIZE) +#define BLE_MSYS_BLOCK_FROM_HEAP CONFIG_BT_NIMBLE_MSYS_BUF_FROM_HEAP +#else +#define BLE_MSYS_1_BLOCK_COUNT CONFIG_BT_LE_MSYS_1_BLOCK_COUNT +#define BLE_MSYS_1_BLOCK_SIZE CONFIG_BT_LE_MSYS_1_BLOCK_SIZE +#define BLE_MSYS_2_BLOCK_COUNT CONFIG_BT_LE_MSYS_2_BLOCK_COUNT +#define BLE_MSYS_2_BLOCK_SIZE CONFIG_BT_LE_MSYS_2_BLOCK_SIZE +#define BLE_MSYS_BLOCK_FROM_HEAP CONFIG_BT_LE_MSYS_BUF_FROM_HEAP +#endif /* CONFIG_BT_NIMBLE_ENABLED */ + +#if BLE_MSYS_1_BLOCK_COUNT > 0 +#define SYSINIT_MSYS_1_MEMBLOCK_SIZE BLE_MSYS_ALIGN(BLE_MSYS_1_BLOCK_SIZE, 4) +#define SYSINIT_MSYS_1_MEMPOOL_SIZE \ + OS_MEMPOOL_SIZE(BLE_MSYS_1_BLOCK_COUNT, SYSINIT_MSYS_1_MEMBLOCK_SIZE) +#else +#error "BLE_MSYS_1_BLOCK_COUNT should be larger than 0!" +#endif /* BLE_MSYS_1_BLOCK_COUNT > 0 */ + +#if BLE_MSYS_2_BLOCK_COUNT > 0 +#define SYSINIT_MSYS_2_MEMBLOCK_SIZE BLE_MSYS_ALIGN(BLE_MSYS_2_BLOCK_SIZE, 4) +#define SYSINIT_MSYS_2_MEMPOOL_SIZE \ + OS_MEMPOOL_SIZE(BLE_MSYS_2_BLOCK_COUNT, SYSINIT_MSYS_2_MEMBLOCK_SIZE) +#else +#error #error "BLE_MSYS_2_BLOCK_COUNT should be larger than 0!" +#endif /* BLE_MSYS_2_BLOCK_COUNT > 0 */ + +/* + *************************************************************************************************** + * External Functions + *************************************************************************************************** + */ +extern int r_esp_ble_msys_init(uint16_t msys_size1, uint16_t msys_size2, uint16_t msys_cnt1, + uint16_t msys_cnt2, uint8_t from_heap); +extern void r_esp_ble_msys_deinit(void); + +/* + *************************************************************************************************** + * BLE MSYS Initialization + *************************************************************************************************** + */ +int +ble_msys_init(void) +{ + return r_esp_ble_msys_init(SYSINIT_MSYS_1_MEMBLOCK_SIZE, SYSINIT_MSYS_2_MEMBLOCK_SIZE, + BLE_MSYS_1_BLOCK_COUNT, BLE_MSYS_2_BLOCK_COUNT, + BLE_MSYS_BLOCK_FROM_HEAP); +} + +void +ble_msys_deinit(void) +{ + r_esp_ble_msys_deinit(); +} diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_coex.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_coex.h new file mode 100644 index 0000000000..a30cd4166e --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_coex.h @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BTDM_COEX_H_ +#define _BTDM_COEX_H_ + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t btdm_coex_init(void); + +void btdm_coex_deinit(void); + +esp_err_t btdm_coex_enable(void); + +void btdm_coex_disable(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BTDM_COEX_H_ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_endian.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_endian.h new file mode 100644 index 0000000000..2fbab35d25 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_endian.h @@ -0,0 +1,146 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BTDM_ENDIAN_H_ +#define _BTDM_ENDIAN_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void +btdm_put_le16(void *buf, uint16_t x) +{ + extern void r_btdm_put_le16(void *buf, uint16_t x); + r_btdm_put_le16(buf, x); +} + +static inline void +btdm_put_le24(void *buf, uint32_t x) +{ + extern void r_btdm_put_le24(void *buf, uint32_t x); + r_btdm_put_le24(buf, x); +} + +static inline void +btdm_put_le32(void *buf, uint32_t x) +{ + extern void r_btdm_put_le32(void *buf, uint32_t x); + r_btdm_put_le32(buf, x); +} + +static inline void +btdm_put_le64(void *buf, uint64_t x) +{ + extern void r_btdm_put_le64(void *buf, uint64_t x); + r_btdm_put_le64(buf, x); +} + +static inline uint16_t +btdm_get_le16(const void *buf) +{ + extern uint16_t r_btdm_get_le16(const void *buf); + return r_btdm_get_le16(buf); +} + +static inline uint32_t +btdm_get_le24(const void *buf) +{ + extern uint32_t r_btdm_get_le24(const void *buf); + return r_btdm_get_le24(buf); +} + +static inline uint32_t +btdm_get_le32(const void *buf) +{ + extern uint32_t r_btdm_get_le32(const void *buf); + return r_btdm_get_le32(buf); +} + +static inline uint64_t +btdm_get_le64(const void *buf) +{ + extern uint64_t r_btdm_get_le64(const void *buf); + return r_btdm_get_le64(buf); +} + +static inline void +btdm_put_be16(void *buf, uint16_t x) +{ + extern void r_btdm_put_be16(void *buf, uint16_t x); + r_btdm_put_be16(buf, x); +} + +static inline void +btdm_put_be24(void *buf, uint32_t x) +{ + extern void r_btdm_put_be24(void *buf, uint32_t x); + r_btdm_put_be24(buf, x); +} + +static inline void +btdm_put_be32(void *buf, uint32_t x) +{ + extern void r_btdm_put_be32(void *buf, uint32_t x); + r_btdm_put_be32(buf, x); +} + +static inline void +btdm_put_be64(void *buf, uint64_t x) +{ + extern void r_btdm_put_be64(void *buf, uint64_t x); + r_btdm_put_be64(buf, x); +} + +static inline uint16_t +btdm_get_be16(const void *buf) +{ + extern uint16_t r_btdm_get_be16(const void *buf); + return r_btdm_get_be16(buf); +} + +static inline uint32_t +btdm_get_be24(const void *buf) +{ + extern uint32_t r_btdm_get_be24(const void *buf); + return r_btdm_get_be24(buf); +} + +static inline uint32_t +btdm_get_be32(const void *buf) +{ + extern uint32_t r_btdm_get_be32(const void *buf); + return r_btdm_get_be32(buf); +} + +static inline uint64_t +btdm_get_be64(const void *buf) +{ + extern uint64_t r_btdm_get_be64(const void *buf); + return r_btdm_get_be64(buf); +} + +static inline void +btdm_swap_in_place(void *buf, int len) +{ + extern void r_btdm_swap_in_place(void *buf, int len); + r_btdm_swap_in_place(buf, len); +} + +static inline void +btdm_swap_buf(uint8_t *dst, const uint8_t *src, int len) +{ + extern void r_btdm_swap_buf(uint8_t *dst, const uint8_t *src, int len); + r_btdm_swap_buf(dst, src, len); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BTDM_ENDIAN_H_ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_external.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_external.h new file mode 100644 index 0000000000..676977a7fe --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_external.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BTDM_EXTERNAL_H_ +#define _BTDM_EXTERNAL_H_ + +#include +#include + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BTDM_EXTERNAL_WR_FUNC(f) wr_ ## f + +#define btdm_external_bb_get_tx_pwr_table BTDM_EXTERNAL_WR_FUNC(btdm_external_bb_get_tx_pwr_table) + +/* + * Function declarations for BTDM EXTERNAL + */ +const int8_t *wr_btdm_external_bb_get_tx_pwr_table(uint8_t *length); + +int btdm_external_init(void); +void btdm_external_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BTDM_EXTERNAL_H_ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_log.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_log.h new file mode 100644 index 0000000000..ef346df7b5 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_log.h @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BTDM_LOG_H_ +#define _BTDM_LOG_H_ + +int btdm_log_init(void); + +void btdm_log_deinit(void); + +#endif diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_lp.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_lp.h new file mode 100644 index 0000000000..ad1db4686d --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_lp.h @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BTDM_LP_H_ +#define _BTDM_LP_H_ + +void btdm_lp_enable_clock(esp_btdm_controller_config_t *cfg); + +void btdm_lp_disable_clock(void); + +int btdm_lp_init(void); + +void btdm_lp_deinit(void); + +void btdm_lp_reset(bool enable_stage); + +void btdm_lp_shutdown(void); + +#endif diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_mempool.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_mempool.h new file mode 100644 index 0000000000..32b49a7b38 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_mempool.h @@ -0,0 +1,244 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _BTDM_MEMPOOL_H_ +#define _BTDM_MEMPOOL_H_ + +#include "btdm_osal.h" +#include "queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A memory block structure. This simply contains a pointer to the free list + * chain and is only used when the block is on the free list. When the block + * has been removed from the free list the entire memory block is usable by the + * caller. + */ +struct btdm_memblock { + SLIST_ENTRY(btdm_memblock) mb_next; +}; + +/* XXX: Change this structure so that we keep the first address in the pool? */ +/* XXX: add memory debug structure and associated code */ +/* XXX: Change how I coded the SLIST_HEAD here. It should be named: + SLIST_HEAD(,btdm_memblock) mp_head; */ + +/** + * Memory pool + */ +struct btdm_mempool { + /** Size of the memory blocks, in bytes. */ + uint32_t mp_block_size; + /** The number of memory blocks. */ + uint16_t mp_num_blocks; + /** The number of free blocks left */ + uint16_t mp_num_free; + /** The lowest number of free blocks seen */ + uint16_t mp_min_free; + /** Bitmap of OS_MEMPOOL_F_[...] values. */ + uint8_t mp_flags; + /** Address of memory buffer used by pool */ + uint32_t mp_membuf_addr; + STAILQ_ENTRY(btdm_mempool) mp_list; + SLIST_HEAD(, btdm_memblock); + /** Name for memory block */ + const char *name; +}; + +/** + * Indicates an extended mempool. Address can be safely cast to + * (struct btdm_mempool_ext *). + */ +#define BTDM_MEMPOOL_F_EXT 0x01 + +#define BTDM_ALIGNMENT 4 +#define BTDM_MEMPOOL_SIZE(n, blksize) \ + ((((blksize) + ((BTDM_ALIGNMENT) - 1)) / (BTDM_ALIGNMENT)) * (n)) + +#if (BTDM_ALIGNMENT == 4) +typedef uint32_t btdm_membuf_t; +#elif (BTDM_ALIGNMENT == 8) +typedef uint64_t btdm_membuf_t; +#elif (BTDM_ALIGNMENT == 16) +typedef __uint128_t btdm_membuf_t; +#else +#error "Unhandled `BTDM_ALIGNMENT` for `btdm_membuf_t`" +#endif /* BTDM_ALIGNMENT == * */ + +/** + * Initialize a memory pool. + * + * @param mp Pointer to a pointer to a mempool + * @param blocks The number of blocks in the pool + * @param blocks_size The size of the block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return btdm_osal_error_t + */ +static inline btdm_osal_error_t +btdm_mempool_init(struct btdm_mempool *mp, uint16_t blocks, uint32_t block_size, void *membuf, + const char *name) +{ + extern btdm_osal_error_t r_btdm_os_mempool_init(struct btdm_mempool * mp, uint16_t blocks, + uint32_t block_size, void *membuf, + const char *name); + return r_btdm_os_mempool_init(mp, blocks, block_size, membuf, name); +} + +#if 0 +/** + * Initializes an extended memory pool. Extended attributes (e.g., callbacks) + * are not specified when this function is called; they are assigned manually + * after initialization. + * + * @param mpe The extended memory pool to initialize. + * @param blocks The number of blocks in the pool. + * @param block_size The size of each block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return btdm_osal_error_t + */ +static inline btdm_osal_error_t +btdm_mempool_ext_init(struct btdm_mempool_ext *mpe, uint16_t blocks, uint32_t block_size, + void *membuf, const char *name) +{ + extern btdm_osal_error_t r_btdm_os_mempool_ext_init(struct btdm_mempool_ext * mpe, + uint16_t blocks, uint32_t block_size, + void *membuf, const char *name); + return r_btdm_os_mempool_ext_init(mpe, blocks, block_size, membuf, name); +} +#endif + +/** + * Clears a memory pool. + * + * @param mp The mempool to clear. + * + * @return btdm_osal_error_t + */ +static inline btdm_osal_error_t +btdm_mempool_clear(struct btdm_mempool *mp) +{ + extern btdm_osal_error_t r_btdm_os_mempool_clear(struct btdm_mempool * mp); + return r_btdm_os_mempool_clear(mp); +} + +/** + * Performs an integrity check of the specified mempool. This function + * attempts to detect memory corruption in the specified memory pool. + * + * @param mp The mempool to check. + * + * @return true if the memory pool passes the integrity + * check; + * false if the memory pool is corrupt. + */ +static inline bool +btdm_mempool_is_sane(const struct btdm_mempool *mp) +{ + extern bool r_btdm_os_mempool_is_sane(const struct btdm_mempool *mp); + return r_btdm_os_mempool_is_sane(mp); +} + +/** + * Checks if a memory block was allocated from the specified mempool. + * + * @param mp The mempool to check as parent. + * @param block_addr The memory block to check as child. + * + * @return 0 if the block does not belong to the mempool; + * 1 if the block does belong to the mempool. + */ +static inline int +btdm_memblock_from(const struct btdm_mempool *mp, const void *block_addr) +{ + extern int r_btdm_os_memblock_from(const struct btdm_mempool *mp, const void *block_addr); + return r_btdm_os_memblock_from(mp, block_addr); +} + +/** + * Get a memory block from a memory pool + * + * @param mp Pointer to the memory pool + * + * @return void* Pointer to block if available; NULL otherwise + */ +static inline void * +btdm_memblock_get(struct btdm_mempool *mp) +{ + extern void *r_btdm_os_memblock_get(struct btdm_mempool * mp); + return r_btdm_os_memblock_get(mp); +} + +/** + * Puts the memory block back into the pool, ignoring the put callback, if any. + * This function should only be called from a put callback to free a block + * without causing infinite recursion. + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return btdm_osal_error_t + */ +static inline btdm_osal_error_t +btdm_mempool_put_from_cb(struct btdm_mempool *mp, void *block_addr) +{ + extern btdm_osal_error_t r_btdm_os_memblock_put_from_cb(struct btdm_mempool * mp, + void *block_addr); + return r_btdm_os_memblock_put_from_cb(mp, block_addr); +} + +/** + * Puts the memory block back into the pool + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return btdm_osal_error_t + */ +static inline btdm_osal_error_t +btdm_memblock_put(struct btdm_mempool *mp, void *block_addr) +{ + extern btdm_osal_error_t r_btdm_os_memblock_put(struct btdm_mempool * mp, void *block_addr); + return r_btdm_os_memblock_put(mp, block_addr); +} + +static inline uint16_t +btdm_memblock_free_num_get(struct btdm_mempool *mp) +{ + extern uint16_t r_btdm_os_memblock_num_free(struct btdm_mempool * mp); + return r_btdm_os_memblock_num_free(mp); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BTDM_MEMPOOL_H_ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_osal.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_osal.h new file mode 100644 index 0000000000..d12809e90c --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_osal.h @@ -0,0 +1,221 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BTDM_OSAL_H_ +#define _BTDM_OSAL_H_ + +#include "sdkconfig.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum btdm_osal_error { + BTDM_OSAL_OK = 0, + BTDM_OSAL_ENOMEM = 1, + BTDM_OSAL_EINVAL = 2, + BTDM_OSAL_INVALID_PARM = 3, + BTDM_OSAL_MEM_NOT_ALIGNED = 4, + BTDM_OSAL_BAD_MUTEX = 5, + BTDM_OSAL_TIMEOUT = 6, + BTDM_OSAL_ERR_IN_ISR = 7, /* Function cannot be called from ISR */ + BTDM_OSAL_ERR_PRIV = 8, /* Privileged access error */ + BTDM_OSAL_NOT_STARTED = 9, /* OS must be started to call this function, but isn't */ + BTDM_OSAL_ENOENT = 10, /* No such thing */ + BTDM_OSAL_EBUSY = 11, /* Resource busy */ + BTDM_OSAL_ERROR = 12, /* Generic Error */ +}; + +enum btdm_osal_malloc_flag { + BTDM_OSAL_MALLOC_F_INTERNAL = 0, + BTDM_OSAL_MALLOC_F_NORMAL, +}; +typedef enum btdm_osal_malloc_flag btdm_osal_malloc_flag_t; + +typedef struct { + uint16_t evt_count; + uint16_t evtq_count; + uint16_t co_count; + uint16_t sem_count; + uint16_t mutex_count; +} btdm_osal_elem_num_t; + +struct btdm_osal_event { + void *event; +}; + +struct btdm_osal_eventq { + void *eventq; +}; + +struct btdm_osal_callout { + void *co; +}; + +struct btdm_osal_mutex { + void *mutex; +}; + +struct btdm_osal_sem { + void *sem; +}; + +/* + * Type definitions for BTDM OSAL + */ +typedef uint32_t btdm_osal_time_t; +typedef int btdm_osal_error_t; +typedef void btdm_osal_event_fn(struct btdm_osal_event *ev); +typedef void btdm_osal_task_fn(void *arg); +typedef void btdm_osal_intr_fn(void *arg); +typedef void *btdm_osal_task_handle_t; +typedef void *btdm_osal_intr_handle_t; + +/* + * Function declarations for BTDM OSAL + */ +void wr_btdm_osal_eventq_init(struct btdm_osal_eventq *evq); +void wr_btdm_osal_eventq_deinit(struct btdm_osal_eventq *evq); +struct btdm_osal_event *wr_btdm_osal_eventq_get(struct btdm_osal_eventq *evq, btdm_osal_time_t tmo); +void wr_btdm_osal_eventq_put(struct btdm_osal_eventq *evq, struct btdm_osal_event *ev); +void wr_btdm_osal_eventq_put_to_front(struct btdm_osal_eventq *evq, struct btdm_osal_event *ev); +void wr_btdm_osal_eventq_remove(struct btdm_osal_eventq *evq, struct btdm_osal_event *ev); +bool wr_btdm_osal_eventq_is_empty(struct btdm_osal_eventq *evq); + +void wr_btdm_osal_event_run(struct btdm_osal_event *ev); +void wr_btdm_osal_event_init(struct btdm_osal_event *ev, btdm_osal_event_fn *fn, void *arg); +void wr_btdm_osal_event_deinit(struct btdm_osal_event *ev); +void wr_btdm_osal_event_reset(struct btdm_osal_event *ev); +bool wr_btdm_osal_event_is_queued(struct btdm_osal_event *ev); +void *wr_btdm_osal_event_get_arg(struct btdm_osal_event *ev); +void wr_btdm_osal_event_set_arg(struct btdm_osal_event *ev, void *arg); + +btdm_osal_error_t wr_btdm_osal_mutex_init(struct btdm_osal_mutex *mu); +btdm_osal_error_t wr_btdm_osal_mutex_deinit(struct btdm_osal_mutex *mu); +btdm_osal_error_t wr_btdm_osal_mutex_pend(struct btdm_osal_mutex *mu, btdm_osal_time_t timeout); +btdm_osal_error_t wr_btdm_osal_mutex_release(struct btdm_osal_mutex *mu); + +btdm_osal_error_t wr_btdm_osal_sem_init(struct btdm_osal_sem *sem, uint16_t tokens); +btdm_osal_error_t wr_btdm_osal_sem_deinit(struct btdm_osal_sem *sem); +btdm_osal_error_t wr_btdm_osal_sem_pend(struct btdm_osal_sem *sem, btdm_osal_time_t timeout); +btdm_osal_error_t wr_btdm_osal_sem_release(struct btdm_osal_sem *sem); +uint16_t wr_btdm_osal_sem_get_count(struct btdm_osal_sem *sem); + +int wr_btdm_osal_callout_init(struct btdm_osal_callout *co, struct btdm_osal_eventq *evq, + btdm_osal_event_fn *ev_cb, void *ev_arg); +void wr_btdm_osal_callout_deinit(struct btdm_osal_callout *co); +btdm_osal_error_t wr_btdm_osal_callout_reset(struct btdm_osal_callout *co, btdm_osal_time_t ticks); +void wr_btdm_osal_callout_mem_reset(struct btdm_osal_callout *co); +void wr_btdm_osal_callout_stop(struct btdm_osal_callout *co); +bool wr_btdm_osal_callout_is_active(struct btdm_osal_callout *co); +btdm_osal_time_t wr_btdm_osal_callout_get_ticks(struct btdm_osal_callout *co); +btdm_osal_time_t wr_btdm_osal_callout_remaining_ticks(struct btdm_osal_callout *co, + btdm_osal_time_t time); +void wr_btdm_osal_callout_set_arg(struct btdm_osal_callout *co, void *arg); + +btdm_osal_time_t wr_btdm_osal_time_get(void); +btdm_osal_error_t wr_btdm_osal_time_ms_to_ticks(uint32_t ms, btdm_osal_time_t *out_ticks); +btdm_osal_error_t wr_btdm_osal_time_ticks_to_ms(btdm_osal_time_t ticks, uint32_t *out_ms); +btdm_osal_time_t wr_btdm_osal_time_ms_to_ticks32(uint32_t ms); +uint32_t wr_btdm_osal_time_ticks_to_ms32(btdm_osal_time_t ticks); + +uint32_t wr_btdm_osal_hw_enter_critical(void); +void wr_btdm_osal_hw_exit_critical(uint32_t ctx); +uint8_t wr_btdm_osal_hw_is_in_critical(void); + +uint32_t wr_btdm_osal_get_time_forever(void); + +int wr_btdm_osal_task_create(btdm_osal_task_fn *fn, const char *name, uint32_t stack_size, + void *arg, uint32_t priority, btdm_osal_task_handle_t *task_handle, + uint32_t core_id); +void wr_btdm_osal_task_delete(btdm_osal_task_handle_t task_handle); + +int wr_btdm_osal_intr_alloc(int src, int flags, btdm_osal_intr_fn *fn, void *arg, + btdm_osal_intr_handle_t *intr_handle); +int wr_btdm_osal_intr_free(btdm_osal_intr_handle_t intr_handle); + +void *wr_btdm_osal_malloc(uint32_t size, btdm_osal_malloc_flag_t flags); +void wr_btdm_osal_free(void *ptr); + +#if !CONFIG_BTDM_CTRL_MULTI_LINK_ENABLED +void *wr_btdm_osal_mmgmt_block_malloc(uint32_t size); +void wr_btdm_osal_mmgmt_block_free(void *ptr); +void wr_btdm_osal_mmgmt_block_copy(void *dst, const void *src, uint16_t size); +#endif /* !CONFIG_BTDM_CTRL_MULTI_LINK_ENABLED */ + +// void * wr_btdm_osal_ets_delay_us(uint32_t us); +int wr_btdm_osal_read_efuse_mac(uint8_t *mac); +void wr_btdm_osal_srand(uint32_t seed); +int wr_btdm_osal_rand(void); + +int btdm_osal_elem_mempool_init(btdm_osal_elem_num_t *elem_num); + +void btdm_osal_elem_mempool_deinit(void); + + +#define BTDM_OSAL_WR_FUNC(f) wr_ ## f + +#define btdm_osal_eventq_init BTDM_OSAL_WR_FUNC(btdm_osal_eventq_init) +#define btdm_osal_eventq_deinit BTDM_OSAL_WR_FUNC(btdm_osal_eventq_deinit) +#define btdm_osal_eventq_get BTDM_OSAL_WR_FUNC(btdm_osal_eventq_get) +#define btdm_osal_eventq_put BTDM_OSAL_WR_FUNC(btdm_osal_eventq_put) +#define btdm_osal_eventq_put_to_front BTDM_OSAL_WR_FUNC(btdm_osal_eventq_put_to_front) +#define btdm_osal_eventq_remove BTDM_OSAL_WR_FUNC(btdm_osal_eventq_remove) +#define btdm_osal_eventq_is_empty BTDM_OSAL_WR_FUNC(btdm_osal_eventq_is_empty) +#define btdm_osal_event_run BTDM_OSAL_WR_FUNC(btdm_osal_event_run) +#define btdm_osal_event_init BTDM_OSAL_WR_FUNC(btdm_osal_event_init) +#define btdm_osal_event_deinit BTDM_OSAL_WR_FUNC(btdm_osal_event_deinit) +#define btdm_osal_event_reset BTDM_OSAL_WR_FUNC(btdm_osal_event_reset) +#define btdm_osal_event_is_queued BTDM_OSAL_WR_FUNC(btdm_osal_event_is_queued) +#define btdm_osal_event_get_arg BTDM_OSAL_WR_FUNC(btdm_osal_event_get_arg) +#define btdm_osal_event_set_arg BTDM_OSAL_WR_FUNC(btdm_osal_event_set_arg) +#define btdm_osal_mutex_init BTDM_OSAL_WR_FUNC(btdm_osal_mutex_init) +#define btdm_osal_mutex_deinit BTDM_OSAL_WR_FUNC(btdm_osal_mutex_deinit) +#define btdm_osal_mutex_pend BTDM_OSAL_WR_FUNC(btdm_osal_mutex_pend) +#define btdm_osal_mutex_release BTDM_OSAL_WR_FUNC(btdm_osal_mutex_release) +#define btdm_osal_sem_init BTDM_OSAL_WR_FUNC(btdm_osal_sem_init) +#define btdm_osal_sem_deinit BTDM_OSAL_WR_FUNC(btdm_osal_sem_deinit) +#define btdm_osal_sem_pend BTDM_OSAL_WR_FUNC(btdm_osal_sem_pend) +#define btdm_osal_sem_release BTDM_OSAL_WR_FUNC(btdm_osal_sem_release) +#define btdm_osal_sem_get_count BTDM_OSAL_WR_FUNC(btdm_osal_sem_get_count) +#define btdm_osal_callout_init BTDM_OSAL_WR_FUNC(btdm_osal_callout_init) +#define btdm_osal_callout_deinit BTDM_OSAL_WR_FUNC(btdm_osal_callout_deinit) +#define btdm_osal_callout_reset BTDM_OSAL_WR_FUNC(btdm_osal_callout_reset) +#define btdm_osal_callout_mem_reset BTDM_OSAL_WR_FUNC(btdm_osal_callout_mem_reset) +#define btdm_osal_callout_stop BTDM_OSAL_WR_FUNC(btdm_osal_callout_stop) +#define btdm_osal_callout_is_active BTDM_OSAL_WR_FUNC(btdm_osal_callout_is_active) +#define btdm_osal_callout_get_ticks BTDM_OSAL_WR_FUNC(btdm_osal_callout_get_ticks) +#define btdm_osal_callout_remaining_ticks BTDM_OSAL_WR_FUNC(btdm_osal_callout_remaining_ticks) +#define btdm_osal_callout_set_arg BTDM_OSAL_WR_FUNC(btdm_osal_callout_set_arg) +#define btdm_osal_time_get BTDM_OSAL_WR_FUNC(btdm_osal_time_get) +#define btdm_osal_time_ms_to_ticks BTDM_OSAL_WR_FUNC(btdm_osal_time_ms_to_ticks) +#define btdm_osal_time_ticks_to_ms BTDM_OSAL_WR_FUNC(btdm_osal_time_ticks_to_ms) +#define btdm_osal_time_ms_to_ticks32 BTDM_OSAL_WR_FUNC(btdm_osal_time_ms_to_ticks32) +#define btdm_osal_time_ticks_to_ms32 BTDM_OSAL_WR_FUNC(btdm_osal_time_ticks_to_ms32) +#define btdm_osal_hw_enter_critical BTDM_OSAL_WR_FUNC(btdm_osal_hw_enter_critical) +#define btdm_osal_hw_exit_critical BTDM_OSAL_WR_FUNC(btdm_osal_hw_exit_critical) +#define btdm_osal_hw_is_in_critical BTDM_OSAL_WR_FUNC(btdm_osal_hw_is_in_critical) +#define btdm_osal_get_time_forever BTDM_OSAL_WR_FUNC(btdm_osal_get_time_forever) +#define btdm_osal_task_create BTDM_OSAL_WR_FUNC(btdm_osal_task_create) +#define btdm_osal_task_delete BTDM_OSAL_WR_FUNC(btdm_osal_task_delete) +#define btdm_osal_intr_alloc BTDM_OSAL_WR_FUNC(btdm_osal_intr_alloc) +#define btdm_osal_intr_free BTDM_OSAL_WR_FUNC(btdm_osal_intr_free) +#define btdm_osal_malloc BTDM_OSAL_WR_FUNC(btdm_osal_malloc) +#define btdm_osal_free BTDM_OSAL_WR_FUNC(btdm_osal_free) +#define btdm_osal_mmgmt_block_malloc BTDM_OSAL_WR_FUNC(btdm_osal_mmgmt_block_malloc) +#define btdm_osal_mmgmt_block_free BTDM_OSAL_WR_FUNC(btdm_osal_mmgmt_block_free) +#define btdm_osal_mmgmt_block_copy BTDM_OSAL_WR_FUNC(btdm_osal_mmgmt_block_copy) +#define btdm_osal_ets_delay_us BTDM_OSAL_WR_FUNC(btdm_osal_ets_delay_us) +#define btdm_osal_read_efuse_mac BTDM_OSAL_WR_FUNC(btdm_osal_read_efuse_mac) +#define btdm_osal_rand BTDM_OSAL_WR_FUNC(btdm_osal_rand) + +#ifdef __cplusplus +} +#endif + +#endif /* _BTDM_OSAL_H_ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_osal_freertos.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_osal_freertos.h new file mode 100644 index 0000000000..789f03a193 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_osal_freertos.h @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BTDM_OSAL_FREERTOS_H_ +#define _BTDM_OSAL_FREERTOS_H_ + +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "freertos/timers.h" +#include "sdkconfig.h" +#include +#include +#include + +#include "btdm_osal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if ((defined(CONFIG_BT_NIMBLE_USE_ESP_TIMER) && CONFIG_BT_NIMBLE_USE_ESP_TIMER) || \ + (defined(CONFIG_BT_LE_USE_ESP_TIMER) && CONFIG_BT_LE_USE_ESP_TIMER)) +/* Use esp timer instead of FreeRTOS timer to implement the callout. */ +#define BTDM_OSAL_USE_ESP_TIMER (1) +#else +#define BTDM_OSAL_USE_ESP_TIMER (0) +#endif + +struct btdm_osal_event_freertos { + bool queued; + void (*fn)(struct btdm_osal_event *ev); + void *arg; +}; + +struct btdm_osal_eventq_freertos { + QueueHandle_t q; +}; + +struct btdm_osal_callout_freertos { +#if BTDM_OSAL_USE_ESP_TIMER + esp_timer_handle_t handle; +#else + TimerHandle_t handle; +#endif + struct btdm_osal_eventq *evq; + struct btdm_osal_event ev; +}; + +struct btdm_osal_mutex_freertos { + SemaphoreHandle_t handle; +}; + +struct btdm_osal_sem_freertos { + SemaphoreHandle_t handle; +}; + +typedef void btdm_osal_event_fn_freertos(struct btdm_osal_event_freertos *ev); + +#ifdef __cplusplus +} +#endif + +#endif /* _BTDM_OSAL_FREERTOS_H_ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_user_cfg.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_user_cfg.h new file mode 100644 index 0000000000..4260350f4f --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_user_cfg.h @@ -0,0 +1,114 @@ +/* + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ESP_BTDM_CFG_H__ +#define __ESP_BTDM_CFG_H__ + +#include +#include +#include "sdkconfig.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_BT_CTRL_SLEEP_ENABLE +#define UC_BT_CTRL_SLEEP_ENABLE CONFIG_BT_CTRL_SLEEP_ENABLE +#else +#define UC_BT_CTRL_SLEEP_ENABLE (0) +#endif + +#define UC_BT_CTRL_TASK_STACK_SIZE CONFIG_BT_CTRL_TASK_STACK_SIZE + +#ifdef CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART +#define UC_HCI_UART_EN CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART +#else +#define UC_HCI_UART_EN 0 // hci ram mode +#endif + +#if UC_HCI_UART_EN + #define UC_BT_CTRL_HCI_UART_TX_PIN (CONFIG_BT_CTRL_HCI_UART_TX_PIN) + #define UC_BT_CTRL_HCI_UART_RX_PIN (CONFIG_BT_CTRL_HCI_UART_RX_PIN) + #define UC_BT_CTRL_HCI_UART_PORT (CONFIG_BT_CTRL_HCI_UART_PORT) + #define UC_BT_CTRL_HCI_UART_BAUD (CONFIG_BT_CTRL_HCI_UART_BAUD) + #define UC_BT_CTRL_HCI_UART_DATA_BITS (UART_DATA_8_BITS) + #define UC_BT_CTRL_HCI_UART_STOP_BITS (UART_STOP_BITS_1) + #define UC_BT_CTRL_HCI_UART_PARITY (0) + #define UC_BT_CTRL_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE) +#else + #define UC_BT_CTRL_HCI_UART_TX_PIN (0) + #define UC_BT_CTRL_HCI_UART_RX_PIN (0) + #define UC_BT_CTRL_HCI_UART_PORT (0) + #define UC_BT_CTRL_HCI_UART_BAUD (0) + #define UC_BT_CTRL_HCI_UART_DATA_BITS (0) + #define UC_BT_CTRL_HCI_UART_STOP_BITS (0) + #define UC_BT_CTRL_HCI_UART_PARITY (0) + #define UC_BT_CTRL_HCI_UART_TASK_STACK_SIZE (0) +#endif + +#if (CONFIG_BT_CTRL_HCI_UART_FLOWCTRL) + #define UC_BT_CTRL_HCI_UART_FLOW_CTRL (CONFIG_BT_CTRL_HCI_UART_FLOWCTRL) + #if UC_BT_CTRL_HCI_UART_FLOW_CTRL + #define UC_BT_CTRL_HCI_UART_CTS_PIN (CONFIG_BT_CTRL_HCI_UART_CTS_PIN) + #define UC_BT_CTRL_HCI_UART_RTS_PIN (CONFIG_BT_CTRL_HCI_UART_RTS_PIN) + #else + #define UC_BT_CTRL_HCI_UART_CTS_PIN (-1) + #define UC_BT_CTRL_HCI_UART_RTS_PIN (-1) + #endif +#else + #define UC_BT_CTRL_HCI_UART_FLOW_CTRL (0) + #define UC_BT_CTRL_HCI_UART_CTS_PIN (-1) + #define UC_BT_CTRL_HCI_UART_RTS_PIN (-1) +#endif + +#if (CONFIG_BT_CTRL_HCI_INTERFACE_USE_RAM) + #define UC_BT_CTRL_HCI_INTERFACE_USE_RAM (1) +#else + #define UC_BT_CTRL_HCI_INTERFACE_USE_RAM (0) +#endif + +#if (CONFIG_BT_CTRL_HCI_INTERFACE_USE_UART) + #define UC_BT_CTRL_HCI_INTERFACE_USE_UART (1) +#else + #define UC_BT_CTRL_HCI_INTERFACE_USE_UART (0) +#endif + +#if (UC_BT_CTRL_HCI_INTERFACE_USE_UART) + #if (CONFIG_BT_CTRL_UART_HCI_DMA_MODE) + #define UC_BT_CTRL_UART_HCI_DMA_MODE (1) + #define UC_BT_CTRL_UART_HCI_NO_DMA_MODE (0) + #else + #define UC_BT_CTRL_UART_HCI_DMA_MODE (0) + #define UC_BT_CTRL_UART_HCI_NO_DMA_MODE (1) + #endif +#endif + +#if (!UC_BT_CTRL_HCI_INTERFACE_USE_RAM) + #define UC_BT_CTRL_HCI_TRANS_TASK_STACK_SIZE (CONFIG_BT_CTRL_HCI_TRANS_TASK_STACK_SIZE) +#endif + +#if (UC_BT_CTRL_UART_HCI_NO_DMA_MODE) + #define UC_BT_CTRL_HCI_UART_RX_BUFFER_SIZE (CONFIG_BT_CTRL_HCI_UART_RX_BUFFER_SIZE) + #define UC_BT_CTRL_HCI_UART_TX_BUFFER_SIZE (CONFIG_BT_CTRL_HCI_UART_TX_BUFFER_SIZE) +#endif + +#if (UC_BT_CTRL_UART_HCI_DMA_MODE) + #define UC_BT_CTRL_HCI_TRANS_RX_MEM_NUM (CONFIG_BT_CTRL_HCI_TRANS_RX_MEM_NUM) + #define UC_BT_CTRL_HCI_LLDESCS_POOL_NUM (CONFIG_BT_CTRL_HCI_LLDESCS_POOL_NUM) +#endif + +#define UC_BT_CTRL_BR_EDR_IS_ENABLE (CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM) +#define UC_BT_CTRL_BLE_IS_ENABLE (CONFIG_BTDM_CTRL_MODE_BLE_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM) + +//TODO +#define UC_BT_CTRL_CONN_FC_ENABLE (1) + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_BTDM_CFG_H__ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/include/queue.h b/components/bt/porting_btdm/controller/btdm_common/include/queue.h new file mode 100644 index 0000000000..920574f441 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/include/queue.h @@ -0,0 +1,210 @@ +/* + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +/* The common BSD linked list queue macros are already defined here for ESP-IDF */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This file defines circular queues. The other types of data structures: + * singly-linked lists, singly-linked tail queues, lists and tail queues + * are used from sys/queue.h + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ CIRCLEQ + * _HEAD + + + + + + * _HEAD_INITIALIZER + + + + + + * _ENTRY + + + + + + * _INIT + + + + + + * _EMPTY + + + + + + * _FIRST + + + + + + * _NEXT + + + + + + * _PREV - - - + + + * _LAST - - + + + + * _FOREACH + + + + + + * _FOREACH_REVERSE - - - + + + * _INSERT_HEAD + + + + + + * _INSERT_BEFORE - + - + + + * _INSERT_AFTER + + + + + + * _INSERT_TAIL - - + + + + * _REMOVE_HEAD + - + - - + * _REMOVE + + + + + + * + */ + +/* + * Circular queue declarations. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { (void *)&(head), (void *)&(head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) + +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for ((var) = CIRCLEQ_FIRST((head)); \ + (var) != (void *)(head) || ((var) = NULL); \ + (var) = CIRCLEQ_NEXT((var), field)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for ((var) = CIRCLEQ_LAST((head)); \ + (var) != (void *)(head) || ((var) = NULL); \ + (var) = CIRCLEQ_PREV((var), field)) + +#define CIRCLEQ_INIT(head) do { \ + CIRCLEQ_FIRST((head)) = (void *)(head); \ + CIRCLEQ_LAST((head)) = (void *)(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \ + CIRCLEQ_PREV((elm), field) = (listelm); \ + if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \ + CIRCLEQ_LAST((head)) = (elm); \ + else \ + CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\ + CIRCLEQ_NEXT((listelm), field) = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + CIRCLEQ_NEXT((elm), field) = (listelm); \ + CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \ + if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \ + CIRCLEQ_FIRST((head)) = (elm); \ + else \ + CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\ + CIRCLEQ_PREV((listelm), field) = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \ + CIRCLEQ_PREV((elm), field) = (void *)(head); \ + if (CIRCLEQ_LAST((head)) == (void *)(head)) \ + CIRCLEQ_LAST((head)) = (elm); \ + else \ + CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \ + CIRCLEQ_FIRST((head)) = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + CIRCLEQ_NEXT((elm), field) = (void *)(head); \ + CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \ + if (CIRCLEQ_FIRST((head)) == (void *)(head)) \ + CIRCLEQ_FIRST((head)) = (elm); \ + else \ + CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \ + CIRCLEQ_LAST((head)) = (elm); \ +} while (0) + +#define CIRCLEQ_LAST(head) ((head)->cqh_last) + +#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) + +#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \ + CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \ + else \ + CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \ + CIRCLEQ_PREV((elm), field); \ + if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \ + CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \ + else \ + CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \ + CIRCLEQ_NEXT((elm), field); \ +} while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_coex.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_coex.c new file mode 100644 index 0000000000..7fbf139276 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_coex.c @@ -0,0 +1,234 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "sdkconfig.h" +#include "btdm_coex.h" + +#if CONFIG_SW_COEXIST_ENABLE +#include "private/esp_coexist_internal.h" +#endif + +extern esp_err_t coex_iso_start(void *coex_iso_info); +extern esp_err_t coex_iso_stop(uint16_t handle); +extern uint16_t coex_protect_frame_thres_get(void); +extern void coex_start_int_handle(uint16_t handle, uint32_t duration); +extern void coex_end_int_handle(uint16_t handle, uint32_t duration); +extern void coex_ble_idle_time_inform(uint32_t start_offset, uint32_t duration); +extern uint8_t coex_t_ifs_pti_selection_get(void); +extern void coex_ble_channel_map_set(uint8_t *channel_map); +extern esp_err_t coex_register_ble_cb(uint8_t type, void *func); +extern void bt_rf_coex_log_func_register(void *cb); + +/* + *************************************************************************************************** + * BTDM COEX Adapter Types + *************************************************************************************************** + */ +typedef void (*coex_schm_cb_t)(uint32_t __event); +typedef void (*coex_wifi_channel_change_btdm_cb_t)(uint8_t primary, uint8_t secondary); +typedef void (*coex_funcs_ble_cb_t)(void); + +/* + *************************************************************************************************** + * BTDM COEX Adapter Functions + *************************************************************************************************** + */ +void +wr_btdm_coex_schm_status_bit_set(uint32_t type, uint32_t status) +{ +#if CONFIG_SW_COEXIST_ENABLE + coex_schm_status_bit_set(type, status); +#endif // CONFIG_SW_COEXIST_ENABLE +} + +void +wr_btdm_coex_schm_status_bit_clear(uint32_t type, uint32_t status) +{ + +#if CONFIG_SW_COEXIST_ENABLE + coex_schm_status_bit_clear(type, status); +#endif // CONFIG_SW_COEXIST_ENABLE +} + +int +wr_btdm_coex_schm_register_btdm_callback(coex_schm_cb_t callback) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_schm_register_callback(COEX_SCHM_CALLBACK_TYPE_BT, callback); +#else + return 0; +#endif +} + +uint32_t +wr_btdm_coex_schm_interval_get(void) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_schm_interval_get(); +#else + return 0; +#endif +} + +uint8_t +wr_btdm_coex_schm_curr_period_get(void) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_schm_curr_period_get(); +#else + return 1; +#endif +} + +void * +wr_btdm_coex_schm_curr_phase_get(void) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_schm_curr_phase_get(); +#else + return NULL; +#endif +} + +int +wr_btdm_coex_register_wifi_channel_change_callback(coex_wifi_channel_change_btdm_cb_t callback) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_register_wifi_channel_change_callback(callback); +#else + return -1; +#endif +} + +int +wr_btdm_coex_wifi_channel_get(uint8_t *primary, uint8_t *secondary) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_wifi_channel_get(primary, secondary); +#else + return -1; +#endif +} + +int +wr_btdm_coex_version_get(unsigned *major, unsigned *minor, unsigned *path) +{ +#if CONFIG_SW_COEXIST_ENABLE + // TODO: enable it after update submodule coexist +#if 0 + coex_version_t version; + ESP_ERROR_CHECK(coex_version_get_value(&version)); + *major = (unsigned int)version.major; + *minor = (unsigned int)version.minor; + *patch = (unsigned int)version.patch; +#endif + return 0; +#endif + return -1; +} + +int +wr_btdm_coex_iso_start(void *coex_iso_info) +{ +#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT + return coex_iso_start(coex_iso_info); +#else + return ESP_OK; +#endif /* CONFIG_SW_COEXIST_ENABLE */ +} + +int +wr_btdm_coex_iso_stop(uint16_t handle) +{ +#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT + return coex_iso_stop(handle); +#else + return ESP_OK; +#endif /* CONFIG_SW_COEXIST_ENABLE */ +} + +uint16_t +wr_btdm_coex_iso_protect_frame_thres_get(void) +{ +#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT + return coex_protect_frame_thres_get(); +#else + return 0; +#endif /* CONFIG_SW_COEXIST_ENABLE */ +} + +void +wr_btdm_coex_iso_start_int_handle(uint16_t handle, uint32_t duration) +{ +#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT + coex_start_int_handle(handle, duration); +#endif /* CONFIG_SW_COEXIST_ENABLE */ +} + +void +wr_btdm_coex_iso_end_int_handle(uint16_t handle, uint32_t duration) +{ +#if CONFIG_SW_COEXIST_ENABLE && CONFIG_BT_LE_ISO_SUPPORT + coex_end_int_handle(handle, duration); +#endif /* CONFIG_SW_COEXIST_ENABLE */ +} + +void +wr_btdm_coex_ble_idle_time_inform(uint32_t start_offset, uint32_t duration) +{ +#if CONFIG_SW_COEXIST_ENABLE + coex_ble_idle_time_inform(start_offset, duration); +#endif /* CONFIG_SW_COEXIST_ENABLE */ +} + +int +wr_btdm_coex_register_ble_cb(uint32_t type, coex_funcs_ble_cb_t func) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_register_ble_cb(type, func); +#else + return ESP_OK; +#endif /* CONFIG_SW_COEXIST_ENABLE */ +} + +/* + *************************************************************************************************** + * BTDM COEX Initialization + *************************************************************************************************** + */ +esp_err_t +btdm_coex_init(void) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_init(); +#else + return ESP_OK; +#endif +} + +void +btdm_coex_deinit(void) +{ + +} + +esp_err_t +btdm_coex_enable(void) +{ +#if CONFIG_SW_COEXIST_ENABLE + return coex_enable(); +#else + return ESP_OK; +#endif +} + +void +btdm_coex_disable(void) +{ +#if CONFIG_SW_COEXIST_ENABLE + coex_disable(); +#endif +} diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_external.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_external.c new file mode 100644 index 0000000000..2038f9de1d --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_external.c @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "btdm_external.h" + +extern const int8_t *bt_bb_get_tx_pwr_table(uint8_t *length); + +const int8_t * +wr_btdm_external_bb_get_tx_pwr_table(uint8_t *length) +{ + assert(length != NULL); + return bt_bb_get_tx_pwr_table(length); +} + +/* + *************************************************************************************************** + * BTDM External Function Initialization + *************************************************************************************************** + */ +int +btdm_external_init(void) +{ + return 0; +} + +void +btdm_external_deinit(void) +{ + +} diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_log.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_log.c new file mode 100644 index 0000000000..60766c4c4b --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_log.c @@ -0,0 +1,129 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "sdkconfig.h" +#include "assert.h" +#include "esp_attr.h" +#include "esp_rom_sys.h" + +/* + *************************************************************************************************** + * External Functions + *************************************************************************************************** + */ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +void r_btdm_sched_list_details_dump(void); +void r_ble_phy_hw_state_dump(uint8_t); +void esp_ble_controller_log_dump_all(bool); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + +/* + *************************************************************************************************** + * Public Function Definitions + *************************************************************************************************** + */ +void IRAM_ATTR +wr_btdm_log_set_flags(uint8_t p0) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_set_buf_index_flag(uint32_t p0); + r_ble_log_set_buf_index_flag(p0); +#endif // BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_log_reset_flags(uint8_t p0) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_reset_buf_index_flag(uint32_t p0); + r_ble_log_reset_buf_index_flag(p0); +#endif // BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_log_internal_x0(uint32_t p0) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_internal_x0(uint32_t p0); + r_ble_log_internal_x0(p0); +#endif // BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_log_internal_x1(uint32_t p0, uint32_t p1) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_internal_x1(uint32_t p0, uint32_t p1); + r_ble_log_internal_x1(p0, p1); +#endif // BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_log_internal_x2(uint32_t p0, uint32_t p1, uint32_t p2) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_internal_x2(uint32_t p0, uint32_t p1, uint32_t p2); + r_ble_log_internal_x2(p0, p1, p2); +#endif // BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_log_internal_x3(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_internal_x3(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3); + r_ble_log_internal_x3(p0, p1, p2, p3); +#endif // BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_log_internal_hex(uint32_t p0, uint32_t p1, uint32_t p2) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_internal_hex(uint32_t p0, uint32_t p1, uint32_t p2); + r_ble_log_internal_hex(p0, p1, p2); +#endif // BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_log_raw_export(uint16_t p0, uint32_t p1, uint32_t p2) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + extern void r_ble_log_raw_export(uint16_t p0, uint32_t p1, uint32_t p2); + r_ble_log_raw_export(p0, p1, p2); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +} + +void IRAM_ATTR +wr_btdm_assert(const char *file, int line, int p0, int p1, uint8_t type) +{ +#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + r_ble_phy_hw_state_dump(false); + r_btdm_sched_list_details_dump(); + esp_ble_controller_log_dump_all(true); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED + + esp_rom_printf("assert %s,%d, param:0x%x,0x%x\n", file, line, p0, p1); + assert(0); +} + +/* + *************************************************************************************************** + * BTDM LOG Initialization + *************************************************************************************************** + */ +int +btdm_log_init(void) +{ + return 0; +} + +void +btdm_log_deinit(void) +{ + +} diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c new file mode 100644 index 0000000000..60c86ef6d7 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c @@ -0,0 +1,358 @@ + +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_err.h" +#include "esp_log.h" +#include "sdkconfig.h" + +#include "esp_bt.h" + +/* From Modem and Phy */ +#include "esp_phy_init.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/esp_clk_tree_common.h" + +#ifdef CONFIG_PM_ENABLE +#include "esp_pm.h" +#endif + +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#include "esp_private/pm_impl.h" +#include "esp_private/sleep_modem.h" +#include "esp_private/sleep_retention.h" +#endif + +/* + *************************************************************************************************** + * Local Defined Macros + *************************************************************************************************** + */ +#define BTDM_LOG_TAG "BTDM_SLEEP" + +#define BTDM_RTC_DELAY_US_LIGHT_SLEEP (2000) +#define BTDM_RTC_DELAY_US_MODEM_SLEEP (1500) + +/* + *************************************************************************************************** + * External Functions + *************************************************************************************************** + */ +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +extern bool r_btdm_sleep_should_skip_light_sleep_check(void); +extern const sleep_retention_entries_config_t *r_btdm_mac_retention_link_get(uint8_t *size); +extern void r_btdm_sleep_wake_up_overhead_set(uint32_t overhead); +#if UC_BT_CTRL_BR_EDR_IS_ENABLE +extern esp_err_t sleep_modem_bredr_mac_modem_state_init(void); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE +#if UC_BT_CTRL_BLE_IS_ENABLE +extern esp_err_t sleep_modem_ble_mac_modem_state_init(void); +#endif // UC_BT_CTRL_BLE_IS_ENABLEs +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + +extern void r_btdm_sleep_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, void *w_arg, + uint32_t us_to_enabled); + +/* + *************************************************************************************************** + * Local Variables + *************************************************************************************************** + */ +static bool s_bt_active = false; +static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; + +#ifdef CONFIG_PM_ENABLE +static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; +#endif // CONFIG_PM_ENABLE +// static modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; +static uint32_t s_bt_lpclk_freq = 100000; + +/* + *************************************************************************************************** + * Static Function Definitions + *************************************************************************************************** + */ +static void +btdm_lp_rtc_slow_clk_select(uint8_t slow_clk_src) +{ + /* Select slow clock source for BT momdule */ + switch (slow_clk_src) { + case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: + ESP_LOGI(BTDM_LOG_TAG, "Using main XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (CONFIG_XTAL_FREQ * 1000000 / s_bt_lpclk_freq - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: + ESP_LOGW(BTDM_LOG_TAG, "Using 136 kHz RC as clock source, use with caution as it may not maintain ACL or Sync process due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_XTAL32K: + ESP_LOGI(BTDM_LOG_TAG, "Using external 32.768 kHz XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_RC32K: + ESP_LOGI(BTDM_LOG_TAG, "Using 32 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_EXT32K: + ESP_LOGI(BTDM_LOG_TAG, "Using 32 kHz oscillator as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); + break; + default: + } +} + +static void +btdm_lp_timer_clk_init(esp_btdm_controller_config_t *cfg) +{ + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_INVALID) { +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; +#else +#if CONFIG_RTC_CLK_SRC_INT_RC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC_SLOW; +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS + uint32_t clk_freq = 0; + + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + if (!esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_XTAL32K, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &clk_freq)) { + if (clk_freq > 32700 && clk_freq < 33800) { + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_XTAL32K; + } else { + ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL detection error, switch to main XTAL as Bluetooth sleep clock"); + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; + } + } else { + ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL detection error, switch to main XTAL as Bluetooth sleep clock"); + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; + } + } else { + ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; + } +#elif CONFIG_RTC_CLK_SRC_INT_RC32K + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC32K; +#elif CONFIG_RTC_CLK_SRC_EXT_OSC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_EXT32K; +#else + ESP_LOGE(BTDM_LOG_TAG, "Unsupported clock source"); + assert(0); +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + } + + // if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + // cfg->rtc_freq = s_bt_lpclk_freq; + // } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) { + // cfg->rtc_freq = 32768; + // } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + // cfg->rtc_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + // //TODO + // // cfg->ble_ll_sca = 3000; + // } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC32K) { + // cfg->rtc_freq = 32000; + // } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_EXT32K) { + // cfg->rtc_freq = 32000; + // } + btdm_lp_rtc_slow_clk_select(s_bt_lpclk_src); +} + +static void +btdm_lp_timer_clk_deinit(void) +{ + modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); +} + +void +btdm_lp_sleep_cb(uint32_t enable_tick, void *arg) +{ + if (!s_bt_active) { + return; + } + esp_phy_disable(PHY_MODEM_BT); +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_release(s_pm_lock); +#endif // CONFIG_PM_ENABLE + s_bt_active = false; +} + +void +btdm_lp_wake_up_cb(void *arg) +{ + if (s_bt_active) { + return; + } +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_acquire(s_pm_lock); +#endif // CONFIG_PM_ENABLE + esp_phy_enable(PHY_MODEM_BT); + s_bt_active = true; +} + +#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE +static esp_err_t +btdm_lp_modem_retention_create(void) +{ + uint8_t size = 0; + const sleep_retention_entries_config_t *btdm_mac_modem_config = + r_btdm_mac_retention_link_get(&size); + esp_err_t err = sleep_retention_entries_create(btdm_mac_modem_config, size, REGDMA_LINK_PRI_5, + SLEEP_RETENTION_MODULE_BLE_MAC); + if (err == ESP_OK) { + ESP_LOGI(BTDM_LOG_TAG, "Modem BTDM MAC retention initialization"); + } + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + sleep_modem_bredr_mac_modem_state_init(); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + +#if UC_BT_CTRL_BLE_IS_ENABLE + sleep_modem_ble_mac_modem_state_init(); +#endif // UC_BT_CTRL_BLE_IS_ENABLE + return err; +} + +static esp_err_t +btdm_lp_modem_state_init(void) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = {.create = {.handle = (void *)btdm_lp_modem_retention_create, .arg = NULL}}, + .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB)}; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); + if (err == ESP_OK) { + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + } + return err; +} + +static void +btdm_lp_modem_state_deinit(void) +{ + esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err == ESP_OK) { + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + assert(err == ESP_OK); + } +} +#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE + +/* + *************************************************************************************************** + * Public Function Definitions + *************************************************************************************************** + */ +#include "modem/modem_syscon_reg.h" +void +btdm_lp_enable_clock(esp_btdm_controller_config_t *cfg) +{ + modem_clock_module_enable(PERIPH_BT_MODULE); + modem_clock_module_mac_reset(PERIPH_BT_MODULE); + // TODO: set the clock ion modem_clock_module_enable + REG_WRITE(MODEM_SYSCON_CLK_CONF_POWER_ST_REG, 0XFFFFFFFF); + // btdm_lp_timer_clk_init(cfg); +} + +void +btdm_lp_disable_clock(void) +{ + btdm_lp_timer_clk_deinit(); + modem_clock_module_disable(PERIPH_BT_MODULE); +} + +int +btdm_lp_init(void) +{ +#if UC_BT_CTRL_SLEEP_ENABLE + ESP_LOGI(BTDM_LOG_TAG, "Bluetooth modem sleep is enabled"); +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + r_btdm_sleep_set_sleep_cb(btdm_lp_sleep_cb, btdm_lp_wake_up_cb, 0, 0, + BTDM_RTC_DELAY_US_LIGHT_SLEEP); +#else + r_btdm_sleep_set_sleep_cb(btdm_lp_sleep_cb, btdm_lp_wake_up_cb, 0, 0, + BTDM_RTC_DELAY_US_MODEM_SLEEP); +#endif /* FREERTOS_USE_TICKLESS_IDLE */ +#endif // UC_BT_CTRL_SLEEP_ENABLE + +#ifdef CONFIG_PM_ENABLE + esp_err_t rc = 0; + + rc = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "bt", &s_pm_lock); + if (rc != ESP_OK) { + return -1; + } +#if UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE + /* Create a new regdma link for BLE related register restoration */ + rc = btdm_lp_modem_state_init(); + assert(rc == 0); + esp_sleep_enable_bt_wakeup(); + ESP_LOGW(BTDM_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); + + rc = esp_pm_register_inform_out_light_sleep_overhead_callback(r_btdm_sleep_wake_up_overhead_set); + if (rc != ESP_OK) { + return -2; + } + // rc = esp_pm_register_skip_light_sleep_callback(r_btdm_sleep_should_skip_light_sleep_check); + if (rc != ESP_OK) { + return -3; + } +#endif /* UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_PM_ENABLE */ + + return 0; +} + +void +btdm_lp_deinit(void) +{ +#if UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE + // esp_pm_unregister_skip_light_sleep_callback(r_btdm_sleep_should_skip_light_sleep_check); + esp_pm_unregister_inform_out_light_sleep_overhead_callback(r_btdm_sleep_wake_up_overhead_set); + esp_sleep_disable_bt_wakeup(); + btdm_lp_modem_state_deinit(); +#endif /* UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + +#ifdef CONFIG_PM_ENABLE + /* lock should be released first */ + if (s_pm_lock) { + esp_pm_lock_delete(s_pm_lock); + s_pm_lock = NULL; + } +#endif // CONFIG_PM_ENABLE +} + +void +btdm_lp_reset(bool enable_stage) +{ + // TODO: For enable_stage, need to disable the phy by default. + if (enable_stage) { + assert(!s_bt_active); + +#if CONFIG_PM_ENABLE + esp_pm_lock_acquire(s_pm_lock); +#endif // CONFIG_PM_ENABLE + + esp_phy_enable(PHY_MODEM_BT); + esp_btbb_enable(); + s_bt_active = true; + } else { + if (s_bt_active) { + esp_btbb_disable(); + esp_phy_disable(PHY_MODEM_BT); +#if CONFIG_PM_ENABLE + esp_pm_lock_release(s_pm_lock); +#endif // CONFIG_PM_ENABLE + s_bt_active = false; + } + } +} + +void +btdm_lp_shutdown(void) +{ + modem_clock_module_mac_reset(PERIPH_BT_MODULE); + if (s_bt_active) { + // esp_phy_disable(PHY_MODEM_BT); + s_bt_active = false; + } +} diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_osal_freertos.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_osal_freertos.c new file mode 100644 index 0000000000..3f21fb5fd8 --- /dev/null +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_osal_freertos.c @@ -0,0 +1,1460 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "btdm_osal_freertos.h" +#include "btdm_mempool.h" + +#include "esp_mac.h" +#include "esp_heap_caps.h" +#include "esp_intr_alloc.h" +#include "esp_ipc.h" +#include "esp_random.h" +#include "esp_log.h" +#include "esp_rom_sys.h" + +extern int esp_rom_printf(const char *fmt, ...); +#define BTDM_OSAL_ASSERT(con) \ + do { \ + if (!(con)) { \ + esp_rom_printf("assertion:%s\n", #con); \ + esp_rom_printf("line:%d,function:%s\n", __LINE__, __func__); \ + assert(0); \ + } \ + } while (0) + +#define BTDM_MEMPOOL_ALLOC (1) + +#if (!defined(SOC_ESP_NIMBLE_CONTROLLER) || !SOC_ESP_NIMBLE_CONTROLLER) +#error "not defined SOC_ESP_NIMBLE_CONTROLLER or SOC_ESP_NIMBLE_CONTROLLER is zero" +#endif + +struct btdm_intr_alloc_params { + union { + struct { + int source; + int flags; + intr_handler_t handler; + void *arg; + intr_handle_t *ret_handle_in; + } cp; + int rsp; + }; +}; + +static const char *TAG = "TBTDM OSAL"; + +struct btdm_mempool s_btdm_osal_ev_pool; +static btdm_membuf_t *s_btdm_osal_ev_buf = NULL; + +struct btdm_mempool s_btdm_osal_evq_pool; +static btdm_membuf_t *s_btdm_osal_evq_buf = NULL; + +struct btdm_mempool s_btdm_osal_co_pool; +static btdm_membuf_t *s_btdm_osal_co_buf = NULL; + +struct btdm_mempool s_btdm_osal_sem_pool; +static btdm_membuf_t *s_btdm_osal_sem_buf = NULL; + +struct btdm_mempool s_btdm_osal_mutex_pool; +static btdm_membuf_t *s_btdm_osal_mutex_buf = NULL; + +static uint16_t s_btdm_osal_evtq_deepth = 0; +static uint8_t s_btdm_osal_intr_nest = 0; +static portMUX_TYPE s_btsm_osal_intr_mutex = portMUX_INITIALIZER_UNLOCKED; + +/* + *************************************************************************************************** + * Static Functions + *************************************************************************************************** + */ +static inline bool IRAM_ATTR +in_isr(void) +{ + /* XXX hw specific! */ + return xPortInIsrContext() != 0; +} + +/* + *************************************************************************************************** + * BTDM OSAL Event Queue + *************************************************************************************************** + */ +void +wr_btdm_osal_eventq_init(struct btdm_osal_eventq *evq) +{ + struct btdm_osal_eventq_freertos *eventq = NULL; + +#if BTDM_MEMPOOL_ALLOC + if (!btdm_memblock_from(&s_btdm_osal_evq_pool, evq->eventq)) { + evq->eventq = btdm_memblock_get(&s_btdm_osal_evq_pool); + eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + BTDM_OSAL_ASSERT(eventq); + memset(eventq, 0, sizeof(*eventq)); + eventq->q = xQueueCreate(s_btdm_osal_evtq_deepth, sizeof(struct btdm_osal_eventq *)); + BTDM_OSAL_ASSERT(eventq->q); + } else { + eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + xQueueReset(eventq->q); + } +#else + if (!evq->eventq) { + evq->eventq = btdm_osal_malloc(sizeof(struct btdm_osal_eventq_freertos), + BTDM_OSAL_MALLOC_F_INTERNAL); + eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + BTDM_OSAL_ASSERT(eventq); + memset(eventq, 0, sizeof(*eventq)); + eventq->q = xQueueCreate(s_btdm_osal_evtq_deepth, sizeof(struct btdm_osal_eventq *)); + BTDM_OSAL_ASSERT(eventq->q); + } else { + eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + xQueueReset(eventq->q); + } +#endif +} + +void +wr_btdm_osal_eventq_deinit(struct btdm_osal_eventq *evq) +{ + struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + + BTDM_OSAL_ASSERT(eventq); + vQueueDelete(eventq->q); +#if BTDM_MEMPOOL_ALLOC + btdm_memblock_put(&s_btdm_osal_evq_pool, eventq); +#else + btdm_osal_free((void *)eventq); +#endif + evq->eventq = NULL; +} + +struct btdm_osal_event *IRAM_ATTR +wr_btdm_osal_eventq_get(struct btdm_osal_eventq *evq, btdm_osal_time_t tmo) +{ + struct btdm_osal_event *ev = NULL; + struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + BaseType_t woken; + BaseType_t ret; + + if (in_isr()) { + BTDM_OSAL_ASSERT(tmo == 0); + ret = xQueueReceiveFromISR(eventq->q, &ev, &woken); + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + ret = xQueueReceive(eventq->q, &ev, tmo); + } + BTDM_OSAL_ASSERT(ret == pdPASS || ret == errQUEUE_EMPTY); + + if (ev) { + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + if (event) { + event->queued = false; + } + } + + return ev; +} + +void IRAM_ATTR +wr_btdm_osal_eventq_put(struct btdm_osal_eventq *evq, struct btdm_osal_event *ev) +{ + BaseType_t woken; + BaseType_t ret; + struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + + if (event->queued) { + return; + } + + event->queued = true; + + if (in_isr()) { + ret = xQueueSendToBackFromISR(eventq->q, &ev, &woken); + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + ret = xQueueSendToBack(eventq->q, &ev, portMAX_DELAY); + } + + BTDM_OSAL_ASSERT(ret == pdPASS); +} + +void IRAM_ATTR +wr_btdm_osal_eventq_put_to_front(struct btdm_osal_eventq *evq, struct btdm_osal_event *ev) +{ + BaseType_t woken; + BaseType_t ret; + struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + + if (event->queued) { + return; + } + + event->queued = true; + + if (in_isr()) { + ret = xQueueSendToFrontFromISR(eventq->q, &ev, &woken); + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + ret = xQueueSendToFront(eventq->q, &ev, portMAX_DELAY); + } + + BTDM_OSAL_ASSERT(ret == pdPASS); +} + +void IRAM_ATTR +wr_btdm_osal_eventq_remove(struct btdm_osal_eventq *evq, struct btdm_osal_event *ev) +{ + struct btdm_osal_event *tmp_ev; + BaseType_t ret; + int i; + int count; + BaseType_t woken, woken2; + struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + + if (!event->queued) { + return; + } + + /* + * XXX We cannot extract element from inside FreeRTOS queue so as a quick + * workaround we'll just remove all elements and add them back except the + * one we need to remove. This is silly, but works for now - we probably + * better use counting semaphore with os_queue to handle this in future. + */ + + if (in_isr()) { + woken = pdFALSE; + + count = uxQueueMessagesWaitingFromISR(eventq->q); + for (i = 0; i < count; i++) { + ret = xQueueReceiveFromISR(eventq->q, &tmp_ev, &woken2); + BTDM_OSAL_ASSERT(ret == pdPASS); + woken |= woken2; + + if (tmp_ev == ev) { + continue; + } + + ret = xQueueSendToBackFromISR(eventq->q, &tmp_ev, &woken2); + BTDM_OSAL_ASSERT(ret == pdPASS); + woken |= woken2; + } + + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + portMUX_TYPE btdm_osal_mut = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL(&btdm_osal_mut); + + count = uxQueueMessagesWaiting(eventq->q); + for (i = 0; i < count; i++) { + ret = xQueueReceive(eventq->q, &tmp_ev, 0); + BTDM_OSAL_ASSERT(ret == pdPASS); + + if (tmp_ev == ev) { + continue; + } + + ret = xQueueSendToBack(eventq->q, &tmp_ev, 0); + BTDM_OSAL_ASSERT(ret == pdPASS); + } + + portEXIT_CRITICAL(&btdm_osal_mut); + } + + event->queued = 0; +} + +bool IRAM_ATTR +wr_btdm_osal_eventq_is_empty(struct btdm_osal_eventq *evq) +{ + struct btdm_osal_eventq_freertos *eventq = (struct btdm_osal_eventq_freertos *)evq->eventq; + return xQueueIsQueueEmptyFromISR(eventq->q); +} + +/* + *************************************************************************************************** + * BTDM OSAL Event + *************************************************************************************************** + */ +void IRAM_ATTR +wr_btdm_osal_event_run(struct btdm_osal_event *ev) +{ + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + event->fn(ev); +} + +void IRAM_ATTR +wr_btdm_osal_event_init(struct btdm_osal_event *ev, btdm_osal_event_fn *fn, void *arg) +{ + struct btdm_osal_event_freertos *event = NULL; + +#if BTDM_MEMPOOL_ALLOC + if (!btdm_memblock_from(&s_btdm_osal_ev_pool, ev->event)) { + ev->event = btdm_memblock_get(&s_btdm_osal_ev_pool); + } +#else + if (!ev->event) { + ev->event = btdm_osal_malloc(sizeof(struct btdm_osal_event_freertos), + BTDM_OSAL_MALLOC_F_INTERNAL); + } +#endif + event = (struct btdm_osal_event_freertos *)ev->event; + BTDM_OSAL_ASSERT(event); + + memset(event, 0, sizeof(*event)); + event->fn = fn; + event->arg = arg; +} + +void IRAM_ATTR +wr_btdm_osal_event_deinit(struct btdm_osal_event *ev) +{ + if (!ev->event) { + return; + } + +#if BTDM_MEMPOOL_ALLOC + btdm_memblock_put(&s_btdm_osal_ev_pool, ev->event); +#else + btdm_osal_free(ev->event); +#endif + ev->event = NULL; +} + +void IRAM_ATTR +wr_btdm_osal_event_reset(struct btdm_osal_event *ev) +{ + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + BTDM_OSAL_ASSERT(event); + event->queued = 0; +} + +bool IRAM_ATTR +wr_btdm_osal_event_is_queued(struct btdm_osal_event *ev) +{ + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + return event->queued; +} + +void *IRAM_ATTR +wr_btdm_osal_event_get_arg(struct btdm_osal_event *ev) +{ + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + return event->arg; +} + +void IRAM_ATTR +wr_btdm_osal_event_set_arg(struct btdm_osal_event *ev, void *arg) +{ + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)ev->event; + event->arg = arg; +} + +/* + *************************************************************************************************** + * BTDM OSAL Mutex + *************************************************************************************************** + */ +btdm_osal_error_t +wr_btdm_osal_mutex_init(struct btdm_osal_mutex *mu) +{ + struct btdm_osal_mutex_freertos *mutex = NULL; +#if BTDM_MEMPOOL_ALLOC + if (!btdm_memblock_from(&s_btdm_osal_mutex_pool, mu->mutex)) { + mu->mutex = btdm_memblock_get(&s_btdm_osal_mutex_pool); + mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + memset(mutex, 0, sizeof(*mutex)); + mutex->handle = xSemaphoreCreateRecursiveMutex(); + BTDM_OSAL_ASSERT(mutex->handle); + } +#else + if (!mu->mutex) { + mu->mutex = btdm_osal_malloc(sizeof(struct btdm_osal_mutex_freertos), + BTDM_OSAL_MALLOC_F_INTERNAL); + mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + memset(mutex, 0, sizeof(*mutex)); + mutex->handle = xSemaphoreCreateRecursiveMutex(); + BTDM_OSAL_ASSERT(mutex->handle); + } +#endif + + return BTDM_OSAL_OK; +} + +btdm_osal_error_t +wr_btdm_osal_mutex_deinit(struct btdm_osal_mutex *mu) +{ + struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(mutex->handle); + vSemaphoreDelete(mutex->handle); + +#if BTDM_MEMPOOL_ALLOC + btdm_memblock_put(&s_btdm_osal_mutex_pool, mutex); +#else + btdm_osal_free((void *)mutex); +#endif + mu->mutex = NULL; + + return BTDM_OSAL_OK; +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_mutex_pend(struct btdm_osal_mutex *mu, btdm_osal_time_t timeout) +{ + BaseType_t ret; + struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(mutex->handle); + + if (in_isr()) { + ret = pdFAIL; + BTDM_OSAL_ASSERT(0); + } else { + ret = xSemaphoreTakeRecursive(mutex->handle, timeout); + } + + return ret == pdPASS ? BTDM_OSAL_OK : BTDM_OSAL_TIMEOUT; +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_mutex_release(struct btdm_osal_mutex *mu) +{ + struct btdm_osal_mutex_freertos *mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(mutex->handle); + + if (in_isr()) { + BTDM_OSAL_ASSERT(0); + } else { + if (xSemaphoreGiveRecursive(mutex->handle) != pdPASS) { + return BTDM_OSAL_BAD_MUTEX; + } + } + + return BTDM_OSAL_OK; +} + +/* + *************************************************************************************************** + * BTDM OSAL Sem + *************************************************************************************************** + */ +btdm_osal_error_t +wr_btdm_osal_sem_init(struct btdm_osal_sem *sem, uint16_t tokens) +{ + struct btdm_osal_sem_freertos *semaphore = NULL; + +#if BTDM_MEMPOOL_ALLOC + if (!btdm_memblock_from(&s_btdm_osal_sem_pool, sem->sem)) { + sem->sem = btdm_memblock_get(&s_btdm_osal_sem_pool); + semaphore = (struct btdm_osal_sem_freertos *)sem->sem; + + if (!semaphore) { + return BTDM_OSAL_INVALID_PARM; + } + + memset(semaphore, 0, sizeof(*semaphore)); + semaphore->handle = xSemaphoreCreateCounting(128, tokens); + BTDM_OSAL_ASSERT(semaphore->handle); + } +#else + if (!sem->sem) { + sem->sem = btdm_osal_malloc(sizeof(struct btdm_osal_sem_freertos), + BTDM_OSAL_MALLOC_F_INTERNAL); + semaphore = (struct btdm_osal_sem_freertos *)sem->sem; + + if (!semaphore) { + return BTDM_OSAL_INVALID_PARM; + } + + memset(semaphore, 0, sizeof(*semaphore)); + semaphore->handle = xSemaphoreCreateCounting(128, tokens); + BTDM_OSAL_ASSERT(semaphore->handle); + } +#endif + + return BTDM_OSAL_OK; +} + +btdm_osal_error_t +wr_btdm_osal_sem_deinit(struct btdm_osal_sem *sem) +{ + struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem; + + if (!semaphore) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(semaphore->handle); + vSemaphoreDelete(semaphore->handle); + +#if BTDM_MEMPOOL_ALLOC + btdm_memblock_put(&s_btdm_osal_sem_pool, semaphore); +#else + btdm_osal_free((void *)semaphore); +#endif + sem->sem = NULL; + + return BTDM_OSAL_OK; +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_sem_pend(struct btdm_osal_sem *sem, btdm_osal_time_t timeout) +{ + BaseType_t woken; + BaseType_t ret; + struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem; + + if (!semaphore) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(semaphore->handle); + + if (in_isr()) { + BTDM_OSAL_ASSERT(timeout == 0); + ret = xSemaphoreTakeFromISR(semaphore->handle, &woken); + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + ret = xSemaphoreTake(semaphore->handle, timeout); + } + + return ret == pdPASS ? BTDM_OSAL_OK : BTDM_OSAL_TIMEOUT; +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_sem_release(struct btdm_osal_sem *sem) +{ + BaseType_t ret; + BaseType_t woken; + struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem; + + if (!semaphore) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(semaphore->handle); + + if (in_isr()) { + ret = xSemaphoreGiveFromISR(semaphore->handle, &woken); + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + ret = xSemaphoreGive(semaphore->handle); + } + + BTDM_OSAL_ASSERT(ret == pdPASS); + return BTDM_OSAL_OK; +} + +uint16_t IRAM_ATTR +wr_btdm_osal_sem_get_count(struct btdm_osal_sem *sem) +{ + struct btdm_osal_sem_freertos *semaphore = (struct btdm_osal_sem_freertos *)sem->sem; + return uxSemaphoreGetCount(semaphore->handle); +} + +/* + *************************************************************************************************** + * BTDM OSAL Callout + *************************************************************************************************** + */ +#if BTDM_OSAL_USE_ESP_TIMER +static void IRAM_ATTR +btdm_osal_event_fn_wrapper(void *arg) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)arg; + BTDM_OSAL_ASSERT(callout); + + if (callout->evq) { + btdm_osal_eventq_put(callout->evq, &callout->ev); + } else { + struct btdm_osal_event_freertos *event = + (struct btdm_osal_event_freertos *)callout->ev.event; + event->fn(&callout->ev); + } +} + +static IRAM_ATTR btdm_osal_error_t +esp_err_to_npl_error(esp_err_t err) +{ + switch (err) { + case ESP_ERR_INVALID_ARG: + return BTDM_OSAL_INVALID_PARM; + + case ESP_ERR_INVALID_STATE: + return BTDM_OSAL_EINVAL; + + case ESP_OK: + return BTDM_OSAL_OK; + + default: + return BTDM_OSAL_ERROR; + } +} +#else +static void IRAM_ATTR +os_callout_timer_cb(TimerHandle_t timer) +{ + struct btdm_osal_callout_freertos *callout; + + callout = pvTimerGetTimerID(timer); + BTDM_OSAL_ASSERT(callout); + + if (callout->evq) { + btdm_osal_eventq_put(callout->evq, &callout->ev); + } else { + struct btdm_osal_event_freertos *event = + (struct btdm_osal_event_freertos *)callout->ev.event; + event->fn(&callout->ev); + } +} +#endif + +int +wr_btdm_osal_callout_init(struct btdm_osal_callout *co, struct btdm_osal_eventq *evq, + btdm_osal_event_fn *ev_cb, void *ev_arg) +{ + struct btdm_osal_callout_freertos *callout = NULL; + +#if BTDM_MEMPOOL_ALLOC + if (!btdm_memblock_from(&s_btdm_osal_co_pool, co->co)) { + co->co = btdm_memblock_get(&s_btdm_osal_co_pool); + callout = (struct btdm_osal_callout_freertos *)co->co; + BTDM_OSAL_ASSERT(callout); + + memset(callout, 0, sizeof(*callout)); + btdm_osal_event_init(&callout->ev, ev_cb, ev_arg); + +#if BTDM_OSAL_USE_ESP_TIMER + callout->evq = evq; + + esp_timer_create_args_t create_args = { + .callback = btdm_osal_event_fn_wrapper, + .arg = callout, + .name = "nimble_timer" + }; + + if (esp_timer_create(&create_args, &callout->handle) != ESP_OK) { + btdm_osal_event_deinit(&callout->ev); + btdm_memblock_put(&s_btdm_osal_co_pool, callout); + co->co = NULL; + return -1; + } +#else + callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); + + if (!callout->handle) { + btdm_osal_event_deinit(&callout->ev); + btdm_memblock_put(&s_btdm_osal_co_pool, callout); + co->co = NULL; + return -1; + } +#endif // BTDM_OSAL_USE_ESP_TIMER + } else { + callout = (struct btdm_osal_callout_freertos *)co->co; + BTDM_OSAL_ASSERT(callout); + callout->evq = evq; + btdm_osal_event_init(&callout->ev, ev_cb, ev_arg); + } +#else + + if (!co->co) { + co->co = btdm_osal_malloc(sizeof(struct btdm_osal_callout_freertos), + BTDM_OSAL_MALLOC_F_INTERNAL); + callout = (struct btdm_osal_callout_freertos *)co->co; + if (!callout) { + return -1; + } + + memset(callout, 0, sizeof(*callout)); + btdm_osal_event_init(&callout->ev, ev_cb, ev_arg); + +#if BTDM_OSAL_USE_ESP_TIMER + callout->evq = evq; + + esp_timer_create_args_t create_args = { + .callback = btdm_osal_event_fn_wrapper, .arg = callout, .name = "nimble_timer"}; + + if (esp_timer_create(&create_args, &callout->handle) != ESP_OK) { + btdm_osal_event_deinit(&callout->ev); + btdm_osal_free((void *)callout); + co->co = NULL; + return -1; + } +#else + callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); + + if (!callout->handle) { + btdm_osal_event_deinit(&callout->ev); + btdm_osal_free((void *)callout); + co->co = NULL; + return -1; + } +#endif // BTDM_OSAL_USE_ESP_TIMER + } else { + callout = (struct btdm_osal_callout_freertos *)co->co; + BTDM_OSAL_ASSERT(callout); + callout->evq = evq; + btdm_osal_event_init(&callout->ev, ev_cb, ev_arg); + } +#endif // BTDM_MEMPOOL_ALLOC + return 0; +} + +void +wr_btdm_osal_callout_deinit(struct btdm_osal_callout *co) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + + /* Since we dynamically deinit timers, function can be called for NULL timers. Return for such + * scenarios */ + if (!callout) { + return; + } + + if (!callout->handle) { + return; + } + + btdm_osal_event_deinit(&callout->ev); +#if BTDM_OSAL_USE_ESP_TIMER + esp_err_t err = esp_timer_stop(callout->handle); + + if (err != ESP_OK) { + /* ESP_ERR_INVALID_STATE is expected when timer is already stopped */ + if (err != ESP_ERR_INVALID_STATE) { + ESP_LOGD(TAG, "Timer not stopped"); + } + } + err = esp_timer_delete(callout->handle); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Timer not deleted"); + } +#else + xTimerDelete(callout->handle, portMAX_DELAY); +#endif // BTDM_OSAL_USE_ESP_TIMER +#if BTDM_MEMPOOL_ALLOC + btdm_memblock_put(&s_btdm_osal_co_pool, callout); +#else + btdm_osal_free((void *)callout); +#endif // BTDM_MEMPOOL_ALLOC + co->co = NULL; + memset(co, 0, sizeof(struct btdm_osal_callout)); +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_callout_reset(struct btdm_osal_callout *co, btdm_osal_time_t ticks) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; +#if BTDM_OSAL_USE_ESP_TIMER + esp_timer_stop(callout->handle); + + return esp_err_to_npl_error(esp_timer_start_once(callout->handle, ticks * 1000)); +#else + + BaseType_t woken1, woken2, woken3; + + if (ticks == 0) { + ticks = 1; + } + if (in_isr()) { + xTimerStopFromISR(callout->handle, &woken1); + xTimerChangePeriodFromISR(callout->handle, ticks, &woken2); + xTimerResetFromISR(callout->handle, &woken3); + + if (woken1 == pdTRUE || woken2 == pdTRUE || woken3 == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + xTimerStop(callout->handle, portMAX_DELAY); + xTimerChangePeriod(callout->handle, ticks, portMAX_DELAY); + xTimerReset(callout->handle, portMAX_DELAY); + } + + return BTDM_OSAL_OK; +#endif +} + +void +wr_btdm_osal_callout_mem_reset(struct btdm_osal_callout *co) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + + btdm_osal_event_reset(&callout->ev); +} + +void IRAM_ATTR +wr_btdm_osal_callout_stop(struct btdm_osal_callout *co) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + + if (!callout) { + return; + } + +#if BTDM_OSAL_USE_ESP_TIMER + esp_timer_stop(callout->handle); +#else + xTimerStop(callout->handle, portMAX_DELAY); +#endif +} + +bool IRAM_ATTR +wr_btdm_osal_callout_is_active(struct btdm_osal_callout *co) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; +#if BTDM_OSAL_USE_ESP_TIMER + return esp_timer_is_active(callout->handle); +#else + return xTimerIsTimerActive(callout->handle) == pdTRUE; +#endif +} + +btdm_osal_time_t IRAM_ATTR +wr_btdm_osal_callout_get_ticks(struct btdm_osal_callout *co) +{ +#if BTDM_OSAL_USE_ESP_TIMER + + uint32_t exp = 0; + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + uint64_t expiry = 0; + esp_err_t err; + + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + + // Fetch expiry time in microseconds + err = esp_timer_get_expiry_time((esp_timer_handle_t)(callout->handle), &expiry); + if (err != ESP_OK) { + // Error. Could not fetch the expiry time + return 0; + } + + // Convert microseconds to ticks + btdm_osal_time_ms_to_ticks((uint32_t)(expiry / 1000), &exp); +#else + // esp_timer_get_expiry_time() is only available from IDF 5.0 onwards + /* Returning 0 from here should not cause any effect. + * Drawback of this approach is that existing code to reset timer would be called + * more often (since the if condition to invoke reset timer would always succeed if + * timer is active). + */ + exp = 0; +#endif // ESP_IDF_VERSION + + return exp; +#else + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + return xTimerGetExpiryTime(callout->handle); +#endif +} + +btdm_osal_time_t IRAM_ATTR +wr_btdm_osal_callout_remaining_ticks(struct btdm_osal_callout *co, btdm_osal_time_t now) +{ + btdm_osal_time_t rt; + uint32_t exp = 0; + + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + +#if BTDM_OSAL_USE_ESP_TIMER +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + uint64_t expiry = 0; + esp_err_t err; + + // Fetch expiry time in microseconds + err = esp_timer_get_expiry_time((esp_timer_handle_t)(callout->handle), &expiry); + if (err != ESP_OK) { + // Error. Could not fetch the expiry time + return 0; + } + + // Convert microseconds to ticks + btdm_osal_time_ms_to_ticks((uint32_t)(expiry / 1000), &exp); +#else + // esp_timer_get_expiry_time() is only available from IDF 5.0 onwards + // Set expiry to 0 + exp = 0; +#endif // ESP_IDF_VERSION +#else + exp = xTimerGetExpiryTime(callout->handle); +#endif + + if (exp > now) { + rt = exp - now; + } else { + rt = 0; + } + + return rt; +} + +void IRAM_ATTR +wr_btdm_osal_callout_set_arg(struct btdm_osal_callout *co, void *arg) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + struct btdm_osal_event_freertos *event = (struct btdm_osal_event_freertos *)callout->ev.event; + event->arg = arg; +} + +#if 0 +void IRAM_ATTR +wr_btdm_osal_callout_mem_reset(struct btdm_osal_callout *co) +{ + struct btdm_osal_callout_freertos *callout = (struct btdm_osal_callout_freertos *)co->co; + + BTDM_OSAL_ASSERT(callout); + BTDM_OSAL_ASSERT(callout->handle); + + btdm_osal_event_reset(&callout->ev); +} +#endif + +/* + *************************************************************************************************** + * BTDM OSAL Time + *************************************************************************************************** + */ +uint32_t IRAM_ATTR +wr_btdm_osal_time_get(void) +{ +#if BTDM_OSAL_USE_ESP_TIMER + return esp_timer_get_time() / 1000; +#else + return xTaskGetTickCountFromISR(); +#endif +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_time_ms_to_ticks(uint32_t ms, btdm_osal_time_t *out_ticks) +{ + uint64_t ticks; +#if BTDM_OSAL_USE_ESP_TIMER + ticks = (uint64_t)ms; +#else + ticks = ((uint64_t)ms * configTICK_RATE_HZ) / 1000; +#endif + if (ticks > UINT32_MAX) { + return BTDM_OSAL_EINVAL; + } + + *out_ticks = ticks; + + return 0; +} + +btdm_osal_error_t IRAM_ATTR +btdm_osal_time_ticks_to_ms(btdm_osal_time_t ticks, uint32_t *out_ms) +{ + uint64_t ms; +#if BTDM_OSAL_USE_ESP_TIMER + ms = ((uint64_t)ticks); +#else + ms = ((uint64_t)ticks * 1000) / configTICK_RATE_HZ; +#endif + if (ms > UINT32_MAX) { + return BTDM_OSAL_EINVAL; + } + + *out_ms = ms; + + return 0; +} + +btdm_osal_time_t IRAM_ATTR +wr_btdm_osal_time_ms_to_ticks32(uint32_t ms) +{ +#if BTDM_OSAL_USE_ESP_TIMER + return ms; +#else + return ms * configTICK_RATE_HZ / 1000; +#endif +} + +uint32_t IRAM_ATTR +wr_btdm_osal_time_ticks_to_ms32(btdm_osal_time_t ticks) +{ +#if BTDM_OSAL_USE_ESP_TIMER + return ticks; +#else + return ticks * 1000 / configTICK_RATE_HZ; +#endif +} + +uint32_t IRAM_ATTR +wr_btdm_osal_get_time_forever(void) +{ + return portMAX_DELAY; +} + +/* + *************************************************************************************************** + * BTDM OSAL Hw Critical + *************************************************************************************************** + */ +uint32_t IRAM_ATTR +wr_btdm_osal_hw_enter_critical(void) +{ + portENTER_CRITICAL_SAFE(&s_btsm_osal_intr_mutex); + ++s_btdm_osal_intr_nest; + return 0; +} + +uint8_t IRAM_ATTR +wr_btdm_osal_hw_is_in_critical(void) +{ + return s_btdm_osal_intr_nest; +} + +void IRAM_ATTR +wr_btdm_osal_hw_exit_critical(uint32_t ctx) +{ + ESP_UNUSED(ctx); + --s_btdm_osal_intr_nest; + portEXIT_CRITICAL_SAFE(&s_btsm_osal_intr_mutex); +} + +/* + *************************************************************************************************** + * BTDM OSAL Task + *************************************************************************************************** + */ +int +wr_btdm_osal_task_create(btdm_osal_task_fn *fn, const char *name, uint32_t stack_size, void *arg, + uint32_t priority, btdm_osal_task_handle_t *task_handle, uint32_t core_id) +{ + return xTaskCreatePinnedToCore(fn, name, stack_size, arg, priority, (TaskHandle_t *)task_handle, + (core_id < portNUM_PROCESSORS ? core_id : tskNO_AFFINITY)) == + pdPASS + ? BTDM_OSAL_OK + : BTDM_OSAL_ERROR; +} + +void +wr_btdm_osal_task_delete(btdm_osal_task_handle_t task_handle) +{ + vTaskDelete(task_handle); +} + +/* + *************************************************************************************************** + * BTDM OSAL Interrupt + *************************************************************************************************** + */ +static void +interrupt_alloc_ipc_func(struct btdm_intr_alloc_params *params) +{ + params->rsp = esp_intr_alloc(params->cp.source, params->cp.flags, params->cp.handler, + params->cp.arg, params->cp.ret_handle_in); +} + +int +wr_btdm_osal_intr_alloc(int src, int flags, btdm_osal_intr_fn *fn, void *arg, + btdm_osal_intr_handle_t *intr_handle) +{ + struct btdm_intr_alloc_params params = { + .cp.source = src, + .cp.flags = ESP_INTR_FLAG_LEVEL3, + .cp.handler = (intr_handler_t)fn, + .cp.arg = arg, + .cp.ret_handle_in = (intr_handle_t *)intr_handle, + }; + + if (!flags) { + params.cp.flags |= ESP_INTR_FLAG_IRAM; + } + +#if !CONFIG_FREERTOS_UNICORE + esp_ipc_call_blocking(CONFIG_BT_CTRL_PINNED_TO_CORE, (esp_ipc_func_t)interrupt_alloc_ipc_func, + ¶ms); +#else + interrupt_alloc_ipc_func(¶ms); +#endif + + return params.rsp; +} + +int +wr_btdm_osal_intr_free(btdm_osal_intr_handle_t intr_handle) +{ + return esp_intr_free(intr_handle); +} + +/* + *************************************************************************************************** + * BTDM OSAL Malloc + *************************************************************************************************** + */ +void * +wr_btdm_osal_malloc(uint32_t size, btdm_osal_malloc_flag_t flags) +{ + if (flags == BTDM_OSAL_MALLOC_F_INTERNAL) { + return heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); + } else { + return heap_caps_malloc(size, MALLOC_CAP_8BIT); + } +} + +void +wr_btdm_osal_free(void *ptr) +{ + heap_caps_free(ptr); +} + +#if !CONFIG_BTDM_CTRL_MULTI_LINK_ENABLED +void * +wr_btdm_osal_mmgmt_block_malloc(uint32_t size) +{ + uint32_t *addr; + + // TODO: Only ble controller uses this function + addr = btdm_osal_malloc(size + 4, BTDM_OSAL_MALLOC_F_INTERNAL); + *addr = (5 << 29) | ((size + 4) >> 2); + + return (void *)((uint32_t)addr + 4); +} +void +wr_btdm_osal_mmgmt_block_free(void *ptr) +{ + void *actual_addr; + + // TODO: Only ble controller uses this function + actual_addr = (void *)ptr - 4; + return btdm_osal_free(actual_addr); +} + +void +wr_btdm_osal_mmgmt_block_copy(void *dst, const void *src, uint16_t size) +{ + // TODO: Only ble controller uses this function + extern void r_ble_lll_mmgmt_block_copy(void *addr0, void *addr1, uint16_t size); + r_ble_lll_mmgmt_block_copy((void *)dst, (void *)src, size); +} +#endif /* !CONFIG_BTDM_CTRL_MULTI_LINK_ENABLED */ + +/* + *************************************************************************************************** + * BTDM OSAL Efuse + *************************************************************************************************** + */ +int +wr_btdm_osal_read_efuse_mac(uint8_t *mac) +{ + ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); + return 0; +} + +/* + *************************************************************************************************** + * BTDM OSAL Rand + *************************************************************************************************** + */ +void +wr_btdm_osal_srand(uint32_t seed) +{ + srand(seed); +} + +int +wr_btdm_osal_rand(void) +{ + // return (int)esp_random(); + return rand(); +} + +/* + *************************************************************************************************** + * BTDM OSAL ISO Mutex (TODO: should be deleted) + *************************************************************************************************** + */ +btdm_osal_error_t +wr_btdm_osal_iso_mutex_init(struct btdm_osal_mutex *mu) +{ + struct btdm_osal_mutex_freertos *mutex; + +#if BTDM_MEMPOOL_ALLOC + if (!btdm_memblock_from(&s_btdm_osal_mutex_pool, mu->mutex)) { + mu->mutex = btdm_memblock_get(&s_btdm_osal_mutex_pool); + mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + memset(mutex, 0, sizeof(*mutex)); + mutex->handle = xSemaphoreCreateMutex(); + BTDM_OSAL_ASSERT(mutex->handle); + } +#else + if (!mu->mutex) { + mu->mutex = malloc(sizeof(struct btdm_osal_mutex_freertos)); + mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + memset(mutex, 0, sizeof(*mutex)); + mutex->handle = xSemaphoreCreateMutex(); + BTDM_OSAL_ASSERT(mutex->handle); + } +#endif + + return BTDM_OSAL_OK; +} + +btdm_osal_error_t +wr_btdm_osal_iso_mutex_deinit(struct btdm_osal_mutex *mu) +{ + struct btdm_osal_mutex_freertos *mutex; + + BTDM_OSAL_ASSERT(mu); + + mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(mutex->handle); + vSemaphoreDelete(mutex->handle); + +#if BTDM_MEMPOOL_ALLOC + btdm_memblock_put(&s_btdm_osal_mutex_pool, mutex); +#else + free((void *)mutex); +#endif + mu->mutex = NULL; + + return BTDM_OSAL_OK; +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_iso_mutex_pend(struct btdm_osal_mutex *mu, btdm_osal_time_t timeout) +{ + struct btdm_osal_mutex_freertos *mutex; + BaseType_t woken; + BaseType_t ret; + + mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(mutex->handle); + + if (in_isr()) { + (void)timeout; + ret = xSemaphoreTakeFromISR(mutex->handle, &woken); + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + ret = xSemaphoreTake(mutex->handle, timeout); + } + + return ret == pdPASS ? BTDM_OSAL_OK : BTDM_OSAL_TIMEOUT; +} + +btdm_osal_error_t IRAM_ATTR +wr_btdm_osal_iso_mutex_release(struct btdm_osal_mutex *mu) +{ + struct btdm_osal_mutex_freertos *mutex; + BaseType_t woken; + BaseType_t ret; + + BTDM_OSAL_ASSERT(mu); + + mutex = (struct btdm_osal_mutex_freertos *)mu->mutex; + if (!mutex) { + return BTDM_OSAL_INVALID_PARM; + } + + BTDM_OSAL_ASSERT(mutex->handle); + + if (in_isr()) { + ret = xSemaphoreGiveFromISR(mutex->handle, &woken); + if (woken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } else { + ret = xSemaphoreGive(mutex->handle); + } + + BTDM_OSAL_ASSERT(ret == pdPASS); + + return BTDM_OSAL_OK; +} + +/* + *************************************************************************************************** + * BTDM OSAL Initialization + *************************************************************************************************** + */ +int +btdm_osal_elem_mempool_init(btdm_osal_elem_num_t *elem_num) +{ +#if BTDM_MEMPOOL_ALLOC + int rc; + + s_btdm_osal_evtq_deepth = elem_num->evt_count; + + if (elem_num->evt_count) { + s_btdm_osal_ev_buf = btdm_osal_malloc( + BTDM_MEMPOOL_SIZE(elem_num->evt_count, sizeof(struct btdm_osal_event_freertos)) * + sizeof(btdm_membuf_t), + BTDM_OSAL_MALLOC_F_INTERNAL); + if (!s_btdm_osal_ev_buf) { + return -1; + } + rc = btdm_mempool_init(&s_btdm_osal_ev_pool, elem_num->evt_count, + sizeof(struct btdm_osal_event_freertos), s_btdm_osal_ev_buf, + "s_btdm_osal_ev_pool"); + if (rc) { + return -2; + } + } + + if (elem_num->evtq_count) { + s_btdm_osal_evq_buf = btdm_osal_malloc( + BTDM_MEMPOOL_SIZE(elem_num->evtq_count, sizeof(struct btdm_osal_eventq_freertos)) * + sizeof(btdm_membuf_t), + BTDM_OSAL_MALLOC_F_INTERNAL); + if (!s_btdm_osal_evq_buf) { + return -3; + } + rc = btdm_mempool_init(&s_btdm_osal_evq_pool, elem_num->evtq_count, + sizeof(struct btdm_osal_eventq_freertos), s_btdm_osal_evq_buf, + "s_btdm_osal_evq_pool"); + if (rc) { + return -4; + } + } + + if (elem_num->co_count) { + s_btdm_osal_co_buf = btdm_osal_malloc( + BTDM_MEMPOOL_SIZE(elem_num->co_count, sizeof(struct btdm_osal_callout_freertos)) * + sizeof(btdm_membuf_t), + BTDM_OSAL_MALLOC_F_INTERNAL); + if (!s_btdm_osal_co_buf) { + return -5; + } + rc = btdm_mempool_init(&s_btdm_osal_co_pool, elem_num->co_count, + sizeof(struct btdm_osal_callout_freertos), s_btdm_osal_co_buf, + "s_btdm_osal_co_pool"); + if (rc) { + return -6; + } + } + + if (elem_num->sem_count) { + s_btdm_osal_sem_buf = btdm_osal_malloc( + BTDM_MEMPOOL_SIZE(elem_num->sem_count, sizeof(struct btdm_osal_sem_freertos)) * + sizeof(btdm_membuf_t), + BTDM_OSAL_MALLOC_F_INTERNAL); + if (!s_btdm_osal_sem_buf) { + return -7; + } + rc = + btdm_mempool_init(&s_btdm_osal_sem_pool, elem_num->sem_count, sizeof(struct btdm_osal_sem_freertos), + s_btdm_osal_sem_buf, "s_btdm_osal_sem_pool"); + if (rc) { + return -8; + } + } + + if (elem_num->mutex_count) { + s_btdm_osal_mutex_buf = btdm_osal_malloc( + BTDM_MEMPOOL_SIZE(elem_num->mutex_count, sizeof(struct btdm_osal_mutex_freertos)) * + sizeof(btdm_membuf_t), + BTDM_OSAL_MALLOC_F_INTERNAL); + if (!s_btdm_osal_mutex_buf) { + return -9; + } + rc = btdm_mempool_init(&s_btdm_osal_mutex_pool, elem_num->mutex_count, + sizeof(struct btdm_osal_mutex_freertos), s_btdm_osal_mutex_buf, + "s_btdm_osal_mutex_pool"); + if (rc) { + return -10; + } + } + + return 0; +#else + return 0; +#endif // BTDM_MEMPOOL_ALLOC +} + +void +btdm_osal_elem_mempool_deinit(void) +{ +#if BTDM_MEMPOOL_ALLOC + if (s_btdm_osal_ev_buf) { + BTDM_OSAL_ASSERT(s_btdm_osal_ev_pool.mp_num_free == s_btdm_osal_ev_pool.mp_num_blocks); + btdm_osal_free(s_btdm_osal_ev_buf); + s_btdm_osal_ev_buf = NULL; + } + if (s_btdm_osal_evq_buf) { + BTDM_OSAL_ASSERT(s_btdm_osal_evq_pool.mp_num_free == s_btdm_osal_evq_pool.mp_num_blocks); + btdm_osal_free(s_btdm_osal_evq_buf); + s_btdm_osal_evq_buf = NULL; + } + if (s_btdm_osal_co_buf) { + BTDM_OSAL_ASSERT(s_btdm_osal_co_pool.mp_num_free == s_btdm_osal_co_pool.mp_num_blocks); + btdm_osal_free(s_btdm_osal_co_buf); + s_btdm_osal_co_buf = NULL; + } + if (s_btdm_osal_sem_buf) { + BTDM_OSAL_ASSERT(s_btdm_osal_sem_pool.mp_num_free == s_btdm_osal_sem_pool.mp_num_blocks); + btdm_osal_free(s_btdm_osal_sem_buf); + s_btdm_osal_sem_buf = NULL; + } + if (s_btdm_osal_mutex_buf) { + BTDM_OSAL_ASSERT(s_btdm_osal_mutex_pool.mp_num_free == s_btdm_osal_mutex_pool.mp_num_blocks); + btdm_osal_free(s_btdm_osal_mutex_buf); + s_btdm_osal_mutex_buf = NULL; + } +#endif // BTDM_MEMPOOL_ALLOC +} diff --git a/components/bt/porting_btdm/transport/driver/common/hci_driver_h4.c b/components/bt/porting_btdm/transport/driver/common/hci_driver_h4.c new file mode 100644 index 0000000000..4515d1504c --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/common/hci_driver_h4.c @@ -0,0 +1,489 @@ +/* + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include "esp_hci_internal.h" +#include "common/hci_driver_h4.h" +#include "common/hci_driver_util.h" + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define HCI_H4_SM_W4_PKT_TYPE 0 +#define HCI_H4_SM_W4_HEADER 1 +#define HCI_H4_SM_W4_PAYLOAD 2 +#define HCI_H4_SM_COMPLETED 3 + +struct hci_h4_input_buffer { + const uint8_t *buf; + uint16_t len; +}; + +static int +hci_h4_frame_start(struct hci_h4_sm *rxs, uint8_t pkt_type) +{ + rxs->pkt_type = pkt_type; + rxs->len = 0; + rxs->exp_len = 0; + + switch (rxs->pkt_type) { + case HCI_H4_CMD: + case HCI_H4_SYNC: + rxs->min_len = 3; + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + rxs->min_len = 4; + break; +#if (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_EVT: + rxs->min_len = 2; + break; +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) + default: + /* !TODO: Sync loss. Need to wait for reset. */ + return -1; + } + + return 0; +} + +static int +hci_h4_ib_consume(struct hci_h4_input_buffer *ib, uint16_t len) +{ + HCI_TRANS_ASSERT((ib->len >= len), ib->len, len); + + ib->buf += len; + ib->len -= len; + + return len; +} + +static int +hci_h4_ib_pull_min_len(struct hci_h4_sm *rxs, + struct hci_h4_input_buffer *ib) +{ + uint16_t len; + + len = min(ib->len, rxs->min_len - rxs->len); + memcpy(&rxs->hdr[rxs->len], ib->buf, len); + + rxs->len += len; + hci_h4_ib_consume(ib, len); + + + return rxs->len != rxs->min_len; +} + +static int +hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) +{ + int rc; + uint16_t conn_handle = 0; + + rc = hci_h4_ib_pull_min_len(h4sm, ib); + if (rc) { + /* need more data */ + return 1; + } + + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->cmd, 0, 0); + h4sm->pkt = h4sm->allocs->cmd(); + if (!h4sm->pkt) { + return -1; + } + + memcpy(h4sm->pkt->data, h4sm->hdr, h4sm->len); + h4sm->exp_len = h4sm->hdr[2] + 3; + break; + case HCI_H4_ACL: + conn_handle = btdm_get_le16(&h4sm->hdr[0]) & HCI_INTERNAL_CONN_MASK; +#if UC_BT_CTRL_BLE_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BLE(conn_handle)) { + assert(h4sm->allocs && h4sm->allocs->acl); + h4sm->om = h4sm->allocs->acl(); + if (!h4sm->om) { + return -1; + } + + ble_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len); + h4sm->exp_len = btdm_get_le16(&h4sm->hdr[2]) + 4; + break; + } +#endif // UC_BT_CTRL_BLE_IS_ENABLE +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BREDR(conn_handle)) { + assert(h4sm->allocs && h4sm->allocs->bredr_acl); + h4sm->exp_len = btdm_get_le16(&h4sm->hdr[2]) + 4; + h4sm->pkt = h4sm->allocs->bredr_acl(conn_handle); + if (!h4sm->pkt) { + return -1; + } + memcpy(h4sm->pkt->data, h4sm->hdr, h4sm->len); + break; + } + case HCI_H4_SYNC: + conn_handle = btdm_get_le16(&h4sm->hdr[0]) & HCI_INTERNAL_CONN_MASK; + assert(h4sm->allocs && h4sm->allocs->sync); + h4sm->exp_len = h4sm->hdr[2] + 3; + h4sm->pkt = h4sm->allocs->sync(conn_handle); + if (!h4sm->pkt) { + return -1; + } + memcpy(h4sm->pkt->data, h4sm->hdr, h4sm->len); + break; +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE +#if !CONFIG_BT_CONTROLLER_ENABLED + case HCI_H4_EVT: + if (h4sm->hdr[0] == BLE_HCI_EVCODE_LE_META) { + /* For LE Meta event we need 3 bytes to parse header */ + h4sm->min_len = 3; + rc = hci_h4_ib_pull_min_len(h4sm, ib); + if (rc) { + /* need more data */ + return 1; + } + } + + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->evt, 0, 0); + + /* We can drop legacy advertising events if there's no free buffer in + * discardable pool. + */ + if (h4sm->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) { + h4sm->buf = h4sm->allocs->evt(1); + } else { + h4sm->buf = h4sm->allocs->evt(0); + if (!h4sm->buf) { + return -1; + } + } + + if (h4sm->buf) { + memcpy(h4sm->buf, h4sm->hdr, h4sm->len); + } + + h4sm->exp_len = h4sm->hdr[1] + 2; + break; +#endif // !CONFIG_BT_CONTROLLER_ENABLED +#if CONFIG_BT_LE_ISO_SUPPORT + case HCI_H4_ISO: + assert(h4sm->allocs && h4sm->allocs->iso); + h4sm->exp_len = (btdm_get_le16(&h4sm->hdr[2]) & 0x7fff) + 4; + h4sm->buf = h4sm->allocs->iso(h4sm->exp_len); + if (!h4sm->buf) { + return -1; + } + + memcpy(h4sm->buf, h4sm->hdr, h4sm->len); + break; +#endif // CONFIG_BT_LE_ISO_SUPPORT + default: + assert(0); + break; + } + + return 0; +} + +static int +hci_h4_sm_w4_payload(struct hci_h4_sm *h4sm, + struct hci_h4_input_buffer *ib) +{ + uint16_t len; + + len = min(ib->len, h4sm->exp_len - h4sm->len); + + + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + case HCI_H4_SYNC: + if (h4sm->pkt) { + memcpy(&h4sm->pkt->data[h4sm->len], ib->buf, len); + } + break; + case HCI_H4_EVT: + case HCI_H4_ISO: + if (h4sm->buf) { + memcpy(&h4sm->buf[h4sm->len], ib->buf, len); + } + break; + case HCI_H4_ACL: + HCI_TRANS_ASSERT(h4sm->om, h4sm->pkt_type, len); + uint16_t conn_handle = btdm_get_le16(&h4sm->hdr[0]) & HCI_INTERNAL_CONN_MASK; +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BREDR(conn_handle)) { + memcpy(&h4sm->pkt->data[h4sm->len], ib->buf, len); + break; + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE +#if UC_BT_CTRL_BLE_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BLE(conn_handle)) { + uint16_t mbuf_len = BLE_MBUF_PKTLEN(h4sm->om); + int rc = ble_mbuf_append(h4sm->om, ib->buf, len); + if (rc) { + /* Some data may already be appended so need to adjust h4sm only by + * the size of appended data. + */ + len = BLE_MBUF_PKTLEN(h4sm->om) - mbuf_len; + h4sm->len += len; + hci_h4_ib_consume(ib, len); + return -1; + } + } + break; +#endif // UC_BT_CTRL_BLE_IS_ENABLE + default: + assert(0); + break; + } + + h4sm->len += len; + hci_h4_ib_consume(ib, len); + + /* return 1 if need more data */ + return h4sm->len != h4sm->exp_len; +} + +static void +hci_h4_sm_completed(struct hci_h4_sm *h4sm) +{ + int rc; + uint8_t data_source = 0xFF; + + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + switch (h4sm->pkt_type) { +#if CONFIG_BT_CONTROLLER_ENABLED + case HCI_H4_ACL: + uint16_t conn_handle = btdm_get_le16(&h4sm->hdr[0]) & HCI_INTERNAL_CONN_MASK; +#if UC_BT_CTRL_BLE_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BLE(conn_handle)) { + if (h4sm->om) { + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om, h4sm->len, HCI_DRIVER_LE_ACL); + HCI_TRANS_ASSERT(rc == 0, rc, 0); + h4sm->om = NULL; + } + } +#endif // UC_BT_CTRL_BLE_IS_ENABLE +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BREDR(conn_handle)) { + if (h4sm->buf) { + rc = h4sm->frame_cb(h4sm->pkt_type, (void *)h4sm->buf, h4sm->len, HCI_DRIVER_BREDR_ACL); + HCI_TRANS_ASSERT(rc == 0, rc, 0); + h4sm->buf = NULL; + } + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + break; + case HCI_H4_CMD: + case HCI_H4_SYNC: + case HCI_H4_ISO: + if (h4sm->buf) { + switch(h4sm->pkt_type) { + case HCI_H4_CMD: + data_source = HCI_DRIVER_CMD; + break; + case HCI_H4_SYNC: + data_source = HCI_DRIVER_BREDR_SYNC; + break; + case HCI_H4_ISO: + data_source = HCI_DRIVER_LE_ISO; + break; + } + + rc = h4sm->frame_cb(h4sm->pkt_type, (void *)h4sm->buf, h4sm->len, data_source); + HCI_TRANS_ASSERT(rc == 0, rc, 0); + h4sm->buf = NULL; + } + break; +#else + case HCI_H4_CMD: + case HCI_H4_EVT: + if (h4sm->buf) { + assert(h4sm->frame_cb); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); + if (rc != 0) { + ble_transport_free(h4sm->buf); + } + h4sm->buf = NULL; + } + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + if (h4sm->om) { + assert(h4sm->frame_cb); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); + if (rc != 0) { + os_mbuf_free_chain(h4sm->om); + } + h4sm->om = NULL; + } + break; +#endif // CONFIG_BT_CONTROLLER_ENABLED + default: + assert(0); + break; + } +} + +static int +hci_h4_sm_free_buf(struct hci_h4_sm *h4sm) +{ + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + if (h4sm->buf) { + h4sm->frees->cmd(h4sm->buf); + h4sm->buf = NULL; + } + break; +#if (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_EVT: + if (h4sm->buf) { + h4sm->frees->evt(h4sm->buf); + h4sm->buf = NULL; + } + break; +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_ACL: +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + uint16_t conn_handle = btdm_get_le16(&h4sm->hdr[0]) & HCI_INTERNAL_CONN_MASK; + if (HCI_INTERNAL_CONN_IS_BLE(conn_handle)) { + if (h4sm->om) { + h4sm->frees->acl(h4sm->om); + h4sm->om = NULL; + } + } else { + if (h4sm->pkt) { + h4sm->frees->bredr_acl(h4sm->pkt); + h4sm->pkt = NULL; + } + } +#else + if (h4sm->om) { + h4sm->frees->acl(h4sm->om); + h4sm->om = NULL; + } +#endif + break; + case HCI_H4_ISO: + if (h4sm->buf) { + h4sm->frees->iso(h4sm->buf); + h4sm->buf = NULL; + } + break; +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + case HCI_H4_SYNC: + if (h4sm->pkt) { + h4sm->frees->sync(h4sm->pkt); + h4sm->pkt = NULL; + } + break; +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + default: + break; + } + + return 0; +} + + +int +hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) +{ + struct hci_h4_input_buffer ib = { + .buf = buf, + .len = len, + }; + + int rc = 0; + while (ib.len && (rc >= 0)) { + rc = 0; + switch (h4sm->state) { + case HCI_H4_SM_W4_PKT_TYPE: + if (hci_h4_frame_start(h4sm, ib.buf[0]) < 0) { + return -1; + } + + hci_h4_ib_consume(&ib, 1); + h4sm->state = HCI_H4_SM_W4_HEADER; + /* no break */ + case HCI_H4_SM_W4_HEADER: + rc = hci_h4_sm_w4_header(h4sm, &ib); + assert(rc >= 0); + if (rc) { + break; + } + h4sm->state = HCI_H4_SM_W4_PAYLOAD; + /* no break */ + case HCI_H4_SM_W4_PAYLOAD: + rc = hci_h4_sm_w4_payload(h4sm, &ib); + assert(rc >= 0); + if (rc) { + break; + } + h4sm->state = HCI_H4_SM_COMPLETED; + /* no break */ + case HCI_H4_SM_COMPLETED: + hci_h4_sm_completed(h4sm); + h4sm->state = HCI_H4_SM_W4_PKT_TYPE; + break; + default: + return -1; + } + } + + /* Calculate consumed bytes + * + * Note: we should always consume some bytes unless there is an oom error. + * It's also possible that we have an oom error but already consumed some + * data, in such case just return success and error will be returned on next + * pass. + */ + len = len - ib.len; + if (len == 0) { + HCI_TRANS_ASSERT((rc < 0), rc, ib.len); + return -1; + } + + return len; +} + +void +hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, const struct hci_h4_frees *frees, + hci_h4_frame_cb *frame_cb) +{ + memset(h4sm, 0, sizeof(*h4sm)); + h4sm->allocs = allocs; + h4sm->frees = frees; + h4sm->frame_cb = frame_cb; +} diff --git a/components/bt/porting_btdm/transport/driver/common/hci_driver_mem.c b/components/bt/porting_btdm/transport/driver/common/hci_driver_mem.c new file mode 100644 index 0000000000..df786e545b --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/common/hci_driver_mem.c @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_hci_internal.h" +#include "common/hci_driver_mem.h" +#include "common/hci_driver_h4.h" + +hci_driver_packet_t * +hci_driver_mem_cmd_alloc(void) +{ + return btdm_hci_trans_buf_alloc(HCI_H4_CMD, 0); +} + +void * +hci_driver_mem_evt_alloc(int discardable) +{ + /* The controller shouldn't invoke this. */ + assert(0); + return NULL; +} + +struct ble_mbuf * +hci_driver_mem_acl_alloc(void) +{ + return ble_msys_get_pkthdr(0, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); +} + +struct ble_mbuf * +hci_driver_mem_acl_len_alloc(uint32_t len) +{ + return ble_msys_get_pkthdr(len, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); +} + +void * +hci_driver_mem_iso_alloc(uint32_t len) +{ + return malloc(len); +} + +void +hci_driver_mem_iso_free(void *ptr) +{ + free(ptr); +} + +struct ble_mbuf * +hci_driver_mem_iso_len_alloc(uint32_t len) +{ + return ble_msys_get_pkthdr(len, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); +} + +void +hci_driver_mem_cmd_free(void * ptr) +{ + hci_driver_packet_t *pkt = (hci_driver_packet_t *) ptr; + btdm_hci_trans_buf_free(pkt); +} + +void +hci_driver_mem_evt_free(void *ptr) +{ + hci_driver_packet_t *pkt = (hci_driver_packet_t *) ptr; + btdm_hci_trans_buf_free(pkt); +} + +#if UC_BTDM_CTRL_BR_EDR_IS_ENABLE +hci_driver_packet_t * +hci_driver_mem_bredr_acl_alloc(uint16_t handle) +{ + return btdm_hci_trans_buf_alloc(HCI_H4_ACL, handle); +} + +void +hci_driver_mem_bredr_acl_free(void *ptr) +{ + hci_driver_packet_t *pkt = (hci_driver_packet_t *) ptr; + bredr_hci_trans_acl_tx_done(pkt); + bredr_hci_trans_acl_free(pkt); +} + +hci_driver_packet_t * +hci_driver_mem_sync_alloc(uint16_t handle) +{ + return btdm_hci_trans_buf_alloc(HCI_H4_SYNC, handle); +} + +void +hci_driver_mem_sync_free(void *ptr) +{ + hci_driver_packet_t *pkt = (hci_driver_packet_t *) ptr; + bredr_hci_trans_sync_tx_done(pkt); + bredr_hci_trans_sync_free(pkt); +} +#endif // UC_BTDM_CTRL_BR_EDR_IS_ENABLE + +const struct hci_h4_allocators s_hci_driver_mem_alloc = { + .cmd = hci_driver_mem_cmd_alloc, + .evt = hci_driver_mem_evt_alloc, + .acl = hci_driver_mem_acl_alloc, + .iso = hci_driver_mem_iso_alloc, +#if UC_BTDM_CTRL_BR_EDR_IS_ENABLE + .sync = hci_driver_mem_sync_alloc, + .bredr_acl = hci_driver_mem_bredr_acl_alloc, +#endif // UC_BTDM_CTRL_BR_EDR_IS_ENABLE +}; + +const struct hci_h4_frees s_hci_driver_mem_free = { + .cmd = hci_driver_mem_cmd_free, + .evt = hci_driver_mem_evt_free, + .acl = ble_mbuf_free_chain, + .iso = hci_driver_mem_iso_free, + .le_evt = r_ble_hci_trans_buf_free, +#if UC_BTDM_CTRL_BR_EDR_IS_ENABLE + .sync = hci_driver_mem_sync_free, + .bredr_acl = hci_driver_mem_bredr_acl_free, +#endif // UC_BTDM_CTRL_BR_EDR_IS_ENABLE +}; diff --git a/components/bt/porting_btdm/transport/driver/common/hci_driver_util.c b/components/bt/porting_btdm/transport/driver/common/hci_driver_util.c new file mode 100644 index 0000000000..4db68e6a54 --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/common/hci_driver_util.c @@ -0,0 +1,356 @@ +/* + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_log.h" +#include "esp_hci_driver.h" +#include "esp_hci_internal.h" +#include "common/hci_driver_util.h" + +#define TAG "HCI_UTIL" +#if UC_BT_CTRL_BR_EDR_IS_ENABLE +#define HCI_DRIVER_UTIL_BREDR_HCI_EVT_TX_POOL_NUM 4 +#define HCI_DRIVER_UTIL_BREDR_TX_POOL_NUM \ + (CONFIG_BT_CTRL_BR_EDR_ACLU_RX_BUF_NB_EFF + CONFIG_BT_CTRL_BR_EDR_SYNC_RX_BUF_NB_EFF + HCI_DRIVER_UTIL_BREDR_HCI_EVT_TX_POOL_NUM) +#else +#define HCI_DRIVER_UTIL_BREDR_TX_POOL_NUM 0 +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + +#if UC_BT_CTRL_BLE_IS_ENABLE +#define HCI_DRIVER_UTIL_BLE_TX_POOL_NUM \ + (CONFIG_BT_LE_ACL_BUF_COUNT + CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT + CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT) +#else +#define HCI_DRIVER_UTIL_BLE_TX_POOL_NUM 0 +#endif // UC_BT_CTRL_BLE_IS_ENABLE + +#define HCI_DRIVER_UTIL_TX_POOL_NUM \ + (HCI_DRIVER_UTIL_BLE_TX_POOL_NUM + HCI_DRIVER_UTIL_BREDR_TX_POOL_NUM) + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +/** + * @brief Structure representing HCI TX data. + */ +typedef struct hci_driver_util_tx_entry { + hci_driver_data_type_t data_type; ///< Type of the HCI TX data. + uint8_t data_source; ///< Source of the HCI TX data. + uint32_t length; ///< Length of the TX data. + union { + hci_driver_packet_t *pkt; + uint8_t *data; ///< Length of the TX ISO data. + }; + STAILQ_ENTRY(hci_driver_util_tx_entry) next; ///< Next element in the linked list. +} hci_driver_util_tx_entry_t; + +/* The list for hci_driver_util_tx_entry */ +STAILQ_HEAD(hci_driver_util_tx_list, hci_driver_util_tx_entry); + +typedef struct { + struct hci_driver_util_tx_list tx_head; + struct hci_driver_util_tx_entry *cur_tx_entry; + uint32_t cur_tx_off; + struct btdm_mempool *tx_entry_pool; + uint8_t *tx_entry_mem; +} hci_driver_util_env_t; + +static hci_driver_util_env_t s_hci_driver_util_env; + +static void +hci_driver_util_memory_deinit(void) +{ + if (s_hci_driver_util_env.tx_entry_pool) { + free(s_hci_driver_util_env.tx_entry_pool); + s_hci_driver_util_env.tx_entry_pool = NULL; + } + if (s_hci_driver_util_env.tx_entry_mem) { + free(s_hci_driver_util_env.tx_entry_mem); + s_hci_driver_util_env.tx_entry_mem = NULL; + } +} + +static int +hci_driver_util_memory_init(void) +{ + int rc; + + s_hci_driver_util_env.tx_entry_pool = (struct btdm_mempool *)malloc(sizeof(struct btdm_mempool)); + if (!s_hci_driver_util_env.tx_entry_pool) { + ESP_LOGE(TAG, "No memory for tx pool"); + goto init_err; + } + + s_hci_driver_util_env.tx_entry_mem = malloc(BTDM_MEMPOOL_SIZE(HCI_DRIVER_UTIL_TX_POOL_NUM, + sizeof(hci_driver_util_tx_entry_t)) * sizeof(btdm_membuf_t)); + if (!s_hci_driver_util_env.tx_entry_mem) { + ESP_LOGE(TAG, "No memory for tx pool buffer"); + goto init_err; + } + + rc = btdm_mempool_init(s_hci_driver_util_env.tx_entry_pool, HCI_DRIVER_UTIL_TX_POOL_NUM, + sizeof(hci_driver_util_tx_entry_t), s_hci_driver_util_env.tx_entry_mem, + "hci_tx_entry_pool"); + if (rc) { + ESP_LOGE(TAG, "Failed to initialize tx pool"); + goto init_err; + } + + return 0; + +init_err: + hci_driver_util_memory_deinit(); + return -1; +} + +int +hci_driver_util_tx_list_enqueue(hci_driver_data_type_t type, uint8_t *data, uint32_t len, hci_driver_data_source_t data_source) +{ + hci_driver_util_tx_entry_t *tx_entry; + hci_driver_packet_t *pkt; + uint8_t event_code = 0; + + tx_entry = btdm_memblock_get(s_hci_driver_util_env.tx_entry_pool); + if (tx_entry == NULL) { + return -1; + } + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + pkt = (hci_driver_packet_t *)data; + switch (data_source) { + case HCI_DRIVER_BREDR_ACL: + bredr_hci_trans_acl_tx_done(pkt); + break; + case HCI_DRIVER_BREDR_SYNC: + bredr_hci_trans_sync_tx_done(pkt); + break; + case HCI_DRIVER_BREDR_EVT: + bredr_hci_trans_evt_tx_done(pkt); + break; + default: + break; + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + + + tx_entry->data_type = type; + tx_entry->data = data; + tx_entry->length = len; + tx_entry->data_source = data_source; + if (data_source == HCI_DRIVER_BTDM_EVT) { + pkt = (hci_driver_packet_t *)data; + event_code = pkt->data[0]; + } else if (data_source == HCI_DRIVER_LE_EVT){ + event_code = data[0]; + } + /* If the txbuf is command status event or command complete event, we should send firstly. + * The tx list maybe used in the controller task and hci task. Therefore, enter critical area. + */ + if ((data_source == HCI_DRIVER_LE_EVT || data_source == HCI_DRIVER_BTDM_EVT) && + ((event_code == 0x0E) || (event_code == 0x0F))) { + btdm_osal_hw_enter_critical(); + STAILQ_INSERT_HEAD(&s_hci_driver_util_env.tx_head, tx_entry, next); + btdm_osal_hw_exit_critical(0); + } else { + btdm_osal_hw_enter_critical(); + STAILQ_INSERT_TAIL(&s_hci_driver_util_env.tx_head, tx_entry, next); + btdm_osal_hw_exit_critical(0); + } + + return 0; +} + +uint32_t +hci_driver_util_tx_list_dequeue(uint32_t max_tx_len, void **tx_data, bool *last_frame) +{ + uint32_t tx_len; + uint32_t data_len; + hci_driver_util_tx_entry_t *tx_entry; + hci_driver_packet_t *pkt = NULL; + struct ble_mbuf *om = NULL; + uint16_t out_off; + /* Check if there is any remaining data that hasn't been sent completely. If it has been completed, + * free the corresponding memory. Therefore, the HCI TX entry needs to be sent one by one; multiple + * entries cannot be sent together. + */ + tx_len = 0; + tx_entry = s_hci_driver_util_env.cur_tx_entry; + if (tx_entry) { + pkt = tx_entry->pkt; + data_len = tx_entry->length; + if (tx_entry->data_type == HCI_DRIVER_TYPE_ACL) { + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + if (tx_entry->data_source == HCI_DRIVER_LE_ACL) { + om = (struct ble_mbuf *)tx_entry->data; + ble_mbuf_free_chain(om); + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + bredr_hci_trans_acl_free(pkt); + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + } else { + if (tx_entry->data_source == HCI_DRIVER_LE_ACL) { + om = (struct ble_mbuf *)tx_entry->data; + om = ble_mbuf_off(om, s_hci_driver_util_env.cur_tx_off, &out_off); + tx_len = min(max_tx_len, om->om_len - out_off); + *tx_data = (void *)&om->om_data[out_off]; + } else { + tx_len = min(max_tx_len, data_len - s_hci_driver_util_env.cur_tx_off); + *tx_data = &pkt->data[s_hci_driver_util_env.cur_tx_off]; + } + } + } else if (tx_entry->data_type == HCI_DRIVER_TYPE_EVT) { + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + if (tx_entry->data_source == HCI_DRIVER_LE_EVT) { + r_ble_hci_trans_buf_free(tx_entry->data); + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else if (tx_entry->data_source == HCI_DRIVER_BREDR_EVT) { + bredr_hci_trans_evt_free(pkt); + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + btdm_hci_trans_buf_free(pkt); + } + } else { + tx_len = min(max_tx_len, data_len - s_hci_driver_util_env.cur_tx_off); + if (tx_entry->data_source == HCI_DRIVER_LE_EVT) { + *tx_data = &tx_entry->data[s_hci_driver_util_env.cur_tx_off]; + } else { + *tx_data = &pkt->data[s_hci_driver_util_env.cur_tx_off]; + } + } + } else if (tx_entry->data_type == HCI_DRIVER_TYPE_ISO) { + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + free(tx_entry->data); + } else { + tx_len = min(max_tx_len, data_len - s_hci_driver_util_env.cur_tx_off); + *tx_data = &tx_entry->data[s_hci_driver_util_env.cur_tx_off]; + } + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else if (tx_entry->data_type == HCI_DRIVER_TYPE_SYNC) { + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + bredr_hci_trans_sync_free(pkt); + } else { + tx_len = min(max_tx_len, data_len - s_hci_driver_util_env.cur_tx_off); + *tx_data = &pkt->data[s_hci_driver_util_env.cur_tx_off]; + } + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + HCI_TRANS_ASSERT(0, tx_entry->data_type, data_len); + } + /* If this is the last frame, inform the invoker not to call this API until the current data + * has been completely sent. + */ + if (tx_len) { + s_hci_driver_util_env.cur_tx_off += tx_len; + + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + *last_frame = true; + } else { + *last_frame = false; + } + } else { + btdm_memblock_put(s_hci_driver_util_env.tx_entry_pool, (void *)tx_entry); + s_hci_driver_util_env.cur_tx_entry = NULL; + } + } + + /* Find a new entry. */ + if (!tx_len && !STAILQ_EMPTY(&s_hci_driver_util_env.tx_head)) { + btdm_osal_hw_enter_critical(); + tx_entry = STAILQ_FIRST(&s_hci_driver_util_env.tx_head); + STAILQ_REMOVE_HEAD(&s_hci_driver_util_env.tx_head, next); + btdm_osal_hw_exit_critical(0); + + *tx_data = &tx_entry->data_type; + s_hci_driver_util_env.cur_tx_entry = tx_entry; + s_hci_driver_util_env.cur_tx_off = 0; + tx_len = 1; + *last_frame = false; + } + + return tx_len; +} + +int +hci_driver_util_init(void) +{ + memset(&s_hci_driver_util_env, 0, sizeof(hci_driver_util_env_t)); + + if (hci_driver_util_memory_init()) { + return -1; + } + + STAILQ_INIT(&s_hci_driver_util_env.tx_head); + + return 0; +} + +void +hci_driver_util_deinit(void) +{ + hci_driver_util_tx_entry_t *tx_entry; + hci_driver_util_tx_entry_t *next_entry; + + /* Free all of controller buffers which haven't been sent yet. The whole mempool will be freed. + * Therefore, it's unnecessary to put the tx_entry into mempool. + */ + tx_entry = STAILQ_FIRST(&s_hci_driver_util_env.tx_head); + while (tx_entry) { + next_entry = STAILQ_NEXT(tx_entry, next); + if (tx_entry->data_type == HCI_DRIVER_TYPE_EVT) { + if (tx_entry->data_source == HCI_DRIVER_LE_EVT) { + r_ble_hci_trans_buf_free(tx_entry->data); + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else if (tx_entry->data_source == HCI_DRIVER_BREDR_EVT) { + bredr_hci_trans_evt_tx_done((hci_driver_packet_t *)tx_entry->data); + bredr_hci_trans_evt_free((hci_driver_packet_t *)tx_entry->data); + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + btdm_hci_trans_buf_free((hci_driver_packet_t *)tx_entry->data); + } + } else if (tx_entry->data_type == HCI_DRIVER_TYPE_ACL) { + if (tx_entry->data_source == HCI_DRIVER_LE_ACL) { + ble_mbuf_free_chain((struct ble_mbuf *)tx_entry->data); + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + bredr_hci_trans_acl_tx_done((hci_driver_packet_t *)tx_entry->data); + bredr_hci_trans_acl_free((hci_driver_packet_t *)tx_entry->data); + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + } else if (tx_entry->data_type == HCI_DRIVER_TYPE_ISO) { + free(tx_entry->data); + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + // SCO data + bredr_hci_trans_sync_tx_done((hci_driver_packet_t *)tx_entry->pkt); + bredr_hci_trans_sync_free((hci_driver_packet_t *)tx_entry->pkt); + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + + tx_entry = next_entry; + } + + hci_driver_util_memory_deinit(); + + memset(&s_hci_driver_util_env, 0, sizeof(hci_driver_util_env_t)); +} + + +void +hci_driver_util_assert_check(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2) +{ + ESP_LOGE(TAG, "hci driver assert: line %d in function %s, param: 0x%x, 0x%x", ln, fn, param1, param2); + assert(0); +} diff --git a/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart.c b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart.c new file mode 100644 index 0000000000..f608604df6 --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart.c @@ -0,0 +1,274 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_log.h" +#include "driver/uart.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "common/hci_driver_h4.h" +#include "common/hci_driver_util.h" +#include "common/hci_driver_mem.h" +#include "hci_driver_uart.h" + +static const char *TAG = "hci_uart"; + +#define CONFIG_BT_LE_HCI_RX_PROC_DATA_LEN (1024) + +typedef struct { + TaskHandle_t tx_task_handler; + TaskHandle_t rx_task_handler; + hci_driver_uart_params_config_t *hci_uart_params; + SemaphoreHandle_t tx_sem; + QueueHandle_t rx_event_queue; + uint8_t *rx_data; + struct hci_h4_sm *h4_sm; + hci_driver_forward_fn *forward_cb; +} hci_driver_uart_env_t; + +static hci_driver_uart_env_t s_hci_driver_uart_env; +static struct hci_h4_sm s_hci_driver_uart_h4_sm; +static uint8_t s_hci_driver_uart_rx_data[CONFIG_BT_LE_HCI_RX_PROC_DATA_LEN]; + +static int +hci_driver_uart_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + int rc; + uint8_t data_source; + + data_source = 0; + /* By now, this layer is only used by controller. */ + ESP_LOGD(TAG, "uart tx len:%d\n", length); + if (dir == HCI_DRIVER_DIR_BTDMC2H) { + if (data_type == HCI_DRIVER_TYPE_EVT) { + data_source = HCI_DRIVER_BTDM_EVT; + } + } else if (dir == HCI_DRIVER_DIR_LEC2H) { + if (data_type == HCI_DRIVER_TYPE_ACL) { + data_source = HCI_DRIVER_LE_ACL; + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + data_source = HCI_DRIVER_LE_EVT; + } else if (data_type == HCI_DRIVER_TYPE_ISO) { + data_source = HCI_DRIVER_LE_ISO; + } + } +#if UC_BTDM_CTRL_BR_EDR_IS_ENABLE + else if (dir == HCI_DRIVER_DIR_BREDRC2H) { + if (data_type == HCI_DRIVER_TYPE_ACL) { + data_source = HCI_DRIVER_BREDR_ACL; + } else if (data_type == HCI_DRIVER_TYPE_SYNC) { + data_source = HCI_DRIVER_BREDR_SYNC; + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + data_source = HCI_DRIVER_BREDR_EVT; + } + } +#endif // UC_BTDM_CTRL_BR_EDR_IS_ENABLE + else { + assert(0); + } + + rc = hci_driver_util_tx_list_enqueue(data_type, data, length, data_source); + if (rc < 0) { + ESP_LOGE(TAG, "tx data enqueue failed!\n"); + return rc; + } + + xSemaphoreGive(s_hci_driver_uart_env.tx_sem); + return rc; +} + +static int +hci_driver_uart_h4_frame_cb(uint8_t pkt_type, void *data, int pkt_len, uint8_t data_source) +{ + hci_driver_forward_fn *forward_cb = s_hci_driver_uart_env.forward_cb; + if (!forward_cb) { + ESP_LOGE(TAG, "rx cb is NULL\n"); + return -1; + } + + ESP_LOGD(TAG, "h4 frame\n"); + return forward_cb(pkt_type, data, pkt_len, HCI_DRIVER_DIR_H2C, data_source); +} + +static void +hci_driver_uart_tx_task(void *p) +{ + void *data; + bool last_frame; + uint32_t tx_len; + uart_port_t port; + + port = s_hci_driver_uart_env.hci_uart_params->hci_uart_port; + while (true) { + xSemaphoreTake(s_hci_driver_uart_env.tx_sem, portMAX_DELAY); + while (true) { + tx_len = hci_driver_util_tx_list_dequeue(0xffffff, &data, &last_frame); + if (tx_len == 0) { + break; + } + + ESP_LOGD(TAG, "uart tx"); + ESP_LOG_BUFFER_HEXDUMP(TAG, data, tx_len, ESP_LOG_DEBUG); + uart_write_bytes(port, data, tx_len); + } + } +} + +static void +hci_driver_uart_rx_task(void *p) +{ + void *data; + int read_len; + int ret; + uart_port_t port; + uart_event_t uart_event; + + port = s_hci_driver_uart_env.hci_uart_params->hci_uart_port; + while (true) { + xQueueReceive(s_hci_driver_uart_env.rx_event_queue, &uart_event, portMAX_DELAY); + data = s_hci_driver_uart_env.rx_data; + while (true) { + read_len = uart_read_bytes(port, data, CONFIG_BT_LE_HCI_RX_PROC_DATA_LEN, 0); + if (read_len == 0) { + break; + } + + ESP_LOGD(TAG, "uart rx read_len:%d\n", read_len); + ESP_LOG_BUFFER_HEXDUMP(TAG, data, read_len, ESP_LOG_DEBUG); + ret = hci_h4_sm_rx(s_hci_driver_uart_env.h4_sm, data, read_len); + if (ret < 0) { + ESP_LOGE(TAG, "parse rx data error! sm_state:%d\n", s_hci_driver_uart_env.h4_sm->state); + r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR); + } + } + } +} + +static int +hci_driver_uart_task_create(void) +{ + /* !TODO: Set the core id by menuconfig */ + xTaskCreatePinnedToCore(hci_driver_uart_tx_task, "hci_driver_uart_tx_task", + UC_BTDM_CTRL_HCI_TRANS_TASK_STACK_SIZE, NULL, + ESP_TASK_BT_CONTROLLER_PRIO, &s_hci_driver_uart_env.tx_task_handler, + 0); + assert(s_hci_driver_uart_env.tx_task_handler); + + xTaskCreatePinnedToCore(hci_driver_uart_rx_task, "hci_driver_uart_rx_task", + UC_BTDM_CTRL_HCI_TRANS_TASK_STACK_SIZE, NULL, + ESP_TASK_BT_CONTROLLER_PRIO, &s_hci_driver_uart_env.rx_task_handler, + 0); + assert(s_hci_driver_uart_env.rx_task_handler); + + ESP_LOGI(TAG, "hci transport task create successfully, prio:%d, stack size: %ld", + ESP_TASK_BT_CONTROLLER_PRIO, UC_BTDM_CTRL_HCI_TRANS_TASK_STACK_SIZE); + + return 0; +} + +static void +hci_driver_uart_task_delete(void) +{ + if (s_hci_driver_uart_env.tx_task_handler) { + vTaskDelete(s_hci_driver_uart_env.tx_task_handler); + s_hci_driver_uart_env.tx_task_handler = NULL; + } + + if (s_hci_driver_uart_env.rx_task_handler) { + vTaskDelete(s_hci_driver_uart_env.rx_task_handler); + s_hci_driver_uart_env.rx_task_handler = NULL; + } +} +static void +hci_driver_uart_deinit(void) +{ + hci_driver_uart_task_delete(); + + ESP_ERROR_CHECK(uart_driver_delete(s_hci_driver_uart_env.hci_uart_params->hci_uart_port)); + + if (s_hci_driver_uart_env.tx_sem) { + vSemaphoreDelete(s_hci_driver_uart_env.tx_sem); + } + + hci_driver_util_deinit(); + memset(&s_hci_driver_uart_env, 0, sizeof(hci_driver_uart_env_t)); +} + +static int +hci_driver_uart_init(hci_driver_forward_fn *cb) +{ + int rc; + memset(&s_hci_driver_uart_env, 0, sizeof(hci_driver_uart_env_t)); + + s_hci_driver_uart_env.h4_sm = &s_hci_driver_uart_h4_sm; + hci_h4_sm_init(s_hci_driver_uart_env.h4_sm, &s_hci_driver_mem_alloc, &s_hci_driver_mem_free, hci_driver_uart_h4_frame_cb); + + rc = hci_driver_util_init(); + if (rc) { + goto error; + } + + s_hci_driver_uart_env.tx_sem = xSemaphoreCreateBinary(); + if (!s_hci_driver_uart_env.tx_sem) { + goto error; + } + + s_hci_driver_uart_env.rx_data = s_hci_driver_uart_rx_data; + s_hci_driver_uart_env.forward_cb = cb; + s_hci_driver_uart_env.hci_uart_params = hci_driver_uart_config_param_get(); + hci_driver_uart_config(s_hci_driver_uart_env.hci_uart_params); + /* Currently, the queue size is set to 1. It will be considered as semaphore. */ + ESP_ERROR_CHECK(uart_driver_install(s_hci_driver_uart_env.hci_uart_params->hci_uart_port, + UC_BTDM_CTRL_HCI_UART_RX_BUFFER_SIZE, + UC_BTDM_CTRL_HCI_UART_TX_BUFFER_SIZE, + 1, &s_hci_driver_uart_env.rx_event_queue, + 0)); + + rc = hci_driver_uart_task_create(); + if (rc) { + goto error; + } + + return 0; + +error: + hci_driver_uart_deinit(); + return rc; +} + +int +hci_driver_uart_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin) +{ + int rc; + + hci_driver_uart_task_delete(); + hci_driver_uart_pin_update(tx_pin, rx_pin, cts_pin, rts_pin); + /* Currently, the queue size is set to 1. It will be considered as semaphore. */ + ESP_ERROR_CHECK(uart_driver_install(s_hci_driver_uart_env.hci_uart_params->hci_uart_port, + UC_BTDM_CTRL_HCI_UART_RX_BUFFER_SIZE, + UC_BTDM_CTRL_HCI_UART_TX_BUFFER_SIZE, + 1, &s_hci_driver_uart_env.rx_event_queue, + 0)); + rc = hci_driver_uart_task_create(); + if (rc) { + hci_driver_uart_task_delete(); + return -2; + } + + return 0; +} + +hci_driver_ops_t hci_driver_uart_ops = { + .hci_driver_tx = hci_driver_uart_tx, + .hci_driver_init = hci_driver_uart_init, + .hci_driver_deinit = hci_driver_uart_deinit, +}; diff --git a/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart.h b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart.h new file mode 100644 index 0000000000..5d5345c3da --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart.h @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "driver/uart.h" +#include "esp_bt.h" +#include "esp_hci_transport.h" + +/** + * @brief UART configuration parameters for the HCI driver + */ +typedef struct hci_driver_uart_params_config +{ + uint8_t hci_uart_port; /*!< Port of UART for HCI */ + uint8_t hci_uart_data_bits; /*!< Data bits of UART for HCI */ + uint8_t hci_uart_stop_bits; /*!< Stop bits of UART for HCI */ + uint8_t hci_uart_flow_ctrl; /*!< Flow control of UART for HCI */ + uint8_t hci_uart_parity; /*!< UART parity */ + uint8_t hci_uart_driver_mode; /*!< UART driver mode */ + uint32_t hci_uart_baud; /*!< Baudrate of UART for HCI */ + int hci_uart_tx_pin; /*!< Tx Pin number of UART for HCI */ + int hci_uart_rx_pin; /*!< Rx Pin number of UART for HCI */ + int hci_uart_rts_pin; /*!< RTS Pin number of UART for HCI */ + int hci_uart_cts_pin; /*!< CTS Pin number of UART for HCI */ +} hci_driver_uart_params_config_t; + +#define BT_HCI_DRIVER_UART_CONFIG_DEFAULT() { \ + .hci_uart_port = UC_BTDM_CTRL_HCI_UART_PORT, \ + .hci_uart_baud = UC_BTDM_CTRL_HCI_UART_BAUD, \ + .hci_uart_tx_pin = UC_BTDM_CTRL_HCI_UART_TX_PIN , \ + .hci_uart_rx_pin = UC_BTDM_CTRL_HCI_UART_RX_PIN, \ + .hci_uart_cts_pin = UC_BTDM_CTRL_HCI_UART_CTS_PIN, \ + .hci_uart_rts_pin = UC_BTDM_CTRL_HCI_UART_RTS_PIN, \ + .hci_uart_data_bits = UC_BTDM_CTRL_HCI_UART_DATA_BITS, \ + .hci_uart_stop_bits = UC_BTDM_CTRL_HCI_UART_STOP_BITS, \ + .hci_uart_flow_ctrl = UC_BTDM_CTRL_HCI_UART_FLOW_CTRL, \ + .hci_uart_parity = UC_BTDM_CTRL_HCI_UART_PARITY, \ +} + +/** + * @brief Configures the HCI driver UART parameters. + * This function sets up the UART interface according to the specified configuration parameters. + * + * @param uart_config A pointer to a structure containing the UART configuration parameters. + * The structure should include details such as baud rate, parity, stop bits, and flow control. + * Ensure that the uart_config structure is correctly initialized before calling this function. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + * + * @note This function should be called before any UART communication is initiated. + */ +int hci_driver_uart_config(hci_driver_uart_params_config_t *uart_config); + +/** + * @brief Update the UART pin configuration for the HCI driver. + * + * This function updates the TX, RX, CTS, and RTS pin assignments for the HCI driver operating over UART. + * It allows dynamic reconfiguration of UART pins as needed. + * + * @param tx_pin The GPIO number assigned to the UART TX pin. + * @param rx_pin The GPIO number assigned to the UART RX pin. + * @param cts_pin The GPIO number assigned to the UART CTS pin. + * @param rts_pin The GPIO number assigned to the UART RTS pin. + * + * @return 0 on success, or a negative error code on failure. + */ +int hci_driver_uart_pin_update(int tx_pin, int rx_pin, int cts_pin, int rts_pin); + +/** + * @brief Retrieves the current UART configuration parameters for the HCI driver. + * + * @return hci_driver_uart_params_config_t* Pointer to the structure with UART configuration parameters. + */ +hci_driver_uart_params_config_t * hci_driver_uart_config_param_get(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart_config.c b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart_config.c new file mode 100644 index 0000000000..04f3ccc6bd --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart_config.c @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "esp_log.h" +#include "driver/uart.h" +#include "hci_driver_uart.h" +#include "esp_private/esp_gpio_reserve.h" + +static const char *TAG = "hci_uart_config"; +static uart_config_t s_uart_cfg; +static hci_driver_uart_params_config_t s_hci_driver_uart_params = BT_HCI_DRIVER_UART_CONFIG_DEFAULT(); + +int hci_driver_uart_config(hci_driver_uart_params_config_t *uart_config) +{ + uart_config_t *uart_cfg; + uart_cfg = &s_uart_cfg; + uart_cfg->baud_rate = uart_config->hci_uart_baud; + uart_cfg->data_bits = uart_config->hci_uart_data_bits; + uart_cfg->stop_bits = uart_config->hci_uart_stop_bits; + uart_cfg->parity = uart_config->hci_uart_parity; + uart_cfg->flow_ctrl = uart_config->hci_uart_flow_ctrl; + uart_cfg->source_clk= UART_SCLK_DEFAULT; + uart_cfg->rx_flow_ctrl_thresh = UART_HW_FIFO_LEN(uart_config->hci_uart_port) - 1; + + ESP_LOGI(TAG,"set uart pin tx:%d, rx:%d.\n", uart_config->hci_uart_tx_pin, uart_config->hci_uart_rx_pin); + ESP_LOGI(TAG,"set rts:%d, cts:%d.\n", uart_config->hci_uart_rts_pin, uart_config->hci_uart_cts_pin); + ESP_LOGI(TAG,"set baud_rate:%d.\n", uart_config->hci_uart_baud); + ESP_LOGI(TAG,"set flow_ctrl:%d.\n", uart_config->hci_uart_flow_ctrl); + + ESP_ERROR_CHECK(uart_driver_delete(uart_config->hci_uart_port)); + ESP_ERROR_CHECK(uart_param_config(uart_config->hci_uart_port, uart_cfg)); + ESP_ERROR_CHECK(uart_set_pin(uart_config->hci_uart_port, uart_config->hci_uart_tx_pin, uart_config->hci_uart_rx_pin, + uart_config->hci_uart_rts_pin, uart_config->hci_uart_cts_pin)); + return 0; +} + +int +hci_driver_uart_pin_update(int tx_pin, int rx_pin, int cts_pin, int rts_pin) +{ + hci_driver_uart_params_config_t *uart_param = &s_hci_driver_uart_params; + /* Fixed warning that the gpio is not usable, may be used by others */ + esp_gpio_revoke(BIT64(uart_param->hci_uart_tx_pin)); + esp_gpio_revoke(BIT64(uart_param->hci_uart_rx_pin)); + if (uart_param->hci_uart_cts_pin != -1) { + esp_gpio_revoke(BIT64(uart_param->hci_uart_cts_pin)); + } + + if (uart_param->hci_uart_rts_pin != -1) { + esp_gpio_revoke(BIT64(uart_param->hci_uart_rts_pin)); + } + + uart_param->hci_uart_tx_pin = tx_pin; + uart_param->hci_uart_rx_pin = rx_pin; + uart_param->hci_uart_rts_pin = rts_pin; + uart_param->hci_uart_cts_pin = cts_pin; + return hci_driver_uart_config(uart_param); +} + +hci_driver_uart_params_config_t * +hci_driver_uart_config_param_get(void) +{ + return &s_hci_driver_uart_params; +} diff --git a/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart_dma.c b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart_dma.c new file mode 100644 index 0000000000..c158ae7a70 --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/uart/hci_driver_uart_dma.c @@ -0,0 +1,714 @@ +/* + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_log.h" +#include "driver/uart.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "common/hci_driver_h4.h" +#include "common/hci_driver_util.h" +#include "common/hci_driver_mem.h" +#include "hci_driver_uart.h" + +#include "ble_hci_trans.h" +#include "esp_private/periph_ctrl.h" +#include "esp_private/gdma.h" +#include "hal/uhci_ll.h" + +/* + * UART DMA Desc struct + * + * -------------------------------------------------------------- + * | own | EoF | sub_sof | 5'b0 | length [11:0] | size [11:0] | + * -------------------------------------------------------------- + * | buf_ptr [31:0] | + * -------------------------------------------------------------- + * | next_desc_ptr [31:0] | + * -------------------------------------------------------------- + */ + +/* this bitfield is start from the LSB!!! */ +typedef struct uhci_lldesc_s { + volatile uint32_t size : 12, + length: 12, + offset: 5, /* h/w reserved 5bit, s/w use it as offset in buffer */ + sosf : 1, /* start of sub-frame */ + eof : 1, /* end of frame */ + owner : 1; /* hw or sw */ + volatile const uint8_t *buf; /* point to buffer data */ + union { + volatile uint32_t empty; + STAILQ_ENTRY(uhci_lldesc_s) qe; /* pointing to the next desc */ + }; +} uhci_lldesc_t; + +/** + * @brief Enumeration of HCI transport transmission states. + */ +typedef enum { + HCI_TRANS_TX_IDLE, ///< HCI Transport TX is in idle state. + HCI_TRANS_TX_START, ///< HCI Transport TX is starting transmission. + HCI_TRANS_TX_END, ///< HCI Transport TX has completed transmission. +} hci_trans_tx_state_t; + +typedef struct { + TaskHandle_t task_handler; + hci_driver_uart_params_config_t *hci_uart_params; + SemaphoreHandle_t process_sem; + struct hci_h4_sm *h4_sm; + hci_driver_forward_fn *forward_cb; + struct os_mempool *hci_rx_data_pool; /*!< Init a memory pool for rx_data cache */ + uint8_t *hci_rx_data_buffer; + struct os_mempool *hci_rxinfo_pool; /*!< Init a memory pool for rxinfo cache */ + os_membuf_t *hci_rxinfo_buffer; + volatile bool rxinfo_mem_exhausted; /*!< Indicate rxinfo memory does not exist */ + volatile bool is_continue_rx; /*!< Continue to rx */ + volatile hci_trans_tx_state_t hci_tx_state; /*!< HCI Tx State */ + struct os_mempool lldesc_mem_pool;/*!< Init a memory pool for uhci_lldesc_t */ + uhci_lldesc_t *lldesc_mem; +} hci_driver_uart_dma_env_t; + +#define ESP_BT_HCI_TL_STATUS_OK (0) /*!< HCI_TL Tx/Rx operation status OK */ +/* The number of lldescs pool */ +#define HCI_LLDESCS_POOL_NUM (UC_BT_CTRL_HCI_LLDESCS_POOL_NUM) +/* Default block size for HCI RX data */ +#define HCI_RX_DATA_POOL_NUM (UC_BT_CTRL_HCI_TRANS_RX_MEM_NUM) +#define HCI_RX_INFO_POOL_NUM (UC_BT_CTRL_HCI_TRANS_RX_MEM_NUM + 1) +#if UC_BT_CTRL_BLE_IS_ENABLE +#define HCI_RX_DATA_BLOCK_SIZE (DEFAULT_BT_LE_ACL_BUF_SIZE + BLE_HCI_TRANS_CMD_SZ) +#else +#define HCI_RX_DATA_BLOCK_SIZE (1024) +#endif + +/** + * @brief callback function for HCI Transport Layer send/receive operations + */ +typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); + +struct uart_txrxchannel { + esp_bt_hci_tl_callback_t callback; + void *arg; + uhci_lldesc_t *link_head; +}; + +struct uart_env_tag { + struct uart_txrxchannel tx; + struct uart_txrxchannel rx; +}; + +typedef struct hci_message { + void *ptr; ///< Pointer to the message data. + uint32_t length; ///< Length of the message data. + STAILQ_ENTRY(hci_message) next; ///< Next element in the linked list. +} hci_message_t; + +static void hci_driver_uart_dma_recv_async(uint8_t *buf, uint32_t size, esp_bt_hci_tl_callback_t callback, void *arg); +int hci_driver_uart_dma_rx_start(uint8_t *rx_data, uint32_t length); +int hci_driver_uart_dma_tx_start(esp_bt_hci_tl_callback_t callback, void *arg); + +static const char *TAG = "uart_dma"; +static hci_driver_uart_dma_env_t s_hci_driver_uart_dma_env; +static struct hci_h4_sm s_hci_driver_uart_h4_sm; + +/* The list for hci_rx_data */ +STAILQ_HEAD(g_hci_rxinfo_list, hci_message); + +DRAM_ATTR struct g_hci_rxinfo_list g_hci_rxinfo_head; +static DRAM_ATTR struct uart_env_tag uart_env; +static volatile uhci_dev_t *s_uhci_hw = &UHCI0; +static DRAM_ATTR gdma_channel_handle_t s_rx_channel; +static DRAM_ATTR gdma_channel_handle_t s_tx_channel; + +static int hci_driver_uart_dma_memory_deinit(void) +{ + + if (s_hci_driver_uart_dma_env.hci_rxinfo_buffer) { + free(s_hci_driver_uart_dma_env.hci_rxinfo_buffer); + s_hci_driver_uart_dma_env.hci_rxinfo_buffer = NULL; + } + + if (s_hci_driver_uart_dma_env.hci_rxinfo_pool) { + free(s_hci_driver_uart_dma_env.hci_rxinfo_pool); + s_hci_driver_uart_dma_env.hci_rxinfo_pool = NULL; + } + + if (s_hci_driver_uart_dma_env.hci_rx_data_buffer) { + free(s_hci_driver_uart_dma_env.hci_rx_data_buffer); + s_hci_driver_uart_dma_env.hci_rx_data_buffer = NULL; + } + + if (s_hci_driver_uart_dma_env.hci_rx_data_pool) { + free(s_hci_driver_uart_dma_env.hci_rx_data_pool); + s_hci_driver_uart_dma_env.hci_rx_data_pool = NULL; + } + + if (s_hci_driver_uart_dma_env.lldesc_mem) { + free(s_hci_driver_uart_dma_env.lldesc_mem); + s_hci_driver_uart_dma_env.lldesc_mem = NULL; + } + + return 0; +} + +static int hci_driver_uart_dma_memory_init(void) +{ + int rc = 0; + + s_hci_driver_uart_dma_env.lldesc_mem = malloc(OS_MEMPOOL_SIZE(HCI_LLDESCS_POOL_NUM, + sizeof (uhci_lldesc_t)) * sizeof(os_membuf_t)); + if (!s_hci_driver_uart_dma_env.lldesc_mem) { + return -1; + } + + rc = os_mempool_init(&s_hci_driver_uart_dma_env.lldesc_mem_pool, HCI_LLDESCS_POOL_NUM, + sizeof (uhci_lldesc_t), s_hci_driver_uart_dma_env.lldesc_mem, "hci_lldesc_pool"); + if (rc) { + goto init_err; + } + + s_hci_driver_uart_dma_env.hci_rx_data_pool = (struct os_mempool *)malloc(sizeof(struct os_mempool)); + if (!s_hci_driver_uart_dma_env.hci_rx_data_pool) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rx_data_pool, 0, sizeof(struct os_mempool)); + s_hci_driver_uart_dma_env.hci_rx_data_buffer = malloc(OS_MEMPOOL_SIZE(HCI_RX_DATA_POOL_NUM, + HCI_RX_DATA_BLOCK_SIZE) * sizeof(os_membuf_t)); + if (!s_hci_driver_uart_dma_env.hci_rx_data_buffer) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rx_data_buffer, 0, OS_MEMPOOL_SIZE(HCI_RX_DATA_POOL_NUM, + HCI_RX_DATA_BLOCK_SIZE) * sizeof(os_membuf_t)); + rc = os_mempool_init(s_hci_driver_uart_dma_env.hci_rx_data_pool, HCI_RX_DATA_POOL_NUM, + HCI_RX_DATA_BLOCK_SIZE, s_hci_driver_uart_dma_env.hci_rx_data_buffer, + "hci_rx_data_pool"); + if (rc) { + goto init_err; + } + + + /* Malloc hci rxinfo pool */ + s_hci_driver_uart_dma_env.hci_rxinfo_pool = (struct os_mempool *)malloc(sizeof(struct os_mempool)); + if (!s_hci_driver_uart_dma_env.hci_rxinfo_pool) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rxinfo_pool, 0, sizeof(struct os_mempool)); + s_hci_driver_uart_dma_env.hci_rxinfo_buffer = malloc(OS_MEMPOOL_SIZE(HCI_RX_INFO_POOL_NUM, + sizeof(hci_message_t)) * sizeof(os_membuf_t)); + if (!s_hci_driver_uart_dma_env.hci_rxinfo_buffer) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rxinfo_buffer, 0, OS_MEMPOOL_SIZE(HCI_RX_INFO_POOL_NUM, + sizeof(hci_message_t)) * sizeof(os_membuf_t)); + rc = os_mempool_init(s_hci_driver_uart_dma_env.hci_rxinfo_pool, HCI_RX_INFO_POOL_NUM, + sizeof(hci_message_t), s_hci_driver_uart_dma_env.hci_rxinfo_buffer, + "hci_rxinfo_pool"); + if (rc) { + goto init_err; + } + + return rc; +init_err: + hci_driver_uart_dma_memory_deinit(); + return rc; +} + +static IRAM_ATTR bool hci_uart_tl_rx_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) +{ + esp_bt_hci_tl_callback_t callback = uart_env.rx.callback; + void *arg = uart_env.rx.arg; + assert(dma_chan == s_rx_channel); + assert(uart_env.rx.callback != NULL); + // clear callback pointer + uart_env.rx.callback = NULL; + uart_env.rx.arg = NULL; + // call handler + callback(arg, ESP_BT_HCI_TL_STATUS_OK); + return true; +} + +static IRAM_ATTR bool hci_uart_tl_tx_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) +{ + esp_bt_hci_tl_callback_t callback = uart_env.tx.callback; + assert(dma_chan == s_tx_channel); + assert(uart_env.tx.callback != NULL); + // clear callback pointer + uart_env.tx.callback = NULL; + // call handler + callback(uart_env.tx.arg, ESP_BT_HCI_TL_STATUS_OK); + uart_env.tx.arg = NULL; + return true; +} + +uint8_t * IRAM_ATTR hci_driver_uart_dma_rxdata_memory_get(void) +{ + uint8_t *rx_data; + rx_data = os_memblock_get(s_hci_driver_uart_dma_env.hci_rx_data_pool); + return rx_data; +} + +hci_message_t * IRAM_ATTR hci_driver_uart_dma_rxinfo_memory_get(void) +{ + hci_message_t *rx_info; + rx_info = os_memblock_get(s_hci_driver_uart_dma_env.hci_rxinfo_pool); + return rx_info; +} + +void IRAM_ATTR hci_driver_uart_dma_cache_rxinfo(hci_message_t *hci_rxinfo) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_TAIL(&g_hci_rxinfo_head, hci_rxinfo, next); + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_continue_rx_enable(bool enable) +{ + os_sr_t sr; + OS_ENTER_CRITICAL(sr); + s_hci_driver_uart_dma_env.is_continue_rx = enable; + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_rxinfo_mem_exhausted_set(bool is_exhausted) +{ + os_sr_t sr; + OS_ENTER_CRITICAL(sr); + s_hci_driver_uart_dma_env.rxinfo_mem_exhausted = is_exhausted; + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_recv_callback(void *arg, uint8_t status) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + hci_message_t *hci_rxinfo; + uint8_t *rx_data; + + if (s_hci_driver_uart_dma_env.rxinfo_mem_exhausted) { + ESP_LOGE(TAG, "Will lost rx data, need adjust rxinfo memory count\n"); + assert(0); + } + + hci_rxinfo = hci_driver_uart_dma_rxinfo_memory_get(); + if (!hci_rxinfo) { + ESP_LOGW(TAG, "set rxinfo mem exhausted flag\n"); + hci_driver_uart_dma_rxinfo_mem_exhausted_set(true); + xSemaphoreGiveFromISR(s_hci_driver_uart_dma_env.process_sem, &xHigherPriorityTaskWoken); + return; + } + + hci_rxinfo->ptr = (void *)uart_env.rx.link_head->buf; + hci_rxinfo->length = uart_env.rx.link_head->length; + hci_driver_uart_dma_cache_rxinfo(hci_rxinfo); + xSemaphoreGiveFromISR(s_hci_driver_uart_dma_env.process_sem, &xHigherPriorityTaskWoken); + rx_data = hci_driver_uart_dma_rxdata_memory_get(); + if (!rx_data) { + hci_driver_uart_dma_continue_rx_enable(true); + }else { + hci_driver_uart_dma_rx_start(rx_data, HCI_RX_DATA_BLOCK_SIZE); + } +} + +void IRAM_ATTR hci_driver_uart_dma_txstate_set(hci_trans_tx_state_t tx_state) +{ + os_sr_t sr; + OS_ENTER_CRITICAL(sr); + s_hci_driver_uart_dma_env.hci_tx_state = tx_state; + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_send_callback(void *arg, uint8_t status) +{ + uhci_lldesc_t *lldesc_head; + uhci_lldesc_t *lldesc_nxt; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + lldesc_head = uart_env.tx.link_head; + while (lldesc_head) { + lldesc_nxt = lldesc_head->qe.stqe_next; + os_memblock_put(&s_hci_driver_uart_dma_env.lldesc_mem_pool, lldesc_head); + lldesc_head = lldesc_nxt; + } + + uart_env.tx.link_head = NULL; + hci_driver_uart_dma_txstate_set(HCI_TRANS_TX_IDLE); + xSemaphoreGiveFromISR(s_hci_driver_uart_dma_env.process_sem, &xHigherPriorityTaskWoken); +} + +static IRAM_ATTR void hci_driver_uart_dma_recv_async(uint8_t *buf, uint32_t size, esp_bt_hci_tl_callback_t callback, void *arg) +{ + uhci_lldesc_t *lldesc_head; + assert(buf != NULL); + assert(size != 0); + assert(callback != NULL); + uart_env.rx.callback = callback; + uart_env.rx.arg = arg; + lldesc_head = uart_env.rx.link_head; + + while (lldesc_head) { + os_memblock_put(&s_hci_driver_uart_dma_env.lldesc_mem_pool, lldesc_head), + lldesc_head = lldesc_head->qe.stqe_next; + } + + uart_env.rx.link_head = NULL; + lldesc_head = os_memblock_get(&s_hci_driver_uart_dma_env.lldesc_mem_pool); + assert(lldesc_head); + memset(lldesc_head, 0, sizeof(uhci_lldesc_t)); + lldesc_head->buf = buf; + lldesc_head->size = size; + lldesc_head->eof = 0; + s_uhci_hw->pkt_thres.pkt_thrs = size; + uart_env.rx.link_head = lldesc_head; + gdma_start(s_rx_channel, (intptr_t)(uart_env.rx.link_head)); +} + +int IRAM_ATTR hci_driver_uart_dma_rx_start(uint8_t *rx_data, uint32_t length) +{ + hci_driver_uart_dma_recv_async(rx_data, length, hci_driver_uart_dma_recv_callback, NULL); + return 0; +} + +int hci_driver_uart_dma_tx_start(esp_bt_hci_tl_callback_t callback, void *arg) +{ + void *data; + bool last_frame; + bool head_is_setted; + uint32_t tx_len; + uhci_lldesc_t *lldesc_data; + uhci_lldesc_t *lldesc_head; + uhci_lldesc_t *lldesc_tail; + + lldesc_head = NULL; + lldesc_tail = NULL; + head_is_setted = false; + last_frame = false; + while (true) { + // The length in DMA is 12 bits + tx_len = hci_driver_util_tx_list_dequeue(0xfff, &data, &last_frame); + if (!tx_len) { + break; + } + + lldesc_data = os_memblock_get(&s_hci_driver_uart_dma_env.lldesc_mem_pool); + /* According to the current processing logic, It should not be empty */ + assert(lldesc_data); + memset(lldesc_data, 0, sizeof(uhci_lldesc_t)); + lldesc_data->length = tx_len; + lldesc_data->buf = data; + lldesc_data->eof = 0; + if (!head_is_setted) { + lldesc_head = lldesc_data; + head_is_setted = true; + } else { + lldesc_tail->qe.stqe_next = lldesc_data; + } + + lldesc_tail = lldesc_data; + if (last_frame) { + break; + } + } + + if (lldesc_head) { + lldesc_tail->eof = 1; + uart_env.tx.link_head = lldesc_head; + uart_env.tx.callback = callback; + uart_env.tx.arg = arg; + /* The DMA interrupt may have been triggered before setting the tx_state, + * So we set it first. + */ + hci_driver_uart_dma_txstate_set(HCI_TRANS_TX_START); + gdma_start(s_tx_channel, (intptr_t)(uart_env.tx.link_head)); + return 0; + } else { + return -1; + } +} + +static void hci_driver_uart_dma_install(void) +{ +#if __PERIPH_CTRL_DEPRECATE_ATTR + periph_module_enable(PERIPH_UHCI0_MODULE); + periph_module_reset(PERIPH_UHCI0_MODULE); +#else + PERIPH_RCC_ATOMIC() { + uhci_ll_enable_bus_clock(1); + uhci_ll_reset_register(); + } +#endif + + // install DMA driver + gdma_channel_alloc_config_t tx_channel_config = { + .flags.reserve_sibling = 1, + .direction = GDMA_CHANNEL_DIRECTION_TX, + }; + + ESP_ERROR_CHECK(gdma_new_ahb_channel(&tx_channel_config, &s_tx_channel)); + gdma_channel_alloc_config_t rx_channel_config = { + .direction = GDMA_CHANNEL_DIRECTION_RX, + .sibling_chan = s_tx_channel, + }; + + ESP_ERROR_CHECK(gdma_new_ahb_channel(&rx_channel_config, &s_rx_channel)); + gdma_connect(s_tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0)); + gdma_connect(s_rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0)); + gdma_strategy_config_t strategy_config = { + .auto_update_desc = false, + .owner_check = false + }; + + ESP_ERROR_CHECK(gdma_apply_strategy(s_tx_channel, &strategy_config)); + ESP_ERROR_CHECK(gdma_apply_strategy(s_rx_channel, &strategy_config)); + gdma_rx_event_callbacks_t rx_cbs = { + .on_recv_eof = hci_uart_tl_rx_eof_callback + }; + + ESP_ERROR_CHECK(gdma_register_rx_event_callbacks(s_rx_channel, &rx_cbs, NULL)); + gdma_tx_event_callbacks_t tx_cbs = { + .on_trans_eof = hci_uart_tl_tx_eof_callback + }; + + ESP_ERROR_CHECK(gdma_register_tx_event_callbacks(s_tx_channel, &tx_cbs, NULL)); + + // configure UHCI + uhci_ll_init((uhci_dev_t *)s_uhci_hw); + // uhci_ll_set_eof_mode((uhci_dev_t *)s_uhci_hw, UHCI_RX_LEN_EOF); + uhci_ll_set_eof_mode((uhci_dev_t *)s_uhci_hw, UHCI_RX_IDLE_EOF); + // disable software flow control + s_uhci_hw->escape_conf.val = 0; + uhci_ll_attach_uart_port((uhci_dev_t *)s_uhci_hw, s_hci_driver_uart_dma_env.hci_uart_params->hci_uart_port); +} + +static int +hci_driver_uart_dma_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + uint8_t data_source; + int rc; + + data_source = 0; + /* By now, this layer is only used by controller. */ + ESP_LOGD(TAG, "dma tx len:%d\n", length); + if (dir == HCI_DRIVER_DIR_BTDMC2H) { + if (data_type == HCI_DRIVER_TYPE_EVT) { + data_source = HCI_DRIVER_BTDM_EVT; + } + } else if (dir == HCI_DRIVER_DIR_LEC2H) { + if (data_type == HCI_DRIVER_TYPE_ACL) { + data_source = HCI_DRIVER_LE_ACL; + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + data_source = HCI_DRIVER_LE_EVT; + } else if (data_type == HCI_DRIVER_TYPE_ISO) { + data_source = HCI_DRIVER_LE_ISO; + } + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else if (dir == HCI_DRIVER_DIR_BREDRC2H) { + if (data_type == HCI_DRIVER_TYPE_ACL) { + data_source = HCI_DRIVER_BREDR_ACL; + } else if (data_type == HCI_DRIVER_TYPE_SYNC) { + data_source = HCI_DRIVER_BREDR_SYNC; + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + data_source = HCI_DRIVER_BREDR_EVT; + } + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + assert(0); + } + + rc = hci_driver_util_tx_list_enqueue(data_type, data, length, data_source); + if (rc < 0) { + ESP_LOGE(TAG, "dma tx data enqueue failed!\n"); + return rc; + } + + xSemaphoreGive(s_hci_driver_uart_dma_env.process_sem); + return rc; +} + +static int +hci_driver_uart_dma_h4_frame_cb(uint8_t pkt_type, void *data, int pkt_len, uint8_t data_source) +{ + hci_driver_forward_fn *forward_cb = s_hci_driver_uart_dma_env.forward_cb; + if (!forward_cb) { + ESP_LOGW(TAG, "rx cb is NULL\n"); + return -1; + } + + ESP_LOGD(TAG, "h4 frame\n"); + return forward_cb(pkt_type, data, pkt_len, HCI_DRIVER_DIR_H2C, data_source); +} + +static void +hci_driver_uart_dma_process_task(void *p) +{ + hci_message_t *rxinfo_container; + os_sr_t sr; + int ret; + uint8_t* rx_data; + uint32_t rx_len; + + while (true) { + xSemaphoreTake(s_hci_driver_uart_dma_env.process_sem, portMAX_DELAY); + ESP_LOGD(TAG, "task run:%d\n",s_hci_driver_uart_dma_env.hci_tx_state); + /* Process Tx data */ + if (s_hci_driver_uart_dma_env.hci_tx_state == HCI_TRANS_TX_IDLE) { + hci_driver_uart_dma_tx_start(hci_driver_uart_dma_send_callback, (void*)&uart_env); + } + + if (s_hci_driver_uart_dma_env.rxinfo_mem_exhausted) { + rx_data = (void *)uart_env.rx.link_head->buf; + rx_len = uart_env.rx.link_head->length; + ESP_LOGD(TAG, "rxinfo exhausted:"); + ESP_LOG_BUFFER_HEXDUMP(TAG, rx_data, rx_len, ESP_LOG_DEBUG); + ret = hci_h4_sm_rx(s_hci_driver_uart_dma_env.h4_sm, rx_data, rx_len); + hci_driver_uart_dma_rx_start(rx_data, HCI_RX_DATA_BLOCK_SIZE); + hci_driver_uart_dma_rxinfo_mem_exhausted_set(false); + if (ret < 0) { + ESP_LOGW(TAG, "parse rx data error!\n"); + r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR); + } + } + + while (!STAILQ_EMPTY(&g_hci_rxinfo_head)) { + OS_ENTER_CRITICAL(sr); + rxinfo_container = STAILQ_FIRST(&g_hci_rxinfo_head); + STAILQ_REMOVE_HEAD(&g_hci_rxinfo_head, next); + OS_EXIT_CRITICAL(sr); + + rx_data = rxinfo_container->ptr; + rx_len = rxinfo_container->length; + ESP_LOGD(TAG, "uart rx"); + ESP_LOG_BUFFER_HEXDUMP(TAG, rx_data, rx_len, ESP_LOG_DEBUG); + ret = hci_h4_sm_rx(s_hci_driver_uart_dma_env.h4_sm, rx_data, rx_len); + if (ret < 0) { + ESP_LOGW(TAG, "parse rx data error!\n"); + r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR); + } + + os_memblock_put(s_hci_driver_uart_dma_env.hci_rxinfo_pool, rxinfo_container); + /* No need to enter CRITICAL */ + if (s_hci_driver_uart_dma_env.is_continue_rx) { + /* We should set continux rx flag first, RX interrupted may happened when rx start soon */ + hci_driver_uart_dma_continue_rx_enable(false); + hci_driver_uart_dma_rx_start(rx_data, HCI_RX_DATA_BLOCK_SIZE); + } else { + os_memblock_put(s_hci_driver_uart_dma_env.hci_rx_data_pool, rx_data); + } + } + } +} + +static int +hci_driver_uart_dma_task_create(void) +{ + /* !TODO: Set the core id by menuconfig */ + xTaskCreatePinnedToCore(hci_driver_uart_dma_process_task, "hci_driver_uart_dma_process_task", + UC_BT_CTRL_HCI_TRANS_TASK_STACK_SIZE, NULL, + ESP_TASK_BT_CONTROLLER_PRIO, &s_hci_driver_uart_dma_env.task_handler, + 0); + assert(s_hci_driver_uart_dma_env.task_handler); + + ESP_LOGI(TAG, "hci transport task create successfully, prio:%d, stack size: %ld", + ESP_TASK_BT_CONTROLLER_PRIO, UC_BT_CTRL_HCI_TRANS_TASK_STACK_SIZE); + + return 0; +} + + +static void +hci_driver_uart_dma_deinit(void) +{ + if (s_hci_driver_uart_dma_env.task_handler) { + vTaskDelete(s_hci_driver_uart_dma_env.task_handler); + s_hci_driver_uart_dma_env.task_handler = NULL; + } + + ESP_ERROR_CHECK(uart_driver_delete(s_hci_driver_uart_dma_env.hci_uart_params->hci_uart_port)); + hci_driver_uart_dma_memory_deinit(); + if (!s_hci_driver_uart_dma_env.process_sem) { + vSemaphoreDelete(s_hci_driver_uart_dma_env.process_sem); + } + + hci_driver_util_deinit(); + memset(&s_hci_driver_uart_dma_env, 0, sizeof(hci_driver_uart_dma_env_t)); +} + + +static int +hci_driver_uart_dma_init(hci_driver_forward_fn *cb) +{ + int rc; + + memset(&s_hci_driver_uart_dma_env, 0, sizeof(hci_driver_uart_dma_env_t)); + + s_hci_driver_uart_dma_env.h4_sm = &s_hci_driver_uart_h4_sm; + hci_h4_sm_init(s_hci_driver_uart_dma_env.h4_sm, &s_hci_driver_mem_alloc, &s_hci_driver_mem_free, hci_driver_uart_dma_h4_frame_cb); + + rc = hci_driver_util_init(); + if (rc) { + goto error; + } + + s_hci_driver_uart_dma_env.process_sem = xSemaphoreCreateBinary(); + if (!s_hci_driver_uart_dma_env.process_sem) { + goto error; + } + + rc = hci_driver_uart_dma_memory_init(); + if (rc) { + goto error; + } + + s_hci_driver_uart_dma_env.forward_cb = cb; + s_hci_driver_uart_dma_env.hci_uart_params = hci_driver_uart_config_param_get(); + hci_driver_uart_config(s_hci_driver_uart_dma_env.hci_uart_params); + + ESP_LOGI(TAG, "uart attach uhci!"); + hci_driver_uart_dma_install(); + + STAILQ_INIT(&g_hci_rxinfo_head); + + rc = hci_driver_uart_dma_task_create(); + if (rc) { + goto error; + } + + s_hci_driver_uart_dma_env.hci_tx_state = HCI_TRANS_TX_IDLE; + s_hci_driver_uart_dma_env.rxinfo_mem_exhausted = false; + s_hci_driver_uart_dma_env.is_continue_rx = false; + hci_driver_uart_dma_rx_start(os_memblock_get(s_hci_driver_uart_dma_env.hci_rx_data_pool), + HCI_RX_DATA_BLOCK_SIZE); + return 0; + +error: + hci_driver_uart_dma_deinit(); + return rc; +} + +int +hci_driver_uart_dma_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin) +{ + return hci_driver_uart_pin_update(tx_pin, rx_pin, cts_pin, rts_pin); +} + + +hci_driver_ops_t hci_driver_uart_dma_ops = { + .hci_driver_tx = hci_driver_uart_dma_tx, + .hci_driver_init = hci_driver_uart_dma_init, + .hci_driver_deinit = hci_driver_uart_dma_deinit, +}; diff --git a/components/bt/porting_btdm/transport/driver/vhci/hci_driver_nimble.c b/components/bt/porting_btdm/transport/driver/vhci/hci_driver_nimble.c new file mode 100644 index 0000000000..80adca189d --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/vhci/hci_driver_nimble.c @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_hci_driver.h" +#include "esp_hci_internal.h" + +typedef struct { + hci_driver_forward_fn *forward_cb; + hci_driver_host_recv_fn *host_recv_cb; +} hci_driver_vhci_env_t; + +static hci_driver_vhci_env_t s_hci_driver_vhci_env; + +static int +hci_driver_vhci_host_recv(hci_driver_data_type_t type, uint8_t *data, uint16_t len) +{ + static hci_driver_host_recv_fn *host_recv_cb; + + host_recv_cb = s_hci_driver_vhci_env.host_recv_cb; + if (host_recv_cb) { + return host_recv_cb(type, data, len); + } + + return -1; +} + +static int +hci_driver_vhci_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ +#if 1 + hci_driver_packet_t *pkt; + + if (dir == HCI_DRIVER_DIR_BTDMC2H) { + uint8_t *hci_evt = r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD); + assert(hci_evt); + pkt = (hci_driver_packet_t *)data; + memcpy(hci_evt, pkt->data, length); + btdm_hci_trans_buf_free(pkt); + data = hci_evt; + } +#endif + return hci_driver_vhci_host_recv(data_type, data, length); +} + +static int +hci_driver_vhci_init(hci_driver_forward_fn *cb) +{ + s_hci_driver_vhci_env.forward_cb = cb; + return 0; +} + +static void +hci_driver_vhci_deinit(void) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); +} + +hci_driver_ops_t hci_driver_vhci_ops = { + .hci_driver_tx = hci_driver_vhci_tx, + .hci_driver_init = hci_driver_vhci_init, + .hci_driver_deinit = hci_driver_vhci_deinit, +}; + +/* Special APIs used by host to send message. */ +int +hci_driver_host_cmd_tx(uint8_t *data, uint32_t length) +{ +#if 0 + hci_driver_packet_t *pkt = NULL; + uint16_t pkt_len; + + pkt_len = data[2] + 3; + pkt = btdm_hci_trans_buf_alloc(HCI_DRIVER_TYPE_CMD, 0); + assert(pkt); + pkt->type = HCI_DRIVER_TYPE_CMD; + pkt->length = pkt_len; + memcpy(pkt->data, &data[0], pkt_len); + r_ble_hci_trans_buf_free(data); + return s_hci_driver_vhci_env.forward_cb(HCI_DRIVER_TYPE_CMD, (uint8_t *)pkt, pkt_len, HCI_DRIVER_DIR_H2C, HCI_DRIVER_CMD); +#else + return s_hci_driver_vhci_env.forward_cb(HCI_DRIVER_TYPE_CMD, data, length, HCI_DRIVER_DIR_H2C, HCI_DRIVER_CMD); +#endif +} + +int +hci_driver_host_acl_tx(uint8_t *data, uint32_t length) +{ + return s_hci_driver_vhci_env.forward_cb(HCI_DRIVER_TYPE_ACL, data, length, HCI_DRIVER_DIR_H2C, HCI_DRIVER_LE_ACL); +} + +#if CONFIG_BT_LE_ISO_SUPPORT +int +hci_driver_host_iso_tx(uint8_t *data, uint32_t length) +{ + return s_hci_driver_vhci_env.forward_cb(HCI_DRIVER_TYPE_ISO, data, length, HCI_DRIVER_DIR_H2C, HCI_DRIVER_LE_ISO); +} +#endif // CONFIG_BT_LE_ISO_SUPPORT + +int +hci_driver_host_callback_register(hci_driver_host_recv_fn *callback) +{ + s_hci_driver_vhci_env.host_recv_cb = callback; + return 0; +} diff --git a/components/bt/porting_btdm/transport/driver/vhci/hci_driver_standard.c b/components/bt/porting_btdm/transport/driver/vhci/hci_driver_standard.c new file mode 100644 index 0000000000..41426e9a60 --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/vhci/hci_driver_standard.c @@ -0,0 +1,302 @@ +/* + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "ble_mbuf.h" +#include "esp_hci_driver.h" +#include "esp_hci_internal.h" +#include "esp_bt.h" + +typedef struct { + hci_driver_forward_fn *forward_cb; + const esp_vhci_host_callback_t *host_recv_cb; +} hci_driver_vhci_env_t; + +static hci_driver_vhci_env_t s_hci_driver_vhci_env; + + +#if 0 +typedef int ble_host_rx_iso_data_fn(uint8_t *data, uint16_t len); +static ble_host_rx_iso_data_fn *ble_host_iso_rx_cb = NULL; + +void ble_hci_register_rx_iso_data_cb(void *cb) +{ + /* If the iso rx cb is already registered, we will give + * a warning log here, and the cb will still be updated. + */ + if (ble_host_iso_rx_cb) { + printf("iso rx cb %p already registered\n", ble_host_iso_rx_cb); + } + + ble_host_iso_rx_cb = cb; +} + +#endif // CONFIG_BT_LE_ISO_SUPPORT + +static int +hci_driver_vhci_host_recv_with_type(uint8_t data_type, uint8_t *data, uint16_t len) +{ + static const esp_vhci_host_callback_t *host_recv_cb; + + host_recv_cb = s_hci_driver_vhci_env.host_recv_cb; + if (!host_recv_cb) { + return -1; + } +#if 0 + if (data_type == HCI_DRIVER_TYPE_ISO) { + if (ble_host_iso_rx_cb) { + return ble_host_iso_rx_cb(data, len); + } + } else +#endif // CONFIG_BT_LE_ISO_SUPPORT + { + if (host_recv_cb->notify_host_recv) { + return host_recv_cb->notify_host_recv(data, len); + } + } + + return -1; +} + +static void +hci_driver_vhci_host_send_available(void) +{ + static const esp_vhci_host_callback_t *host_recv_cb; + + host_recv_cb = s_hci_driver_vhci_env.host_recv_cb; + if (host_recv_cb && host_recv_cb->notify_host_send_available) { + host_recv_cb->notify_host_send_available(); + } +} + +static int +hci_driver_vhci_controller_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, hci_driver_direction_t dir) +{ + int rc = 0; + uint16_t buf_len = length + 1;; + uint8_t *buf = NULL; + struct ble_mbuf *om; + uint8_t old_value = 0; + hci_driver_packet_t *pkt = (hci_driver_packet_t *)data; + + if (data_type == HCI_DRIVER_TYPE_ACL) { +#if UC_BT_CTRL_BLE_IS_ENABLE + if (dir == HCI_DRIVER_DIR_LEC2H) { + om = (struct ble_mbuf *)data; + buf = malloc(buf_len); + /* TODO: If there is no memory, should handle it in the controller. */ + assert(buf); + buf[0] = HCI_DRIVER_TYPE_ACL; + ble_mbuf_copydata(om, 0, length, &buf[1]); + ble_mbuf_free_chain(om); + rc = hci_driver_vhci_host_recv_with_type(data_type, buf, buf_len); + free(buf); + } +#endif // UC_BT_CTRL_BLE_IS_ENABLE +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + if (dir == HCI_DRIVER_DIR_BREDRC2H) { + buf = pkt->data - 1; + old_value = *buf; + *buf = data_type; + rc = hci_driver_vhci_host_recv_with_type(data_type, buf, buf_len); + *buf = old_value; + if (rc >= 0) { + bredr_hci_trans_acl_tx_done(pkt); + bredr_hci_trans_acl_free(pkt); + } + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + /* TODO: If there is no memory, should handle it in the controller. */ + if (dir == HCI_DRIVER_DIR_LEC2H) { + buf = malloc(buf_len); + assert(buf != NULL); + buf[0] = HCI_DRIVER_TYPE_EVT; + memcpy(&buf[1], data, length); + rc = hci_driver_vhci_host_recv_with_type(data_type, buf, buf_len); + r_ble_hci_trans_buf_free(data); + free(buf); + } +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else if (dir == HCI_DRIVER_DIR_BREDRC2H) { + buf = pkt->data - 1; + old_value = *buf; + *buf = data_type; + rc = hci_driver_vhci_host_recv_with_type(data_type, buf, buf_len); + *buf = old_value; + if (rc >= 0) { + bredr_hci_trans_evt_tx_done((hci_driver_packet_t *)data); + bredr_hci_trans_evt_free((hci_driver_packet_t *)data); + } + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + buf = pkt->data - 1; + old_value = *buf; + *buf = data_type; + rc = hci_driver_vhci_host_recv_with_type(data_type, buf, buf_len); + *buf = old_value; + btdm_hci_trans_buf_free(pkt); + } + + } +#if CONFIG_BT_LE_ISO_SUPPORT + else if (data_type == HCI_DRIVER_TYPE_ISO) { + rc = hci_driver_vhci_host_recv_with_type(data_type, data, length); + free(data); + } +#endif // CONFIG_BT_LE_ISO_SUPPORT +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else if (data_type == HCI_DRIVER_TYPE_SYNC) { + /* SCO/ESCO data */ + buf = pkt->data - 1; + old_value = *buf; + *buf = data_type; + rc = hci_driver_vhci_host_recv_with_type(data_type, buf, buf_len); + *buf = old_value; + if (rc >= 0) { + bredr_hci_trans_sync_tx_done(pkt); + bredr_hci_trans_sync_free(pkt); + } + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + assert(0); + } + + return rc; +} + +static int +hci_driver_vhci_host_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + struct ble_mbuf *om; + uint16_t pkt_len; + uint16_t conn_handle; + hci_driver_packet_t *pkt = NULL; + uint8_t data_source = 0xFF; + + pkt_len = length - 1; + switch (data_type) { + case HCI_DRIVER_TYPE_CMD: + pkt = btdm_hci_trans_buf_alloc(data_type, 0); + assert(pkt); + //TODO: check if pkt_len is not larger than the allocated one. + memcpy(pkt->data, &data[1], pkt_len); + data = (uint8_t *)pkt; + break; + + case HCI_DRIVER_TYPE_ACL: + conn_handle = btdm_get_le16(&data[1]) & HCI_INTERNAL_CONN_MASK; +#if UC_BT_CTRL_BLE_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BLE(conn_handle)) { + om = ble_msys_get_pkthdr(pkt_len, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); + assert(om); + assert(ble_mbuf_append(om, &data[1], length - 1) == 0); + data = (uint8_t *)om; + data_source = HCI_DRIVER_LE_ACL; + } +#endif // UC_BT_CTRL_BLE_IS_ENABLE +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + if (HCI_INTERNAL_CONN_IS_BREDR(conn_handle)) { + pkt = btdm_hci_trans_buf_alloc(data_type, conn_handle); + assert(pkt); + memcpy(pkt->data, &data[1], pkt_len); + data = (uint8_t *)pkt; + data_source = HCI_DRIVER_BREDR_ACL; + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + break; + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + case HCI_DRIVER_TYPE_SYNC: + conn_handle = btdm_get_le16(&data[1]) & HCI_INTERNAL_CONN_MASK; + pkt = btdm_hci_trans_buf_alloc(data_type, conn_handle); + assert(pkt); + memcpy(pkt->data, &data[1], pkt_len); + data = (uint8_t *)pkt; + data_source = HCI_DRIVER_BREDR_SYNC; + break; +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + case HCI_DRIVER_TYPE_ISO: + data_source = HCI_DRIVER_LE_ISO; + break; + default: + assert(0); + break; + } + + if (pkt) { + pkt->length = pkt_len; + } + + return s_hci_driver_vhci_env.forward_cb(data_type, data, pkt_len, HCI_DRIVER_DIR_H2C, data_source); +} + +static int +hci_driver_vhci_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + int rc; + if (dir == HCI_DRIVER_DIR_H2C) { + rc = hci_driver_vhci_host_tx(data_type, data, length); + } else { + rc = hci_driver_vhci_controller_tx(data_type, data, length, dir); + } + + return rc; +} + +static int +hci_driver_vhci_init(hci_driver_forward_fn *cb) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); + s_hci_driver_vhci_env.forward_cb = cb; + return 0; +} + +static void +hci_driver_vhci_deinit(void) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); +} + +hci_driver_ops_t hci_driver_vhci_ops = { + .hci_driver_tx = hci_driver_vhci_tx, + .hci_driver_init = hci_driver_vhci_init, + .hci_driver_deinit = hci_driver_vhci_deinit, +}; + +/* Special APIs declared in the `esp_bt.h'. */ +esp_err_t +esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) +{ + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_FAIL; + } + + s_hci_driver_vhci_env.host_recv_cb = callback; + return ESP_OK; +} + +void +esp_vhci_host_send_packet(uint8_t *data, uint16_t len) +{ + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return; + } + + hci_driver_vhci_tx(data[0], data, len, HCI_DRIVER_DIR_H2C); +} + +bool +esp_vhci_host_check_send_available(void) +{ + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return false; + } + return true; +} diff --git a/components/bt/porting_btdm/transport/driver/vhci/hci_driver_tamplete.c b/components/bt/porting_btdm/transport/driver/vhci/hci_driver_tamplete.c new file mode 100644 index 0000000000..63feb934da --- /dev/null +++ b/components/bt/porting_btdm/transport/driver/vhci/hci_driver_tamplete.c @@ -0,0 +1,133 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "os/os_mbuf.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "esp_hci_driver.h" + +typedef struct { + hci_driver_forward_fn *forward_cb; +} hci_driver_vhci_env_t; + +static hci_driver_vhci_env_t s_hci_driver_vhci_env; + +static int +hci_driver_vhci_controller_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + int rc; + uint16_t len = 0; + uint8_t *buf = NULL; + struct os_mbuf *om; + + if (data_type == HCI_DRIVER_TYPE_ACL) { + /* The ACL data will be packaged as structure of `os_mbuf`. + * 1. Allocate a buffer suitable for the host. Use the following method to copy the data + * from the os_mbuf to the newly allocated memory. + * ```c + * buf = malloc(length); + * os_mbuf_copydata(om, 0, length, buf); + * ``` + * 2. Free the controller's os_mbuf + * ```c + * os_mbuf_free_chain(om); + * ``` + */ + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + /* The event data will be packaged as an array. + * 1. Allocate a buffer suitable for the host. Use the following method to copy the data + * from the controller buffer to the newly allocated memory. + * ```c + * buf = malloc(length); + * memcpy(buf, data, length); + * ``` + * 2. Free the controller's buffer. + * ```c + * r_ble_hci_trans_buf_free(data); + * ``` + */ + } else { + assert(0); + } + + rc = s_hci_driver_vhci_env.forward_cb(data_type, buf, len, HCI_DRIVER_DIR_C2H); + free(buf); + + return rc; +} + +static int +hci_driver_vhci_host_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + uint8_t *hci_data; + struct os_mbuf *om; + + if (data_type == HCI_DRIVER_TYPE_ACL) { + /* The ACL data needs to be packaged as structure of `os_mbuf`. + * 1. Get an os_mbuf in the following way. + * ```c + * om = os_msys_get_pkthdr(length, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); + * ``` + * 2. Copy the host's data into this os_mbuf using the following method. + * ```c + * assert(os_mbuf_append(om, data, length) == 0); + * hci_data = (uint8_t *)om; + * ``` + * 3. Free the host's buffer if needed. + */ + } else if (data_type == HCI_DRIVER_TYPE_CMD) { + /* The COMMAND data needs to be packaged as an array. + * 1. Get a command buffer from the controller. + * ```c + * hci_data = r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD); + * ``` + * 2. Copy the host's data into this buffer. + * ```c + * memcpy(hci_data, data, length); + * ``` + * 3. Free the host's buffer if needed. + */ + } else { + assert(0); + } + + return s_hci_driver_vhci_env.forward_cb(data_type, hci_data, length, HCI_DRIVER_DIR_H2C); +} + +static int +hci_driver_vhci_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + int rc; + + if (dir == HCI_DRIVER_DIR_C2H) { + rc = hci_driver_vhci_controller_tx(data_type, data, length); + } else { + rc = hci_driver_vhci_host_tx(data_type, data, length); + } + return rc; +} + +static int +hci_driver_vhci_init(hci_driver_forward_fn *cb) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); + s_hci_driver_vhci_env.forward_cb = cb; + return 0; +} + +static void +hci_driver_vhci_deinit(void) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); +} + +hci_driver_ops_t hci_driver_vhci_ops = { + .hci_driver_tx = hci_driver_vhci_tx, + .hci_driver_init = hci_driver_vhci_init, + .hci_driver_deinit = hci_driver_vhci_deinit, +}; diff --git a/components/bt/porting_btdm/transport/include/common/hci_driver_h4.h b/components/bt/porting_btdm/transport/include/common/hci_driver_h4.h new file mode 100644 index 0000000000..d92bd7bc79 --- /dev/null +++ b/components/bt/porting_btdm/transport/include/common/hci_driver_h4.h @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _HCI_H4_H_ +#define _HCI_H4_H_ + +#include +#include "esp_hci_internal.h" + +#define HCI_H4_NONE 0x00 +#define HCI_H4_CMD 0x01 +#define HCI_H4_ACL 0x02 +#define HCI_H4_SYNC 0x03 +#define HCI_H4_EVT 0x04 +#define HCI_H4_ISO 0x05 + +typedef hci_driver_packet_t *(hci_h4_alloc_cmd)(void); +typedef void *(hci_h4_alloc_evt)(int); +typedef struct ble_mbuf *(hci_h4_alloc_acl)(void); +typedef void *(hci_h4_alloc_iso)(uint32_t); +#if CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +typedef hci_driver_packet_t *(hci_h4_alloc_sync)(uint16_t); +typedef hci_driver_packet_t *(hci_h4_alloc_bredr_acl)(uint16_t); +#endif // CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +struct hci_h4_allocators { + hci_h4_alloc_cmd *cmd; + hci_h4_alloc_acl *acl; + hci_h4_alloc_evt *evt; + hci_h4_alloc_iso *iso; +#if CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM + hci_h4_alloc_sync *sync; + hci_h4_alloc_bredr_acl *bredr_acl; +#endif // CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +}; + +extern const struct hci_h4_allocators hci_h4_allocs_from_ll; +extern const struct hci_h4_allocators hci_h4_allocs_from_hs; + +typedef void (hci_h4_free_cmd)(void * ptr); +typedef void (hci_h4_free_evt)(void * ptr); +typedef int (hci_h4_free_acl)(struct ble_mbuf *om); +typedef void (hci_h4_free_iso)(void *ptr); +typedef void (hci_h4_free_le_evt)(uint8_t *buf); +#if CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +typedef void (hci_h4_free_sync)(void *ptr); +typedef void (hci_h4_free_bredr_acl)(void *ptr); +#endif // CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +struct hci_h4_frees { + hci_h4_free_cmd *cmd; + hci_h4_free_acl *acl; + hci_h4_free_evt *evt; + hci_h4_free_iso *iso; + hci_h4_free_le_evt *le_evt; +#if CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM + hci_h4_free_sync *sync; + hci_h4_free_bredr_acl *bredr_acl; +#endif // CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +}; + +typedef int (hci_h4_frame_cb)(uint8_t pkt_type, void *data, int len, uint8_t data_source); + +struct hci_h4_sm { + uint8_t state; + uint8_t pkt_type; + uint8_t min_len; + uint16_t len; + uint16_t exp_len; + uint8_t hdr[4]; + union { + uint8_t *buf; + struct ble_mbuf *om; + hci_driver_packet_t *pkt; + }; + + const struct hci_h4_allocators *allocs; + const struct hci_h4_frees *frees; + hci_h4_frame_cb *frame_cb; +}; + +void hci_h4_sm_init(struct hci_h4_sm *h4sm, + const struct hci_h4_allocators *allocs, + const struct hci_h4_frees *frees, + hci_h4_frame_cb *frame_cb); + +int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); + +#endif /* _HCI_H4_H_ */ diff --git a/components/bt/porting_btdm/transport/include/common/hci_driver_mem.h b/components/bt/porting_btdm/transport/include/common/hci_driver_mem.h new file mode 100644 index 0000000000..96143b5a69 --- /dev/null +++ b/components/bt/porting_btdm/transport/include/common/hci_driver_mem.h @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _H_HCI_DRIVER_MEM_ +#define _H_HCI_DRIVER_MEM_ +#include +#include "esp_hci_internal.h" + +hci_driver_packet_t *hci_driver_mem_cmd_alloc(void); + +void *hci_driver_mem_evt_alloc(int discardable); + +struct ble_mbuf *hci_driver_mem_acl_alloc(void); + +struct ble_mbuf *hci_driver_mem_acl_len_alloc(uint32_t len); + +void *hci_driver_mem_iso_alloc(uint32_t len); + +struct ble_mbuf *hci_driver_mem_iso_len_alloc(uint32_t len); + +extern const struct hci_h4_allocators s_hci_driver_mem_alloc; +extern const struct hci_h4_frees s_hci_driver_mem_free; +#if CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM +hci_driver_packet_t *hci_driver_mem_bredr_acl_alloc(uint16_t len); + +hci_driver_packet_t *hci_driver_mem_sync_alloc(uint16_t len); +#endif // CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY || CONFIG_BTDM_CTRL_MODE_BTDM + +#endif // _H_HCI_DRIVER_MEM_ diff --git a/components/bt/porting_btdm/transport/include/common/hci_driver_util.h b/components/bt/porting_btdm/transport/include/common/hci_driver_util.h new file mode 100644 index 0000000000..7347f2d6bf --- /dev/null +++ b/components/bt/porting_btdm/transport/include/common/hci_driver_util.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _H_HCI_DRIVER_UTIL_ +#define _H_HCI_DRIVER_UTIL_ +#include + +int hci_driver_util_init(void); + +void hci_driver_util_deinit(void); + +int hci_driver_util_tx_list_enqueue(hci_driver_data_type_t type, uint8_t *data, uint32_t len, hci_driver_data_source_t data_source); + +uint32_t hci_driver_util_tx_list_dequeue(uint32_t max_tx_len, void **tx_data, bool *last_frame); + +void hci_driver_util_assert_check(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); +#define HCI_TRANS_ASSERT(cond, p1, p2) \ + if (!(cond)) { \ + hci_driver_util_assert_check(__LINE__, __func__, p1, p2); \ + } +#endif // _H_HCI_DRIVER_UTIL_ diff --git a/components/bt/porting_btdm/transport/include/esp_hci_driver.h b/components/bt/porting_btdm/transport/include/esp_hci_driver.h new file mode 100644 index 0000000000..08ef8d3b35 --- /dev/null +++ b/components/bt/porting_btdm/transport/include/esp_hci_driver.h @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef H_ESP_HCI_DRIVER_ +#define H_ESP_HCI_DRIVER_ +#include +#include "queue.h" +#include "esp_bt.h" +#include "esp_hci_transport.h" +/** + * @brief Enumeration of HCI transport direction. + */ +typedef enum { + HCI_DRIVER_DIR_LEC2H = 0x00, ///< From controller to host. + HCI_DRIVER_DIR_BREDRC2H, + HCI_DRIVER_DIR_BTDMC2H, + HCI_DRIVER_DIR_H2C, ///< From host to controller. +} hci_driver_direction_t; + +typedef enum { + HCI_DRIVER_TYPE_CMD = 0x01, ///< HCI Command Indicator. + HCI_DRIVER_TYPE_ACL, ///< HCI ACL Data Indicator. + HCI_DRIVER_TYPE_SYNC, ///< HCI Synchronous Data Indicator. + HCI_DRIVER_TYPE_EVT, ///< HCI Event Indicator. + HCI_DRIVER_TYPE_ISO, ///< HCI Isochronous Data Indicator. + HCI_DRIVER_TYPE_VENDOR, ///< HCI Vendor data Indicator. +} hci_driver_data_type_t; + +typedef enum { + HCI_DRIVER_CMD = 0x00, + HCI_DRIVER_LE_EVT, + HCI_DRIVER_BREDR_EVT, + HCI_DRIVER_BTDM_EVT, + HCI_DRIVER_LE_ACL, + HCI_DRIVER_LE_ISO, + HCI_DRIVER_BREDR_ACL, + HCI_DRIVER_BREDR_SYNC, +} hci_driver_data_source_t; + +struct hci_driver_packet +{ + STAILQ_ENTRY(hci_driver_packet) next; + uint8_t *data; + uint16_t length; + uint8_t flags; + uint8_t type; +}; +typedef struct hci_driver_packet hci_driver_packet_t; + +typedef int hci_driver_forward_fn(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir, uint8_t data_source); + +#define HCI_DRIVER_D2P(data) ((void *)((uint32_t)data - sizeof(hci_driver_packet_t))) + +/** + * @brief Structure of HCI driver operations. + */ +typedef struct hci_driver_ops { + int (*hci_driver_tx)(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir); + int (*hci_driver_init)(hci_driver_forward_fn *cb); + void (*hci_driver_deinit)(void); +} hci_driver_ops_t; + + +#if CONFIG_BT_NIMBLE_ENABLED +typedef int hci_driver_host_recv_fn(hci_driver_data_type_t type, uint8_t *data, uint16_t len); + +/** + * @brief Set the host's HCI callback which will be invoked when receiving ACL/Events from controller. + * @param callback hci_driver_host_recv_fn type variable + * @return int 0 on success, non-zero error code on failure. + */ +int hci_driver_host_callback_register(hci_driver_host_recv_fn *callback); + +/** + * @brief Called to send HCI commands form host to controller. + * @param data Point to the commands data + * @param length Length of data + * @return int 0 on success, non-zero error code on failure. + */ +int hci_driver_host_cmd_tx(uint8_t *data, uint32_t length); + +/** + * @brief Called to send HCI ACL form host to controller. + * @param data Point to the ACL data + * @param length Length of data + * @return int 0 on success, non-zero error code on failure. + */ +int hci_driver_host_acl_tx(uint8_t *data, uint32_t length); + +#if CONFIG_BT_LE_ISO_SUPPORT +/** + * @brief Called to send HCI ISO daata form host to controller. + * @param data Point to the ISO data + * @param length Length of data + * @return int 0 on success, non-zero error code on failure. + */ +int hci_driver_host_iso_tx(uint8_t *data, uint32_t length); +#endif // CONFIG_BT_LE_ISO_SUPPORT +#endif // CONFIG_BT_NIMBLE_ENABLED + +#if UC_BT_CTRL_HCI_INTERFACE_USE_RAM +extern hci_driver_ops_t hci_driver_vhci_ops; +#endif // UC_BT_CTRL_HCI_INTERFACE_USE_RAM + +#if UC_BT_CTRL_HCI_INTERFACE_USE_UART +extern hci_driver_ops_t hci_driver_uart_ops; +#if UC_BT_CTRL_UART_HCI_DMA_MODE +extern hci_driver_ops_t hci_driver_uart_dma_ops; +#endif // UC_BT_CTRL_UART_HCI_DMA_MODE +#endif // UC_BT_CTRL_HCI_INTERFACE_USE_UART + +#endif // H_ESP_HCI_DRIVER_ diff --git a/components/bt/porting_btdm/transport/include/esp_hci_internal.h b/components/bt/porting_btdm/transport/include/esp_hci_internal.h new file mode 100644 index 0000000000..ee75e7d0b5 --- /dev/null +++ b/components/bt/porting_btdm/transport/include/esp_hci_internal.h @@ -0,0 +1,186 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_ESP_HCI_INTERNAL_ +#define H_ESP_HCI_INTERNAL_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "esp_hci_driver.h" +#include "ble_mbuf.h" + + +/* The leadingspace in user info header for ACL data */ +#define ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE (4) + +#define ESP_HCI_INTERNAL_BUF_CMD (3) + +/** + * @brief Define the HCI hardware error code for synchronization loss. + * This error code is used to indicate a loss of synchronization between the controller and the host. + */ +#define ESP_HCI_SYNC_LOSS_ERR (0x1) +/** Callback function types; executed when HCI packets are received. */ +typedef int esp_hci_internal_rx_cmd_fn(uint8_t *cmd, void *arg); +typedef int esp_hci_internal_rx_acl_fn(struct ble_mbuf *om, void *arg); +#if CONFIG_BT_LE_ISO_SUPPORT +typedef int esp_hci_internal_rx_iso_fn(const uint8_t *data, uint16_t len, void *arg); +/** + * @brief Configure the ISO data receive callback for BLE HCI transport. + * + * @param iso_cb The callback to execute upon receiving ISO data. + * + * @param iso_arg Optional argument to pass to the ISO callback. + */ +void r_ble_iso_trans_cfg_hs(esp_hci_internal_rx_iso_fn *iso_cb, void *iso_arg); + +#define ble_iso_trans_cfg_hs r_ble_iso_trans_cfg_hs +/** + * @brief Transmit ISO (Isochronous) data over BLE HCItransport. + * + * @param data Pointer to the ISO data buffer to be transmitted. + * @param length Length of the ISO data in bytes. + * @param arg Optional user-defined argument, passed through + * the transport layer and may be used by the underlying driver or callback. + * + * @return 0 on success, or a non-zero error code on failure. + */ +int r_ble_hci_trans_hs_iso_tx(const uint8_t *data, uint16_t length, void *arg); + +#define ble_hci_trans_hs_iso_tx r_ble_hci_trans_hs_iso_tx +#endif // CONFIG_BT_LE_ISO_SUPPORT +/** + * Configures the HCI transport to operate with a host. The transport will + * execute specified callbacks upon receiving HCI packets from the controller. + * + * @param evt_cb The callback to execute upon receiving an HCI + * event. + * @param evt_arg Optional argument to pass to the event + * callback. + * @param acl_cb The callback to execute upon receiving ACL + * data. + * @param acl_arg Optional argument to pass to the ACL + * callback. + */ +void r_ble_hci_trans_cfg_hs(esp_hci_internal_rx_cmd_fn *evt_cb, void *evt_arg, + esp_hci_internal_rx_acl_fn *acl_cb, void *acl_arg); +/** + * Sends ACL data from host to controller. + * + * @param om The ACL data packet to send. + * + * @return 0 on success; + * A BLE_ERR_[...] error code on failure. + */ +int r_ble_hci_trans_hs_acl_tx(struct ble_mbuf *om); + +/** + * Sends an HCI command from the host to the controller. + * + * @param cmd The HCI command to send. This buffer must be + * allocated via ble_hci_trans_buf_alloc(). + * + * @return 0 on success; + * A BLE_ERR_[...] error code on failure. + */ +int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); + + +#if CONFIG_BT_LE_ISO_SUPPORT +int ble_hci_trans_hs_iso_tx(const uint8_t *data, uint16_t length, void *arg); +#endif /* CONFIG_BT_LE_ISO_SUPPORT */ + +/** + * Allocates a flat buffer of the specified type. + * + * @param type The type of buffer to allocate; one of the + * BLE_HCI_TRANS_BUF_[...] constants. + * + * @return The allocated buffer on success; + * NULL on buffer exhaustion. + */ +uint8_t * r_ble_hci_trans_buf_alloc(int type); + +/** + * Frees the specified flat buffer. The buffer must have been allocated via + * ble_hci_trans_buf_alloc(). + * + * @param buf The buffer to free. + */ +void r_ble_hci_trans_buf_free(uint8_t *buf); + +/** + * @brief Handle an HCI hardware error event. + * This function processes a hardware error code and generates the appropriate HCI hardware error event. + * + * @param hw_err The hardware error code that needs to be processed. The specific meaning of the error code + * depends on the implementation and the hardware. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + * + * @note This function should be called whenever a hardware error is detected in the HCI Layer. + */ +int r_ble_ll_hci_ev_hw_err(uint8_t hw_err); + +//!TODO: Check what this API is used for +int r_ble_hci_trans_reset(void); + +//!TODO: Should we initialize the hci layer in IDF ? +void esp_ble_hci_trans_init(uint8_t); + +// ******************************************************************************************** +// btdm common +// ******************************************************************************************** + +typedef int (*btdm_hci_trans_tx_func_t)(hci_driver_packet_t *pkt); + +#define HCI_INTERNAL_CONN_MASK (0x0fff) +#define HCI_INTERNAL_CONN_IS_BLE(conn_handle) (!(conn_handle & 0x0800)) +#define HCI_INTERNAL_CONN_IS_BREDR(conn_handle) (conn_handle & 0x0800) +#define HCI_INTERNAL_CONN_IS_BREDR_ACL(conn_handle) ((conn_handle & 0x0800) && (conn_handle & 0x000f)) +#define HCI_INTERNAL_CONN_IS_BREDR_SYNC(conn_handle) ((conn_handle & 0x0800) && (conn_handle & 0x00f0)) + +int r_btdm_hci_trans_register_tx(btdm_hci_trans_tx_func_t *tx_func, bool async); + +int r_btdm_hci_trans_rx(hci_driver_packet_t *pkt); + +hci_driver_packet_t *r_btdm_hci_trans_buf_alloc(uint8_t type, uint16_t conn_handle); +void r_btdm_hci_trans_buf_free(hci_driver_packet_t *pkt); +uint16_t r_btdm_get_le16(const void *buf); + +#define btdm_hci_trans_buf_alloc r_btdm_hci_trans_buf_alloc +#define btdm_hci_trans_buf_free r_btdm_hci_trans_buf_free +#define btdm_get_le16 r_btdm_get_le16 +#define btdm_hci_trans_register_tx r_btdm_hci_trans_register_tx +#define btdm_hci_trans_rx r_btdm_hci_trans_rx + +void btdm_hci_pkt_flag_ble_setf(hci_driver_packet_t *pkt, uint8_t is_ble); +uint8_t btdm_hci_pkt_flag_ble_getf(hci_driver_packet_t *pkt); +uint8_t btdm_hci_pkt_flag_bredr_getf(hci_driver_packet_t *pkt); +uint8_t btdm_hci_pkt_flag_cmdpool_getf(hci_driver_packet_t *pkt); + +// ******************************************************************************************** +// BREDR +// ******************************************************************************************** + +int bredr_hci_trans_acl_rx(hci_driver_packet_t *pkt); +int bredr_hci_trans_sync_rx(hci_driver_packet_t *pkt); +void bredr_hci_trans_register_tx(btdm_hci_trans_tx_func_t *acl_tx_func, + btdm_hci_trans_tx_func_t *sync_tx_func, + btdm_hci_trans_tx_func_t *evt_tx_func); +void bredr_hci_trans_acl_tx_done(hci_driver_packet_t *pkt); +void bredr_hci_trans_sync_tx_done(hci_driver_packet_t *pkt); +void bredr_hci_trans_evt_tx_done(hci_driver_packet_t *pkt); +int bredr_hci_trans_acl_free(hci_driver_packet_t *pkt); +int bredr_hci_trans_sync_free(hci_driver_packet_t *pkt); +int bredr_hci_trans_evt_free(hci_driver_packet_t *pkt); + +#ifdef __cplusplus +} +#endif +#endif /* H_ESP_HCI_INTERNAL_ */ diff --git a/components/bt/porting_btdm/transport/include/esp_hci_transport.h b/components/bt/porting_btdm/transport/include/esp_hci_transport.h new file mode 100644 index 0000000000..a82dad9a8a --- /dev/null +++ b/components/bt/porting_btdm/transport/include/esp_hci_transport.h @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_ESP_HCI_TRANSPORT_ +#define H_ESP_HCI_TRANSPORT_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "ble_mbuf.h" +#include "esp_hci_driver.h" + +/** + * @brief Enumeration of HCI packet indicators + */ +typedef enum { + HCI_CMD_IND = 0x01, /*!< HCI Command Indicator */ + HCI_ACL_IND, /*!< HCI ACL Data Indicator */ + HCI_SYNC_IND, /*!< HCI Synchronous Data Indicator */ + HCI_EVT_IND, /*!< HCI Event Indicator */ + HCI_ISO_IND, /*!< HCI Isochronous Data Indicator */ + HCI_VENDOR_IND, /*!< HCI Vendor data Indicator */ +} hci_trans_pkt_ind_t; + +/** + * @brief Enumeration of HCI Transport Mode + */ +typedef enum { + HCI_TRANSPORT_VHCI, /*!< VHCI Transport Mode */ + HCI_TRANSPORT_UART_NO_DMA, /*!< UART_NO_DMA Transport Mode */ + HCI_TRANSPORT_UART_UHCI, /*!< UART_UHCI Transport Mode */ + HCI_TRANSPORT_SDIO, /*!< SDIO Transport Mode */ + HCI_TRANSPORT_USB, /*!< USB Transport Mode */ +} hci_trans_mode_t; + +/** + * @brief Initialize the HCI transport layer. + * It should be called before using any other functions in the transport layer. + * + * @param hci_transport_mode The mode in which the HCI transport should operate. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + */ +int hci_transport_init(uint8_t hci_transport_mode); + +/** + * @brief Deinitialize the HCI transport layer for releasing any allocated resources. + */ +void hci_transport_deinit(void); + +#ifdef __cplusplus +} +#endif +#endif /* H_ESP_HCI_TRANSPORT_ */ diff --git a/components/bt/porting_btdm/transport/src/hci_transport.c b/components/bt/porting_btdm/transport/src/hci_transport.c new file mode 100644 index 0000000000..eafed645c9 --- /dev/null +++ b/components/bt/porting_btdm/transport/src/hci_transport.c @@ -0,0 +1,287 @@ +/* + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_log.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "esp_bt.h" + +typedef struct hci_transport_env +{ + hci_driver_ops_t *driver_ops; +} hci_transport_env_t; + +static hci_transport_env_t s_hci_transport_env; + +/* Functions for controller Rx. */ +static int +hci_transport_controller_rx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, hci_driver_direction_t dir, uint8_t data_source) +{ + int rc; + hci_driver_packet_t *pkt; + + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return -1; + } + + rc = 0; + assert(dir == HCI_DRIVER_DIR_H2C); + if (data_type == HCI_DRIVER_TYPE_CMD) { + pkt = (hci_driver_packet_t *)data; + rc = btdm_hci_trans_rx(pkt); + } else if (data_type == HCI_DRIVER_TYPE_ACL) { + if (data_source == HCI_DRIVER_LE_ACL) { +#if UC_BT_CTRL_BLE_IS_ENABLE + rc = r_ble_hci_trans_hs_acl_tx((struct ble_mbuf *) data); +#endif // UC_BT_CTRL_BLE_IS_ENABLE + } else { +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + pkt = (hci_driver_packet_t *)data; + pkt->length = length; + rc = bredr_hci_trans_acl_rx(pkt); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + } + } +#if CONFIG_BT_LE_ISO_SUPPORT + else if (data_type == HCI_DRIVER_TYPE_ISO) { + rc = ble_hci_trans_hs_iso_tx(data, length, NULL); + } +#endif // CONFIG_BT_LE_ISO_SUPPORT +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + else if (data_type == HCI_DRIVER_TYPE_SYNC) { + pkt = (hci_driver_packet_t *)data; + pkt->length = length; + rc = bredr_hci_trans_sync_rx(pkt); + } +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + else { + rc = -1; + } + + return rc; +} + +#if UC_BT_CTRL_BLE_IS_ENABLE +/* Functions for controller Tx. */ +static int +hci_transport_controller_le_evt_tx(uint8_t *hci_ev, void *arg) +{ + /* TODO: In order to support dual-host mode, use legacy interfaces for ble when nimble host is enabled */ + uint32_t len; + + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + r_ble_hci_trans_buf_free(hci_ev); + return -1; + } + + len = hci_ev[1] + 2; + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_EVT, hci_ev, len, + HCI_DRIVER_DIR_LEC2H); +} + +static int +hci_transport_controller_le_acl_tx(struct ble_mbuf *om, void *arg) +{ + /* TODO: In order to support dual-host mode, use legacy interfaces for ble when nimble host is enabled */ + uint16_t len; + + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + ble_mbuf_free_chain(om); + return -1; + } + + len = BLE_MBUF_PKTHDR(om)->omp_len; + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_ACL, (uint8_t *)om, len, + HCI_DRIVER_DIR_LEC2H); +} +#endif // UC_BT_CTRL_BLE_IS_ENABLE + +#if UC_BT_CTRL_BR_EDR_IS_ENABLE +static int +hci_transport_controller_bredr_tx_dummy(hci_driver_packet_t *pkt, void *arg) +{ + return -1; +} + +static int +hci_transport_controller_bredr_acl_tx(hci_driver_packet_t *pkt, void *arg) +{ + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_ACL, (uint8_t *)pkt, pkt->length, + HCI_DRIVER_DIR_BREDRC2H); +} + +static int +hci_transport_controller_bredr_sync_tx(hci_driver_packet_t *pkt, void *arg) +{ + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_SYNC, (uint8_t *)pkt, pkt->length, + HCI_DRIVER_DIR_BREDRC2H); +} + +static int +hci_transport_controller_bredr_evt_tx(hci_driver_packet_t *pkt, void *arg) +{ + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_EVT, (uint8_t *)pkt, pkt->length, + HCI_DRIVER_DIR_BREDRC2H); +} +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + +#if CONFIG_BT_LE_ISO_SUPPORT +typedef void ble_host_rx_iso_data_fn(uint8_t *data, uint16_t len); + +static ble_host_rx_iso_data_fn *ble_host_iso_rx_cb = NULL; + +void ble_host_register_rx_iso_data_cb(void *cb) +{ + /* If the iso rx cb is already registered, we will give + * a warning log here, and the cb will still be updated. + */ + if (ble_host_iso_rx_cb) { + printf("iso rx cb %p already registered\n", ble_host_iso_rx_cb); + } + + ble_host_iso_rx_cb = cb; +} + +void ble_hci_register_rx_iso_data_cb(void *cb) +{ + ble_host_register_rx_iso_data_cb(cb); +} + +static int +hci_transport_controller_le_iso_tx_dummy(const uint8_t *data, uint16_t len, void *arg) +{ + return -1; +} + +static int +hci_transport_controller_le_iso_tx(const uint8_t *data, uint16_t len, void *arg) +{ + //ISO_TODO: arg is not used + + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + //ISO_TODO: free this tx buffer + return -1; + } + +#if CONFIG_BT_NIMBLE_ENABLED + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_ISO, (uint8_t *)data, len, + HCI_DRIVER_DIR_LEC2H); +#elif CONFIG_BT_BLUEDROID_ENABLED + if (ble_host_iso_rx_cb) { + ble_host_iso_rx_cb((uint8_t *)data, len); + } + + free((void *)data); +#endif // CONFIG_BT_NIMBLE_ENABLED + return 0; +} +#endif // CONFIG_BT_LE_ISO_SUPPORT + +/* Functions for controller Tx. */ +static int +hci_transport_controller_le_tx_dummy(void *data, void *arg) +{ + return -1; +} + +static int +hci_transport_controller_tx_dummy(hci_driver_packet_t *pkt) +{ + return -1; +} + +static int +hci_transport_controller_tx(hci_driver_packet_t *pkt) +{ + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_INITED + && esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return -1; + } + + return s_hci_transport_env.driver_ops->hci_driver_tx(pkt->type, (uint8_t *)pkt, pkt->length, + HCI_DRIVER_DIR_BTDMC2H); +} + +int +hci_transport_init(uint8_t hci_transport_mode) +{ + int rc; + hci_driver_ops_t *ops; + + memset(&s_hci_transport_env, 0, sizeof(hci_transport_env_t)); + + switch(hci_transport_mode) { +#if UC_BT_CTRL_HCI_INTERFACE_USE_RAM + case HCI_TRANSPORT_VHCI: + ops = &hci_driver_vhci_ops; + break; +#endif // UC_BT_CTRL_HCI_INTERFACE_USE_RAM +#if UC_BT_CTRL_HCI_INTERFACE_USE_UART +#if UC_BT_CTRL_UART_HCI_DMA_MODE + case HCI_TRANSPORT_UART_UHCI: + ops = &hci_driver_uart_dma_ops; + break; +#else + case HCI_TRANSPORT_UART_NO_DMA: + ops = &hci_driver_uart_ops; + break; +#endif // UC_BT_CTRL_UART_HCI_DMA_MODE +#endif // UC_BT_CTRL_HCI_INTERFACE_USE_UART + default: + assert(0); + } + + rc = ops->hci_driver_init(hci_transport_controller_rx); + if (rc) { + goto error; + } + + s_hci_transport_env.driver_ops = ops; +#if UC_BT_CTRL_BLE_IS_ENABLE + r_ble_hci_trans_cfg_hs((esp_hci_internal_rx_cmd_fn *)hci_transport_controller_le_evt_tx, NULL, + (esp_hci_internal_rx_acl_fn *)hci_transport_controller_le_acl_tx, NULL); +#if CONFIG_BT_LE_ISO_SUPPORT + ble_iso_trans_cfg_hs((esp_hci_internal_rx_iso_fn *)hci_transport_controller_le_iso_tx, NULL); +#endif // CONFIG_BT_LE_ISO_SUPPORT + +#endif // UC_BT_CTRL_BLE_IS_ENABLE +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + bredr_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_acl_tx, + (btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_sync_tx, + (btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_evt_tx); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + btdm_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_tx, false); + return 0; +error: + hci_transport_deinit(); + return rc; +} + +void +hci_transport_deinit(void) +{ + hci_driver_ops_t *ops; + + btdm_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_tx_dummy, false); +#if UC_BT_CTRL_BLE_IS_ENABLE + r_ble_hci_trans_cfg_hs((esp_hci_internal_rx_cmd_fn *)hci_transport_controller_le_tx_dummy, NULL, + (esp_hci_internal_rx_acl_fn *)hci_transport_controller_le_tx_dummy, NULL); +#if CONFIG_BT_LE_ISO_SUPPORT + ble_iso_trans_cfg_hs((esp_hci_internal_rx_iso_fn *)hci_transport_controller_le_iso_tx_dummy, NULL); +#endif // CONFIG_BT_LE_ISO_SUPPORT +#endif // UC_BT_CTRL_BLE_IS_ENABLE +#if UC_BT_CTRL_BR_EDR_IS_ENABLE + bredr_hci_trans_register_tx((btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy, + (btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy, + (btdm_hci_trans_tx_func_t *)hci_transport_controller_bredr_tx_dummy); +#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE + ops = s_hci_transport_env.driver_ops; + if (ops) { + ops->hci_driver_deinit(); + } + memset(&s_hci_transport_env, 0, sizeof(hci_transport_env_t)); +} diff --git a/components/esp_hw_support/modem/port/esp32h4/modem_clock_impl.c b/components/esp_hw_support/modem/port/esp32h4/modem_clock_impl.c index 3ba7291016..fa79beef17 100644 --- a/components/esp_hw_support/modem/port/esp32h4/modem_clock_impl.c +++ b/components/esp_hw_support/modem/port/esp32h4/modem_clock_impl.c @@ -34,7 +34,7 @@ uint32_t IRAM_ATTR modem_clock_get_module_deps(shared_periph_module_t module) case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; - // case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; @@ -44,23 +44,23 @@ uint32_t IRAM_ATTR modem_clock_get_module_deps(shared_periph_module_t module) return deps; } -// static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) -// { - // modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); - // modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); - // modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); -// } +static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); +} -// #if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING -// static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) -// { -// bool all_clock_enabled = true; -// all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); -// all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); -// all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); -// return all_clock_enabled ? ESP_OK : ESP_FAIL; -// } -// #endif +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) { @@ -176,7 +176,7 @@ static void IRAM_ATTR modem_clock_configure_impl(modem_clock_context_t *ctx, int : (dev_id == MODEM_CLOCK_COEXIST) ? modem_clock_coex_configure : (dev_id == MODEM_CLOCK_I2C_MASTER) ? modem_clock_i2c_master_configure : (dev_id == MODEM_CLOCK_ETM) ? modem_clock_etm_configure - // : (dev_id == MODEM_CLOCK_BLE_MAC) ? modem_clock_ble_mac_configure + : (dev_id == MODEM_CLOCK_BLE_MAC) ? modem_clock_ble_mac_configure : (dev_id == MODEM_CLOCK_BT_I154_COMMON_BB) ? modem_clock_ble_i154_bb_configure : (dev_id == MODEM_CLOCK_802154_MAC) ? modem_clock_ieee802154_mac_configure : (dev_id == MODEM_CLOCK_DATADUMP) ? modem_clock_data_dump_configure @@ -196,7 +196,7 @@ static esp_err_t IRAM_ATTR modem_clock_check_impl(modem_clock_context_t *ctx, in : (dev_id == MODEM_CLOCK_COEXIST) ? modem_clock_coex_check_enable : (dev_id == MODEM_CLOCK_I2C_MASTER) ? modem_clock_i2c_master_check_enable : (dev_id == MODEM_CLOCK_ETM) ? modem_clock_etm_check_enable - // : (dev_id == MODEM_CLOCK_BLE_MAC) ? modem_clock_ble_mac_check_enable + : (dev_id == MODEM_CLOCK_BLE_MAC) ? modem_clock_ble_mac_check_enable : (dev_id == MODEM_CLOCK_BT_I154_COMMON_BB) ? modem_clock_ble_i154_bb_check_enable : (dev_id == MODEM_CLOCK_802154_MAC) ? modem_clock_ieee802154_mac_check_enable : (dev_id == MODEM_CLOCK_DATADUMP) ? modem_clock_data_dump_check_enable diff --git a/components/esp_phy/lib b/components/esp_phy/lib index ac744ff2c5..3dad662616 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit ac744ff2c5c39c63f8cdd503d4074905647fdbb6 +Subproject commit 3dad662616b80b89abed23f218fb8ef2222ceb63 diff --git a/components/hal/esp32h4/modem_clock_hal.c b/components/hal/esp32h4/modem_clock_hal.c index 35e7e86555..f80de7ce92 100644 --- a/components/hal/esp32h4/modem_clock_hal.c +++ b/components/hal/esp32h4/modem_clock_hal.c @@ -30,10 +30,9 @@ void IRAM_ATTR modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_conte case MODEM_CLOCK_DOMAIN_MODEM_PERIPH: modem_syscon_ll_set_modem_periph_icg_bitmap(hal->syscon_dev, bitmap); break; - // TODO: PM-636 - // case MODEM_CLOCK_DOMAIN_BT: - // modem_syscon_ll_set_bt_icg_bitmap(hal->syscon_dev, bitmap); - // break; + case MODEM_CLOCK_DOMAIN_BT: + modem_syscon_ll_set_bt_icg_bitmap(hal->syscon_dev, bitmap); + break; case MODEM_CLOCK_DOMAIN_MODEM_FE: modem_syscon_ll_set_fe_icg_bitmap(hal->syscon_dev, bitmap); break; @@ -58,6 +57,7 @@ uint32_t IRAM_ATTR modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_c { HAL_ASSERT(domain < MODEM_CLOCK_DOMAIN_MAX); uint32_t bitmap = 0; + switch (domain) { case MODEM_CLOCK_DOMAIN_MODEM_APB: @@ -66,10 +66,9 @@ uint32_t IRAM_ATTR modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_c case MODEM_CLOCK_DOMAIN_MODEM_PERIPH: bitmap = modem_syscon_ll_get_modem_periph_icg_bitmap(hal->syscon_dev); break; - // TODO: PM-636 - // case MODEM_CLOCK_DOMAIN_BT: - // bitmap = modem_syscon_ll_get_bt_icg_bitmap(hal->syscon_dev); - // break; + case MODEM_CLOCK_DOMAIN_BT: + bitmap = modem_syscon_ll_get_bt_icg_bitmap(hal->syscon_dev); + break; case MODEM_CLOCK_DOMAIN_MODEM_FE: bitmap = modem_syscon_ll_get_fe_icg_bitmap(hal->syscon_dev); break; diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 4110dfa3df..c3bc266397 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -55,6 +55,10 @@ config SOC_PARLIO_LCD_SUPPORTED bool default y +config SOC_BT_SUPPORTED + bool + default y + config SOC_IEEE802154_BLE_ONLY bool default y @@ -1123,6 +1127,50 @@ config SOC_TOUCH_SAMPLE_CFG_NUM int default 3 +config SOC_BLE_SUPPORTED + bool + default y + +config SOC_ESP_NIMBLE_CONTROLLER + bool + default y + +config SOC_BLE_50_SUPPORTED + bool + default y + +config SOC_BLE_DEVICE_PRIVACY_SUPPORTED + bool + default y + +config SOC_BLE_POWER_CONTROL_SUPPORTED + bool + default y + +config SOC_BLE_MULTI_CONN_OPTIMIZATION + bool + default y + +config SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED + bool + default y + +config SOC_BLE_CTE_SUPPORTED + bool + default y + +config SOC_BLE_SUBRATE_SUPPORTED + bool + default y + +config SOC_BLE_PERIODIC_ADV_WITH_RESPONSE + bool + default y + +config SOC_BLE_ISO_SUPPORTED + bool + default y + config SOC_USB_OTG_PERIPH_NUM int default 1 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 840498ad5e..e0232b54aa 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -46,7 +46,7 @@ #define SOC_ETM_SUPPORTED 1 #define SOC_PARLIO_SUPPORTED 1 #define SOC_PARLIO_LCD_SUPPORTED 1 -// #define SOC_BT_SUPPORTED 1 +#define SOC_BT_SUPPORTED 1 #define SOC_IEEE802154_BLE_ONLY 1 #define SOC_PHY_SUPPORTED 1 #define SOC_IEEE802154_SUPPORTED 1 @@ -534,15 +534,18 @@ #define SOC_TOUCH_SAMPLE_CFG_NUM (3) /*!< The sample configurations number in total, each sampler can be used to sample on one frequency */ /*---------------------------------- Bluetooth CAPS ----------------------------------*/ -// #define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */ -// #define SOC_BLE_MESH_SUPPORTED (1) /*!< Support BLE MESH */ -// #define SOC_ESP_NIMBLE_CONTROLLER (1) /*!< Support BLE EMBEDDED controller V1 */ -// #define SOC_BLE_50_SUPPORTED (1) /*!< Support Bluetooth 5.0 */ -// #define SOC_BLE_DEVICE_PRIVACY_SUPPORTED (1) /*!< Support BLE device privacy mode */ -// #define SOC_BLE_POWER_CONTROL_SUPPORTED (1) /*!< Support Bluetooth Power Control */ -// #define SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED (1) /*!< Support For BLE Periodic Adv Enhancements */ -// #define SOC_BLUFI_SUPPORTED (1) /*!< Support BLUFI */ -// #define SOC_BLE_MULTI_CONN_OPTIMIZATION (1) /*!< Support multiple connections optimization */ +#define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */ +// #define SOC_BLE_MESH_SUPPORTED (1) /*!< Support BLE MESH */ +#define SOC_ESP_NIMBLE_CONTROLLER (1) /*!< Support BLE EMBEDDED controller V1 */ +#define SOC_BLE_50_SUPPORTED (1) /*!< Support Bluetooth 5.0 */ +#define SOC_BLE_DEVICE_PRIVACY_SUPPORTED (1) /*!< Support BLE device privacy mode */ +#define SOC_BLE_POWER_CONTROL_SUPPORTED (1) /*!< Support Bluetooth Power Control */ +#define SOC_BLE_MULTI_CONN_OPTIMIZATION (1) /*!< Support multiple connections optimization */ +#define SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED (1) /*!< Support For BLE Periodic Adv Enhancements */ +#define SOC_BLE_CTE_SUPPORTED (1) /*!< Support Bluetooth LE Constant Tone Extension (CTE) */ +#define SOC_BLE_SUBRATE_SUPPORTED (1) /*!< Support Bluetooth LE Connection Subrating */ +#define SOC_BLE_PERIODIC_ADV_WITH_RESPONSE (1) /*!< Support Bluetooth LE Periodic Advertising with Response (PAwR) */ +#define SOC_BLE_ISO_SUPPORTED (1) /*!< Support Bluetooth ISO */ /*-------------------------- USB CAPS ----------------------------------------*/ #define SOC_USB_OTG_PERIPH_NUM (1U) diff --git a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Beacon/README.md b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Beacon/README.md index 113c94670b..7991151991 100644 --- a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Beacon/README.md +++ b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Beacon/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # Bluedroid Beacon Example diff --git a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Connection/README.md b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Connection/README.md index ced37511d4..715caa01f6 100644 --- a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Connection/README.md +++ b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_Connection/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # Bluedroid Connection Example diff --git a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/README.md b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/README.md index 96b33a5a9b..88f6da3ffe 100644 --- a/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/README.md +++ b/examples/bluetooth/ble_get_started/bluedroid/Bluedroid_GATT_Server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # Bluedroid GATT Server Example diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/README.md b/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/README.md index 4f4b0aed13..525cf64c89 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/README.md +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # NimBLE Beacon Example diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/README.md b/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/README.md index 03bd0ae83c..d575068394 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/README.md +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # NimBLE Connection Example diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/README.md b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/README.md index 9be317a527..ca3b0bbf7e 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/README.md +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # NimBLE GATT Server Example diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/README.md b/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/README.md index d652ffb4b3..ec6f83fcfc 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/README.md +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # NimBLE Security Example diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/README.md b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/README.md index 3b8c083b8f..f2fccb3c8f 100644 --- a/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/cent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE ACL Latency Test - Central diff --git a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/README.md b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/README.md index 8267c661ac..3d465a65df 100644 --- a/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_acl_latency/periph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE ACL Latency Test - Peripheral diff --git a/examples/bluetooth/bluedroid/ble/ble_ancs/README.md b/examples/bluetooth/bluedroid/ble/ble_ancs/README.md index da4d0ab4d0..bb1c60bdb9 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ancs/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_ancs/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE ANCS Example diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md index 4a886f60f0..c6b36140d0 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE Compatibility Test Example diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md index 918968fafe..3acd9e49d9 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Eddystone Example diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md index f0251f4412..92cbfac7a4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Eddystone Example 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 index 7649b1e653..494300f530 100644 --- 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 @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Encrypted Advertising Data Central Example (Bluedroid) 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 index 95e86da46b..1e7b550ad3 100644 --- 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 @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Encrypted Advertising Data Peripheral Example (Bluedroid) 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 0bb49a7da4..44759b647e 100644 --- a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE HID Example diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md b/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md index 065a2efe83..86e260ea27 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF iBeacon demo 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 51c95b7401..77222e2e62 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 @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Multiple Connection Central Example 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 2eb99a15f5..205f6eb87d 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 @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Multiple Connection Peripheral Example diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md b/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md index 72ad1f99b1..ef6d53c974 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_spp_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF SPP GATT CLIENT demo diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md b/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md index d9b16345ab..f6f11a3135 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_spp_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | ## ESP-IDF GATT SERVER SPP Example 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 f7a5b0375d..3b1b485866 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE throughput GATT CLIENT Test 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 c540c43760..a3f55acbfe 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/README.md +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE throughput GATT SERVER Test diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/README.md b/examples/bluetooth/bluedroid/ble/gatt_client/README.md index d7348f8ed1..d2f47736b5 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Gatt Client Example diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md b/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md index f6ab4b81a2..5ad0e10928 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Gatt Security Client Example diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md b/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md index 337689ebc7..712547bcdf 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Gatt Security Server Example diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/README.md b/examples/bluetooth/bluedroid/ble/gatt_server/README.md index 07c4481b61..ee1422ba55 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Gatt Server Example 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 6296ff6ad3..6922255151 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Gatt Server Service Table Example diff --git a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md index af422337b0..ef7a0210ba 100644 --- a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md +++ b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Gatt Client Multi Connection Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md index c94cd0d3ff..5d9f2da65b 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Gatt Security Client Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md index ae64baa5a6..f92d7f2a6e 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE50 Security Server Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/README.md b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/README.md index b94fd36a80..2e13ce40e8 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE 50 throughput GATT CLIENT Test diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/README.md b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/README.md index 70e7f2f6ae..97d33e45dd 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble50_throughput/throughput_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BLE 50 throughput GATT SERVER Test diff --git a/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_central/README.md b/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_central/README.md index 8c09d5de74..6f26ff4190 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_central/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_central/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Connection Subrating Central Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_peripheral/README.md b/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_peripheral/README.md index 7b1c23d53f..b341e1de6c 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_peripheral/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_conn_subrating_peripheral/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Connection Subrating Peripheral Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_connection_central_with_cte/README.md b/examples/bluetooth/bluedroid/ble_50/ble_connection_central_with_cte/README.md index 75ed052729..b6775870b3 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_connection_central_with_cte/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_connection_central_with_cte/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | --------- | -------- | -------- | # ESP-IDF BLE Connection Central with CTE Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_connection_peripheral_with_cte/README.md b/examples/bluetooth/bluedroid/ble_50/ble_connection_peripheral_with_cte/README.md index 12cca1d525..f9520a4244 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_connection_peripheral_with_cte/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_connection_peripheral_with_cte/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | --------- | -------- | -------- | # ESP-IDF BLE Connection Peripheral with CTE Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser/README.md b/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser/README.md index 7822109fb3..c282f137de 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Periodic Advertiser With Response (PAwR) Advertiser Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser_conn/README.md b/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser_conn/README.md index 626e236c36..c913833c8c 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser_conn/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_pawr_advertiser_conn/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Periodic Advertiser With Response (PAwR) Advertiser Connection Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_pawr_synchronizer/README.md b/examples/bluetooth/bluedroid/ble_50/ble_pawr_synchronizer/README.md index 7f5e05cc4e..f05a44a874 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_pawr_synchronizer/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_pawr_synchronizer/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # ESP-IDF PAwR Synchronizer Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_periodic_adv_with_cte/README.md b/examples/bluetooth/bluedroid/ble_50/ble_periodic_adv_with_cte/README.md index 42d37138e1..a9f0de95dc 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_periodic_adv_with_cte/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_periodic_adv_with_cte/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | --------- | -------- | -------- | # ESP-IDF BLE Periodic Advertising with CTE Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_periodic_sync_with_cte/README.md b/examples/bluetooth/bluedroid/ble_50/ble_periodic_sync_with_cte/README.md index 7528592d0e..27ce29e47e 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_periodic_sync_with_cte/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_periodic_sync_with_cte/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | --------- | -------- | -------- | # ESP-IDF BLE Periodic Sync with CTE Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_power_control_central/README.md b/examples/bluetooth/bluedroid/ble_50/ble_power_control_central/README.md index 1fa3b88ba3..517d76a223 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_power_control_central/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_power_control_central/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Power Control Central Example diff --git a/examples/bluetooth/bluedroid/ble_50/ble_power_control_peripheral/README.md b/examples/bluetooth/bluedroid/ble_50/ble_power_control_peripheral/README.md index cb6310ef8c..851c1b6b9a 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble_power_control_peripheral/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble_power_control_peripheral/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Power Control Peripheral Example diff --git a/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md b/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md index 3f7a212d7d..09a8bb6ece 100644 --- a/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md +++ b/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | #ESP-IDF Multi Adv Example diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md b/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md index cc9a06c40e..fc2f6827c3 100644 --- a/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md +++ b/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP_IDF Periodic Adv Example diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md b/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md index 6cf9dceebb..7c9e1dc9b6 100644 --- a/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md +++ b/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF Periodic Sync Example diff --git a/examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/README.md b/examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/README.md index 97adc5a665..29e7c50e7c 100644 --- a/examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/README.md +++ b/examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | ESP-IDF UART HCI Host ===================== diff --git a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/README.md b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/README.md index 1aba998ec0..82dcfeeac1 100644 --- a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/README.md +++ b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | ESP-IDF Gattc and Gatts Coexistence example ============================================== diff --git a/examples/bluetooth/esp_hid_device/README.md b/examples/bluetooth/esp_hid_device/README.md index 7a80a5d443..be44591cbf 100644 --- a/examples/bluetooth/esp_hid_device/README.md +++ b/examples/bluetooth/esp_hid_device/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BT/BLE HID Device Demo diff --git a/examples/bluetooth/esp_hid_host/README.md b/examples/bluetooth/esp_hid_host/README.md index 0f4c02f76b..d95ebee85c 100644 --- a/examples/bluetooth/esp_hid_host/README.md +++ b/examples/bluetooth/esp_hid_host/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF BT/BLE HID Host Demo diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/README.md b/examples/bluetooth/hci/ble_adv_scan_combined/README.md index 20ea4ac560..a310afd2a1 100644 --- a/examples/bluetooth/hci/ble_adv_scan_combined/README.md +++ b/examples/bluetooth/hci/ble_adv_scan_combined/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | ESP-IDF Combined Bluetooth advertising and scanning =================================================== diff --git a/examples/bluetooth/hci/controller_vhci_ble_adv/README.md b/examples/bluetooth/hci/controller_vhci_ble_adv/README.md index 7feb7000d1..f576f89a91 100644 --- a/examples/bluetooth/hci/controller_vhci_ble_adv/README.md +++ b/examples/bluetooth/hci/controller_vhci_ble_adv/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | ESP-IDF VHCI ble_advertising app ================================ diff --git a/examples/bluetooth/nimble/ble_ancs/README.md b/examples/bluetooth/nimble/ble_ancs/README.md index 7180d04acc..d33f0d059d 100644 --- a/examples/bluetooth/nimble/ble_ancs/README.md +++ b/examples/bluetooth/nimble/ble_ancs/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # ESP-IDF NimBLE ANCS Example diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/README.md b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/README.md index 2d7be7843f..9b3f1e0b6c 100644 --- a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/README.md +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | --------- | -------- | -------- | # Bluetooth LE Direction Finding Example (Periodic Advertiser With CTE) diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/README.md b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/README.md index 3a32e624d9..47e98476b9 100644 --- a/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/README.md +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | --------- | -------- | -------- | # Bluetooth LE Direction Finding Example (Periodic Sync with CTE) diff --git a/examples/bluetooth/nimble/ble_cts/cts_cent/README.md b/examples/bluetooth/nimble/ble_cts/cts_cent/README.md index 571c49f32a..019abfbabc 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_cent/README.md +++ b/examples/bluetooth/nimble/ble_cts/cts_cent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE CTS Cent Example diff --git a/examples/bluetooth/nimble/ble_cts/cts_prph/README.md b/examples/bluetooth/nimble/ble_cts/cts_prph/README.md index e84491233e..023438ed00 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_prph/README.md +++ b/examples/bluetooth/nimble/ble_cts/cts_prph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Current Time Service Example diff --git a/examples/bluetooth/nimble/ble_dynamic_service/README.md b/examples/bluetooth/nimble/ble_dynamic_service/README.md index 81158bfcfd..be2afc2a13 100644 --- a/examples/bluetooth/nimble/ble_dynamic_service/README.md +++ b/examples/bluetooth/nimble/ble_dynamic_service/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Dynamic Service Example diff --git a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/README.md b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/README.md index 0f10cfea7d..b6bd899953 100644 --- a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/README.md +++ b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_cent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Encrypted Advertising Data Central Example diff --git a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/README.md b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/README.md index ceb55e0060..ed507c94d4 100644 --- a/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/README.md +++ b/examples/bluetooth/nimble/ble_enc_adv_data/enc_adv_data_prph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Encrypted Advertising Data Peripheral Example diff --git a/examples/bluetooth/nimble/ble_gattc_gatts_coex/README.md b/examples/bluetooth/nimble/ble_gattc_gatts_coex/README.md index 3d91b02206..536e04dda4 100644 --- a/examples/bluetooth/nimble/ble_gattc_gatts_coex/README.md +++ b/examples/bluetooth/nimble/ble_gattc_gatts_coex/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE GATTC GATTS Coex Example diff --git a/examples/bluetooth/nimble/ble_htp/htp_cent/README.md b/examples/bluetooth/nimble/ble_htp/htp_cent/README.md index b7546d3547..46228ed8fb 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_cent/README.md +++ b/examples/bluetooth/nimble/ble_htp/htp_cent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE HTP Cent Example diff --git a/examples/bluetooth/nimble/ble_htp/htp_prph/README.md b/examples/bluetooth/nimble/ble_htp/htp_prph/README.md index 365f877e6a..a12947d00a 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_prph/README.md +++ b/examples/bluetooth/nimble/ble_htp/htp_prph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Heart Rate Measurement Example diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/README.md b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/README.md index 6749acc696..0de07e7330 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/README.md +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Central L2CAP COC Example diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/README.md b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/README.md index a4dd4f0357..881c7e9f61 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/README.md +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Peripheral L2CAP COC Example diff --git a/examples/bluetooth/nimble/ble_multi_adv/README.md b/examples/bluetooth/nimble/ble_multi_adv/README.md index 4fe27bda3f..03fe12d620 100644 --- a/examples/bluetooth/nimble/ble_multi_adv/README.md +++ b/examples/bluetooth/nimble/ble_multi_adv/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Multi Adv Example diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md index 8f3339a66e..a742c780b7 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Multiple Connection Central Example diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md index 95d7358bbd..b60cf69ed7 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Multiple Connection Peripheral Example diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/README.md b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/README.md index 7fce880ce1..e8a4429ac0 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/README.md +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Periodic Advertiser With Response (PAwR) Advertiser Example diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/README.md b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/README.md index 23198ac9dc..afc2dd7d9e 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/README.md +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Periodic Advertiser With Response (PAwR) Sync Example diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/README.md b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/README.md index a8bc010ff3..22f26a484c 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/README.md +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Periodic Advertiser With Response (PAwR) Advertiser Connection Example diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/README.md b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/README.md index a6858b0dbf..3af5b6c95a 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/README.md +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | --------- | -------- | -------- | # BLE Periodic Advertiser With Response (PAwR) Sync Connection Example diff --git a/examples/bluetooth/nimble/ble_periodic_adv/README.md b/examples/bluetooth/nimble/ble_periodic_adv/README.md index e5f88e084d..0a754ef829 100644 --- a/examples/bluetooth/nimble/ble_periodic_adv/README.md +++ b/examples/bluetooth/nimble/ble_periodic_adv/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Periodic Advertiser Example diff --git a/examples/bluetooth/nimble/ble_periodic_sync/README.md b/examples/bluetooth/nimble/ble_periodic_sync/README.md index 2d9cd490e8..01c4c1affd 100644 --- a/examples/bluetooth/nimble/ble_periodic_sync/README.md +++ b/examples/bluetooth/nimble/ble_periodic_sync/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Periodic Sync Example diff --git a/examples/bluetooth/nimble/ble_phy/phy_cent/README.md b/examples/bluetooth/nimble/ble_phy/phy_cent/README.md index 577e115f53..a583aee641 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_cent/README.md +++ b/examples/bluetooth/nimble/ble_phy/phy_cent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Central PHY Example diff --git a/examples/bluetooth/nimble/ble_phy/phy_prph/README.md b/examples/bluetooth/nimble/ble_phy/phy_prph/README.md index 68ed3e3cc2..14bbafec06 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_prph/README.md +++ b/examples/bluetooth/nimble/ble_phy/phy_prph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Peripheral PHY Example diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/README.md b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/README.md index bed629eaf9..3575eeaea8 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/README.md +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Central Proximity Sensor Example diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/README.md b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/README.md index a3323cf122..30313e20af 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/README.md +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Peripheral Proximity Sensor Example diff --git a/examples/bluetooth/nimble/ble_spp/spp_client/README.md b/examples/bluetooth/nimble/ble_spp/spp_client/README.md index 25cb257aff..e8d9076d09 100644 --- a/examples/bluetooth/nimble/ble_spp/spp_client/README.md +++ b/examples/bluetooth/nimble/ble_spp/spp_client/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE SPP central example diff --git a/examples/bluetooth/nimble/ble_spp/spp_server/README.md b/examples/bluetooth/nimble/ble_spp/spp_server/README.md index 8b2adb4d14..bdccd1ef8a 100644 --- a/examples/bluetooth/nimble/ble_spp/spp_server/README.md +++ b/examples/bluetooth/nimble/ble_spp/spp_server/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE SPP peripheral example diff --git a/examples/bluetooth/nimble/blecent/README.md b/examples/bluetooth/nimble/blecent/README.md index 914446f130..2026784f50 100644 --- a/examples/bluetooth/nimble/blecent/README.md +++ b/examples/bluetooth/nimble/blecent/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Central Example diff --git a/examples/bluetooth/nimble/blecsc/README.md b/examples/bluetooth/nimble/blecsc/README.md index aab033e044..63bfee6555 100644 --- a/examples/bluetooth/nimble/blecsc/README.md +++ b/examples/bluetooth/nimble/blecsc/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | diff --git a/examples/bluetooth/nimble/blehr/README.md b/examples/bluetooth/nimble/blehr/README.md index c4c1f62a69..866c67e8d6 100644 --- a/examples/bluetooth/nimble/blehr/README.md +++ b/examples/bluetooth/nimble/blehr/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Heart Rate Measurement Example diff --git a/examples/bluetooth/nimble/bleprph/README.md b/examples/bluetooth/nimble/bleprph/README.md index 78e815aad4..8f23ac1c5a 100644 --- a/examples/bluetooth/nimble/bleprph/README.md +++ b/examples/bluetooth/nimble/bleprph/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Peripheral Example diff --git a/examples/bluetooth/nimble/bleprph_host_only/README.md b/examples/bluetooth/nimble/bleprph_host_only/README.md index d60b04e5ba..4225ab1ff9 100644 --- a/examples/bluetooth/nimble/bleprph_host_only/README.md +++ b/examples/bluetooth/nimble/bleprph_host_only/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # BLE Peripheral Example diff --git a/examples/bluetooth/nimble/hci/README.md b/examples/bluetooth/nimble/hci/README.md index 23c81f3c25..3c8b0d216a 100644 --- a/examples/bluetooth/nimble/hci/README.md +++ b/examples/bluetooth/nimble/hci/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C2 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | -| ----------------- | -------- | -------- | -------- | --------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | +| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | ESP-IDF UART HCI Controller =========================== diff --git a/examples/bluetooth/nimble/power_save/README.md b/examples/bluetooth/nimble/power_save/README.md index 2cbea64861..4553bce320 100644 --- a/examples/bluetooth/nimble/power_save/README.md +++ b/examples/bluetooth/nimble/power_save/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | Bluetooth Power Save Example ================================= diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md b/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md index 6db1595be7..84e7eafbb4 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # Throughput blecent Example diff --git a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/README.md b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/README.md index d43009f167..db36be9ce8 100644 --- a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/README.md +++ b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # Throughput bleprph Example