From 6f827995f40afa169e8ea5d9a2d795826aa3ed76 Mon Sep 17 00:00:00 2001 From: Mayank Tyagi Date: Tue, 17 Mar 2026 15:43:11 +0530 Subject: [PATCH] feat(nimble): ADD BLE HCI logging support for ESP Insights --- components/bt/CMakeLists.txt | 8 ++ components/bt/Kconfig | 6 ++ components/bt/common/hci_log/bt_hci_log.c | 10 +++ .../bt/common/hci_log/bt_hci_log_insights.c | 90 +++++++++++++++++++ .../hci_log/include/hci_log/bt_hci_log.h | 13 ++- .../bt/common/include/bt_ble_insights.h | 21 +++++ components/bt/common/include/bt_common.h | 17 +++- components/bt/common/include/bt_user_config.h | 10 ++- .../bt/host/bluedroid/api/esp_bluedroid_hci.c | 11 ++- components/bt/host/bluedroid/hci/hci_hal_h4.c | 9 +- .../host/nimble/esp-hci/src/esp_nimble_hci.c | 23 +++-- components/bt/host/nimble/nimble | 2 +- .../host/nimble/port/include/esp_nimble_cfg.h | 9 ++ 13 files changed, 213 insertions(+), 16 deletions(-) create mode 100644 components/bt/common/hci_log/bt_hci_log_insights.c create mode 100644 components/bt/common/include/bt_ble_insights.h diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 379ab86bfb4..1c7b71d02b4 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -133,6 +133,7 @@ if(CONFIG_BT_ENABLED) list(APPEND srcs "common/btc/core/btc_alarm.c" "common/api/esp_blufi_api.c" "common/hci_log/bt_hci_log.c" + "common/hci_log/bt_hci_log_insights.c" "common/btc/core/btc_manage.c" "common/btc/core/btc_task.c" "common/btc/profile/esp/blufi/blufi_prf.c" @@ -1014,6 +1015,13 @@ if(DEFINED CONFIG_BLE_LOG_PRPH_UART_DMA_PORT) endif() endif() +idf_component_get_property(bt_component_type bt COMPONENT_TYPE) +if(bt_component_type STREQUAL "LIBRARY") + idf_component_optional_requires(PRIVATE ble_insights) +else() + idf_component_optional_requires(INTERFACE ble_insights) +endif() + if(CONFIG_BLE_COMPRESSED_LOG_ENABLE) if(LOG_COMPRESSION_TARGET) add_dependencies(${COMPONENT_LIB} ${LOG_COMPRESSION_TARGET}) diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 417a8c18e9f..691ca1f433e 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -109,6 +109,12 @@ menu "Bluetooth" This option is to configure the buffer size of the hci adv report cache in hci debug mode. This is a ring buffer, the new data will overwrite the oldest data if the buffer is full. + config BT_HCI_LOG_INSIGHTS_ENABLE + depends on BT_HCI_LOG_DEBUG_EN + bool "Enable Insights for HCI LOGS BT Stack" + help + Enable this to allow the BT stack to send diagnostic events. + endmenu menuconfig BLE_MESH diff --git a/components/bt/common/hci_log/bt_hci_log.c b/components/bt/common/hci_log/bt_hci_log.c index fef3760b3f2..0437cb50e35 100644 --- a/components/bt/common/hci_log/bt_hci_log.c +++ b/components/bt/common/hci_log/bt_hci_log.c @@ -35,6 +35,16 @@ static const char s_hex_to_char_mapping[16] = { static bt_hci_log_t g_bt_hci_log_data_ctl = {0}; static bt_hci_log_t g_bt_hci_log_adv_ctl = {0}; +uint8_t bt_hci_log_h4_type_to_data_type(uint8_t h4_type) +{ + switch (h4_type) { + case 0x05: + return HCI_LOG_DATA_TYPE_ISO_DATA; + default: + return h4_type; + } +} + esp_err_t bt_hci_log_init(void) { uint8_t *g_bt_hci_log_data_buffer = NULL; diff --git a/components/bt/common/hci_log/bt_hci_log_insights.c b/components/bt/common/hci_log/bt_hci_log_insights.c new file mode 100644 index 00000000000..8ab832efa4f --- /dev/null +++ b/components/bt/common/hci_log/bt_hci_log_insights.c @@ -0,0 +1,90 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" + +#include "esp_timer.h" +#include "bt_ble_insights.h" +#include "bt_common.h" +#include "hci_log/bt_hci_log.h" + +#if (BT_HCI_LOG_INCLUDED == TRUE) && BT_HCI_INSIGHTS_INCLUDED +static uint8_t s_hci_log_seq_num = 0; +static portMUX_TYPE s_hci_log_mux = portMUX_INITIALIZER_UNLOCKED; + +#define HCI_LOG_INSIGHTS_LINE_SIZE 128U +#define HCI_LOG_INSIGHTS_TS_LEN 8U + +static const char *bt_hci_log_insights_label(uint8_t data_type) +{ + switch (data_type) { + case HCI_LOG_DATA_TYPE_COMMAND: + return "C"; + case HCI_LOG_DATA_TYPE_H2C_ACL: + return "H"; + case HCI_LOG_DATA_TYPE_SCO: + return "S"; + case HCI_LOG_DATA_TYPE_EVENT: + return "E"; + case HCI_LOG_DATA_TYPE_ADV: + return "ADV"; + case HCI_LOG_DATA_TYPE_C2H_ACL: + return "D"; + case HCI_LOG_DATA_TYPE_ISO_DATA: + return "I"; + default: + return NULL; + } +} + +void bt_hci_log_record_insights(uint8_t data_type, const uint8_t *data, uint16_t data_len) +{ + const char *label = bt_hci_log_insights_label(data_type); + char line[HCI_LOG_INSIGHTS_LINE_SIZE]; + uint8_t ts_bytes[HCI_LOG_INSIGHTS_TS_LEN]; + uint64_t timestamp; + uint8_t seq_num; + int offset; + + if (!BT_BLE_INSIGHTS_AVAILABLE || label == NULL || data == NULL || data_len == 0) { + return; + } + + portENTER_CRITICAL(&s_hci_log_mux); + seq_num = ++s_hci_log_seq_num; + portEXIT_CRITICAL(&s_hci_log_mux); + + timestamp = esp_timer_get_time(); + memcpy(ts_bytes, ×tamp, sizeof(ts_bytes)); + + offset = snprintf(line, sizeof(line), "%02x %s:", (unsigned int)seq_num, label); + if (offset < 0 || (size_t)offset >= sizeof(line) - 1) { + return; + } + + for (size_t i = 0; i < sizeof(ts_bytes) && offset <= (int)sizeof(line) - 3; i++) { + offset += snprintf(&line[offset], sizeof(line) - offset, "%02x", ts_bytes[i]); + } + + if (offset < 0 || (size_t)offset >= sizeof(line) - 1) { + return; + } + + line[offset++] = ' '; + line[offset] = '\0'; + + for (uint16_t i = 0; i < data_len && offset <= (int)sizeof(line) - 3; i++) { + offset += snprintf(&line[offset], sizeof(line) - offset, "%02X", data[i]); + } + + ble_insights_log(line); +} +#endif diff --git a/components/bt/common/hci_log/include/hci_log/bt_hci_log.h b/components/bt/common/hci_log/include/hci_log/bt_hci_log.h index 4646862194c..8174bc06c95 100644 --- a/components/bt/common/hci_log/include/hci_log/bt_hci_log.h +++ b/components/bt/common/hci_log/include/hci_log/bt_hci_log.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -102,6 +102,17 @@ esp_err_t bt_hci_log_record_hci_data(uint8_t data_type, uint8_t *data, uint16_t */ esp_err_t bt_hci_log_record_hci_adv(uint8_t data_type, uint8_t *data, uint8_t data_len); +/** + * + * @brief Convert HCI H4 packet type to HCI log data type. + * + * @param h4_type : HCI H4 packet type byte + * + * @return corresponding HCI log data type + * + */ +uint8_t bt_hci_log_h4_type_to_data_type(uint8_t h4_type); + #ifdef __cplusplus } #endif diff --git a/components/bt/common/include/bt_ble_insights.h b/components/bt/common/include/bt_ble_insights.h new file mode 100644 index 00000000000..c433eed982e --- /dev/null +++ b/components/bt/common/include/bt_ble_insights.h @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __BT_BLE_INSIGHTS_H__ +#define __BT_BLE_INSIGHTS_H__ + +#if __has_include("ble_insights.h") +#include "ble_insights.h" +#define BT_BLE_INSIGHTS_AVAILABLE 1 +#else +#define BT_BLE_INSIGHTS_AVAILABLE 0 +static inline void ble_insights_log(const char *log) +{ + (void)log; +} +#endif + +#endif /* __BT_BLE_INSIGHTS_H__ */ diff --git a/components/bt/common/include/bt_common.h b/components/bt/common/include/bt_common.h index 372ea68e7e9..343600f36e6 100644 --- a/components/bt/common/include/bt_common.h +++ b/components/bt/common/include/bt_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -100,6 +100,13 @@ #define BT_HCI_LOG_INCLUDED FALSE #endif +// HCI INSIGHTS LOG +#if UC_BT_HCI_LOG_INSIGHTS_ENABLE +#define BT_HCI_INSIGHTS_INCLUDED UC_BT_HCI_LOG_INSIGHTS_ENABLE +#else +#define BT_HCI_INSIGHTS_INCLUDED FALSE +#endif + // HCI LOG TO SPI #if UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED #define BT_BLE_LOG_SPI_OUT_HCI_ENABLED UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED @@ -117,10 +124,10 @@ #if UC_BT_HCI_LOG_DATA_BUFFER_SIZE #define HCI_LOG_DATA_BUFFER_SIZE UC_BT_HCI_LOG_DATA_BUFFER_SIZE #else -#define HCI_BUFFER_SIZE (5) +#define HCI_LOG_DATA_BUFFER_SIZE (5) #endif -#if UC_BT_HCI_ADV_BUFFER_SIZE +#if UC_BT_HCI_LOG_ADV_BUFFER_SIZE #define HCI_LOG_ADV_BUFFER_SIZE UC_BT_HCI_LOG_ADV_BUFFER_SIZE #else #define HCI_LOG_ADV_BUFFER_SIZE (5) @@ -277,4 +284,8 @@ typedef struct { #define BD_ADDR_LEN 6 /* Device address length */ typedef UINT8 BD_ADDR[BD_ADDR_LEN]; /* Device address */ +#if (BT_HCI_LOG_INCLUDED == TRUE) && BT_HCI_INSIGHTS_INCLUDED +void bt_hci_log_record_insights(uint8_t data_type, const uint8_t *data, uint16_t data_len); +#endif + #endif /* _BT_COMMON_H_ */ diff --git a/components/bt/common/include/bt_user_config.h b/components/bt/common/include/bt_user_config.h index b9dd69d8cb8..f9858c41688 100644 --- a/components/bt/common/include/bt_user_config.h +++ b/components/bt/common/include/bt_user_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -176,4 +176,12 @@ #define UC_BT_HCI_LOG_ADV_BUFFER_SIZE (5) #endif + +// HCI LOG INSIGHTS +#ifdef CONFIG_BT_HCI_LOG_INSIGHTS_ENABLE +#define UC_BT_HCI_LOG_INSIGHTS_ENABLE TRUE +#else +#define UC_BT_HCI_LOG_INSIGHTS_ENABLE FALSE +#endif + #endif /* __BT_USER_CONFIG_H__ */ diff --git a/components/bt/host/bluedroid/api/esp_bluedroid_hci.c b/components/bt/host/bluedroid/api/esp_bluedroid_hci.c index 4ddc169a97c..2c80581722d 100644 --- a/components/bt/host/bluedroid/api/esp_bluedroid_hci.c +++ b/components/bt/host/bluedroid/api/esp_bluedroid_hci.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ #include #include "esp_log.h" #include "esp_bluedroid_hci.h" +#include "bt_common.h" #include "common/bt_target.h" #include "hci/hci_trans_int.h" #if (BT_CONTROLLER_INCLUDED == TRUE) @@ -68,7 +69,13 @@ bool hci_host_check_send_available(void) void hci_host_send_packet(uint8_t *data, uint16_t len) { #if (BT_HCI_LOG_INCLUDED == TRUE) - bt_hci_log_record_hci_data(data[0], &data[1], len - 1); + if (data != NULL && len > 1) { + uint8_t data_type = bt_hci_log_h4_type_to_data_type(data[0]); + bt_hci_log_record_hci_data(data_type, &data[1], (uint16_t)(len - 1)); +#if BT_HCI_INSIGHTS_INCLUDED + bt_hci_log_record_insights(data_type, &data[1], (uint16_t)(len - 1)); +#endif + } #endif #if CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED ble_log_spi_out_hci_write(BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM, data, len); diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index c4c08dd939d..097b4bd7f58 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -34,6 +34,7 @@ #include "esp_bt.h" #endif #include "esp_bluedroid_hci.h" +#include "bt_common.h" #if (C2H_FLOW_CONTROL_INCLUDED == TRUE) #include "l2c_int.h" @@ -601,14 +602,20 @@ void bt_record_hci_data(uint8_t *data, uint16_t len) #endif // (BLE_50_FEATURE_SUPPORT == TRUE) )) { bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, &data[2], len - 2); +#if BT_HCI_INSIGHTS_INCLUDED + bt_hci_log_record_insights(HCI_LOG_DATA_TYPE_ADV, &data[2], len - 2); +#endif } else { uint8_t data_type; - if (data[0] == HCI_LOG_DATA_TYPE_ISO_DATA) { + if (data[0] == DATA_TYPE_ISO) { data_type = HCI_LOG_DATA_TYPE_ISO_DATA; } else { data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : data[0]); } bt_hci_log_record_hci_data(data_type, &data[1], len - 1); +#if BT_HCI_INSIGHTS_INCLUDED + bt_hci_log_record_insights(data_type, &data[1], len - 1); +#endif } #endif // (BT_HCI_LOG_INCLUDED == TRUE) } diff --git a/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c b/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c index 02065c08538..cc36004685a 100644 --- a/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c +++ b/components/bt/host/nimble/esp-hci/src/esp_nimble_hci.c @@ -78,7 +78,11 @@ void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, void esp_vhci_host_send_packet_wrapper(uint8_t *data, uint16_t len) { #if (BT_HCI_LOG_INCLUDED == TRUE) - bt_hci_log_record_hci_data(data[0], &data[1], len - 1); + uint8_t data_type = bt_hci_log_h4_type_to_data_type(data[0]); + bt_hci_log_record_hci_data(data_type, &data[1], len - 1); +#if BT_HCI_INSIGHTS_INCLUDED + bt_hci_log_record_insights(data_type, &data[1], len - 1); +#endif #endif #if CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED ble_log_spi_out_hci_write(BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM, data, len); @@ -237,17 +241,22 @@ static void dummy_controller_rcv_pkt_ready(void) void bt_record_hci_data(uint8_t *data, uint16_t len) { #if (BT_HCI_LOG_INCLUDED == TRUE) - if ((data[0] == BLE_HCI_UART_H4_EVT) && (data[1] == BLE_HCI_EVCODE_LE_META) && ((data[3] == BLE_HCI_LE_SUBEV_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) + if (len < 2) { + return; + } + if ((len >= 4) && (data[0] == BLE_HCI_UART_H4_EVT) && (data[1] == BLE_HCI_EVCODE_LE_META) && ((data[3] == BLE_HCI_LE_SUBEV_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT))) { bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, &data[2], len - 2); +#if BT_HCI_INSIGHTS_INCLUDED + bt_hci_log_record_insights(HCI_LOG_DATA_TYPE_ADV, &data[2], len - 2); +#endif } else { uint8_t data_type; - if (data[0] == HCI_LOG_DATA_TYPE_ISO_DATA) { - data_type = HCI_LOG_DATA_TYPE_ISO_DATA; - } else { - data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : data[0]); - } + data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : bt_hci_log_h4_type_to_data_type(data[0])); bt_hci_log_record_hci_data(data_type, &data[1], len - 1); +#if BT_HCI_INSIGHTS_INCLUDED + bt_hci_log_record_insights(data_type, &data[1], len - 1); +#endif } #endif // (BT_HCI_LOG_INCLUDED == TRUE) } diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index 1022de21ca9..df2e4440e0a 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit 1022de21ca9eb62af86b2b59024b29bff17f29c8 +Subproject commit df2e4440e0add798a2893f67d548d0e80204d6d0 diff --git a/components/bt/host/nimble/port/include/esp_nimble_cfg.h b/components/bt/host/nimble/port/include/esp_nimble_cfg.h index d50070e5711..673a0c58040 100644 --- a/components/bt/host/nimble/port/include/esp_nimble_cfg.h +++ b/components/bt/host/nimble/port/include/esp_nimble_cfg.h @@ -2281,4 +2281,13 @@ #define MYNEWT_VAL_BLE_SCAN_ALLOW_ENH_ADI_FILTER (0) #endif #endif + +#ifndef MYNEWT_VAL_BT_NIMBLE_INSIGHTS_ENABLE +#ifdef CONFIG_BT_NIMBLE_INSIGHTS_ENABLE +#define MYNEWT_VAL_BT_NIMBLE_INSIGHTS_ENABLE CONFIG_BT_NIMBLE_INSIGHTS_ENABLE +#else +#define MYNEWT_VAL_BT_NIMBLE_INSIGHTS_ENABLE (0) +#endif +#endif + #endif