From 0efee1745ce00d53a7939206a4da608d7300eabb Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Tue, 9 Apr 2024 15:31:54 +0800 Subject: [PATCH 1/3] feat(bt/bluedroid): add api to setnd vendor hci command --- .../bt/host/bluedroid/api/esp_gap_ble_api.c | 30 ++++++- .../api/include/api/esp_gap_ble_api.h | 33 +++++++ .../bt/host/bluedroid/bta/dm/bta_dm_act.c | 8 ++ .../bt/host/bluedroid/bta/dm/bta_dm_api.c | 15 ++++ .../bt/host/bluedroid/bta/dm/bta_dm_main.c | 1 + .../bluedroid/bta/dm/include/bta_dm_int.h | 11 +++ .../host/bluedroid/bta/include/bta/bta_api.h | 6 ++ .../btc/profile/std/gap/btc_gap_ble.c | 86 ++++++++++++++++++- .../btc/profile/std/include/btc_gap_ble.h | 9 +- .../bt/host/bluedroid/stack/btm/btm_devctl.c | 5 +- 10 files changed, 199 insertions(+), 5 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_gap_ble_api.c b/components/bt/host/bluedroid/api/esp_gap_ble_api.c index 5db7b62973..5aa2157277 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1599,3 +1599,31 @@ esp_err_t esp_ble_gap_set_periodic_adv_sync_trans_params(esp_bd_addr_t addr, con == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) + +esp_err_t esp_ble_gap_vendor_command_send(esp_ble_vendor_cmd_params_t *vendor_cmd_param) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!vendor_cmd_param || !vendor_cmd_param->p_param_buf || !vendor_cmd_param->param_len) { + return ESP_ERR_NOT_ALLOWED; + } + // If command is not a VSC, return error + if ((vendor_cmd_param->opcode & VENDOR_HCI_CMD_MASK) != VENDOR_HCI_CMD_MASK) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT; + arg.vendor_cmd_send.opcode = vendor_cmd_param->opcode; + arg.vendor_cmd_send.param_len = vendor_cmd_param->param_len; + arg.vendor_cmd_send.p_param_buf = vendor_cmd_param->p_param_buf; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, btc_gap_ble_arg_deep_free) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h b/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h index 3ab210a089..3239a704a4 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h @@ -224,6 +224,7 @@ typedef enum { ESP_GAP_BLE_DTM_TEST_UPDATE_EVT, /*!< when direct test mode state changes, the event comes */ // BLE_INCLUDED ESP_GAP_BLE_ADV_CLEAR_COMPLETE_EVT, /*!< When clear advertising complete, the event comes */ + ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT, /*!< When vendor hci command complete, the event comes */ ESP_GAP_BLE_EVT_MAX, /*!< when maximum advertising event complete, the event comes */ } esp_gap_ble_cb_event_t; @@ -238,6 +239,8 @@ typedef uint8_t esp_gap_ble_channels[ESP_GAP_BLE_CHANNELS_LEN]; /// Scan response data maximum length #define ESP_BLE_SCAN_RSP_DATA_LEN_MAX 31 +#define VENDOR_HCI_CMD_MASK (0x3F << 10) /**!< 0xFC00 */ + /* relate to BTM_BLE_AD_TYPE_xxx in stack/btm_ble_api.h */ /// The type of advertising data(not adv_type) typedef enum { @@ -364,6 +367,15 @@ typedef enum { DTM_TEST_STOP_EVT, } esp_ble_dtm_update_evt_t; +/** + * @brief Vendor HCI command parameters + */ +typedef struct { + uint16_t opcode; /*!< vendor hci command opcode */ + uint8_t param_len; /*!< the length of parameter */ + uint8_t *p_param_buf; /*!< the point of parameter buffer */ +} esp_ble_vendor_cmd_params_t; + #if (BLE_42_FEATURE_SUPPORT == TRUE) /** * @brief DTM TX parameters @@ -1471,6 +1483,14 @@ typedef union { esp_ble_dtm_update_evt_t update_evt; /*!< DTM state change event, 0x00: DTM TX start, 0x01: DTM RX start, 0x02:DTM end */ uint16_t num_of_pkt; /*!< number of packets received, only valid if update_evt is DTM_TEST_STOP_EVT and shall be reported as 0 for a transmitter */ } dtm_state_update; /*!< Event parameter of ESP_GAP_BLE_DTM_TEST_UPDATE_EVT */ + /** + * @brief ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT + */ + struct vendor_cmd_cmpl_evt_param { + uint16_t opcode; /*!< vendor hci command opcode */ + uint16_t param_len; /*!< The length of parameter buffer */ + uint8_t *p_param_buf; /*!< The point of parameter buffer */ + } vendor_cmd_cmpl; /*!< Event parameter of ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT */ } esp_ble_gap_cb_param_t; /** @@ -2540,6 +2560,19 @@ esp_err_t esp_ble_dtm_stop(void); */ esp_err_t esp_ble_gap_clear_advertising(void); +/** + * @brief This function is called to send vendor hci command. + * + * + * + * @param[in] vendor_cmd_param: vendor hci command parameters + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_vendor_command_send(esp_ble_vendor_cmd_params_t *vendor_cmd_param); + #ifdef __cplusplus } #endif diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index 2e0901a6f7..2e8a3563d7 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -729,6 +729,14 @@ void bta_dm_cfg_coex_status (tBTA_DM_MSG *p_data) } #endif +void bta_dm_send_vendor_hci(tBTA_DM_MSG *p_data) +{ + BTM_VendorSpecificCommand(p_data->vendor_hci_cmd.opcode, + p_data->vendor_hci_cmd.param_len, + p_data->vendor_hci_cmd.p_param_buf, + p_data->vendor_hci_cmd.vendor_hci_cb); +} + /******************************************************************************* ** ** Function bta_dm_set_afh_channels diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c index 8fd5f09c07..06d748937d 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -227,6 +227,21 @@ void BTA_DmCfgCoexStatus(UINT8 op, UINT8 type, UINT8 status) } #endif +void BTA_DmsendVendorHciCmd(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf, tBTA_SEND_VENDOR_HCI_CMPL_CBACK p_vendor_cmd_complete_cback) +{ + tBTA_DM_API_SEND_VENDOR_HCI_CMD *p_msg; + if ((p_msg = (tBTA_DM_API_SEND_VENDOR_HCI_CMD *)osi_malloc(sizeof(tBTA_DM_API_SEND_VENDOR_HCI_CMD) + param_len)) != NULL) { + p_msg->hdr.event = BTA_DM_API_SEND_VENDOR_HCI_CMD_EVT; + p_msg->opcode = opcode; + p_msg->param_len = param_len; + p_msg->p_param_buf = (UINT8 *)(p_msg + 1); + memcpy(p_msg->p_param_buf, p_param_buf, param_len); + p_msg->vendor_hci_cb = p_vendor_cmd_complete_cback; + + bta_sys_sendmsg(p_msg); + } +} + #if (CLASSIC_BT_INCLUDED == TRUE) void BTA_DmConfigEir(tBTA_DM_EIR_CONF *eir_config) diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c index 42e67d77b5..d931469fc7 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -65,6 +65,7 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { #if (ESP_COEX_VSC_INCLUDED == TRUE) bta_dm_cfg_coex_status, /* BTA_DM_API_CFG_COEX_ST_EVT */ #endif + bta_dm_send_vendor_hci, /* BTA_DM_API_SEND_VENDOR_HCI_CMD_EVT */ #if (CLASSIC_BT_INCLUDED == TRUE) bta_dm_config_eir, /* BTA_DM_API_CONFIG_EIR_EVT */ bta_dm_set_page_timeout, /* BTA_DM_API_PAGE_TO_SET_EVT */ diff --git a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index a46651d342..4689460a5a 100644 --- a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h @@ -57,6 +57,7 @@ enum { #if (ESP_COEX_VSC_INCLUDED == TRUE) BTA_DM_API_CFG_COEX_ST_EVT, #endif + BTA_DM_API_SEND_VENDOR_HCI_CMD_EVT, #if (CLASSIC_BT_INCLUDED == TRUE) BTA_DM_API_CONFIG_EIR_EVT, BTA_DM_API_PAGE_TO_SET_EVT, @@ -265,6 +266,14 @@ typedef struct { } tBTA_DM_API_CFG_COEX_STATUS; #endif +typedef struct { + BT_HDR hdr; + UINT16 opcode; + UINT8 param_len; + UINT8 *p_param_buf; + tBTA_SEND_VENDOR_HCI_CMPL_CBACK *vendor_hci_cb; +}tBTA_DM_API_SEND_VENDOR_HCI_CMD; + /* data type for BTA_DM_API_CONFIG_EIR_EVT */ typedef struct { BT_HDR hdr; @@ -1162,6 +1171,7 @@ typedef union { #if (ESP_COEX_VSC_INCLUDED == TRUE) tBTA_DM_API_CFG_COEX_STATUS cfg_coex_status; #endif + tBTA_DM_API_SEND_VENDOR_HCI_CMD vendor_hci_cmd; tBTA_DM_API_CONFIG_EIR config_eir; tBTA_DM_API_SET_AFH_CHANNELS set_afh_channels; @@ -1676,6 +1686,7 @@ extern void bta_dm_get_dev_name (tBTA_DM_MSG *p_data); #if (ESP_COEX_VSC_INCLUDED == TRUE) extern void bta_dm_cfg_coex_status(tBTA_DM_MSG *p_data); #endif +extern void bta_dm_send_vendor_hci(tBTA_DM_MSG *p_data); #if (CLASSIC_BT_INCLUDED == TRUE) extern void bta_dm_config_eir (tBTA_DM_MSG *p_data); extern void bta_dm_set_page_timeout (tBTA_DM_MSG *p_data); diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_api.h index 8ba75884f5..54922ade8a 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -417,6 +417,8 @@ typedef void (tBTA_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK) (tBTA_STATUS st typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status); +typedef tBTM_VSC_CMPL_CB tBTA_SEND_VENDOR_HCI_CMPL_CBACK; + typedef tBTM_START_ADV_CMPL_CBACK tBTA_START_ADV_CMPL_CBACK; typedef tBTM_START_STOP_ADV_CMPL_CBACK tBTA_START_STOP_ADV_CMPL_CBACK; @@ -433,6 +435,8 @@ typedef tBTM_SET_LOCAL_PRIVACY_CBACK tBTA_SET_LOCAL_PRIVACY_CBACK; typedef tBTM_CMPL_CB tBTA_CMPL_CB; +typedef tBTM_VSC_CMPL tBTA_VSC_CMPL; + typedef tBTM_TX_POWER_RESULTS tBTA_TX_POWER_RESULTS; typedef tBTM_RSSI_RESULTS tBTA_RSSI_RESULTS; @@ -1744,6 +1748,8 @@ extern void BTA_DmGetDeviceName(tBTA_GET_DEV_NAME_CBACK *p_cback); extern void BTA_DmCfgCoexStatus(UINT8 op, UINT8 type, UINT8 status); #endif +extern void BTA_DmsendVendorHciCmd(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf, tBTA_SEND_VENDOR_HCI_CMPL_CBACK p_vendor_cmd_complete_cback); + /******************************************************************************* ** ** Function BTA_DmGetRemoteName diff --git a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c index f8f87320df..2a636454e6 100644 --- a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1256,6 +1256,42 @@ void btc_dtm_stop_callback(void *p1) } } +static void btc_ble_vendor_hci_cmd_complete_callback(tBTA_VSC_CMPL *p_param) +{ + bool param_invalid = false; + if ((!p_param) || (!p_param->param_len) || (!p_param->p_param_buf)) { + BTC_TRACE_ERROR("%s param error\n", __func__); + param_invalid = true; + } + + esp_ble_gap_cb_param_t param = {0}; + bt_status_t ret; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT; + if (!param_invalid) { + param.vendor_cmd_cmpl.opcode = p_param->opcode; + param.vendor_cmd_cmpl.param_len = p_param->param_len; + param.vendor_cmd_cmpl.p_param_buf = p_param->p_param_buf; + } else { + if (p_param) { + param.vendor_cmd_cmpl.opcode = p_param->opcode; + } else { + param.vendor_cmd_cmpl.opcode = 0; + } + param.vendor_cmd_cmpl.param_len = 0; + param.vendor_cmd_cmpl.p_param_buf = NULL; + } + + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), btc_gap_ble_cb_deep_copy, btc_gap_ble_cb_deep_free); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + void btc_get_whitelist_size(uint16_t *length) { BTM_BleGetWhiteListSize(length); @@ -1598,6 +1634,19 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) break; } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + case BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT: { + btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src; + btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *)p_dest; + if (src->vendor_cmd_send.param_len) { + dst->vendor_cmd_send.p_param_buf = osi_malloc(src->vendor_cmd_send.param_len); + if (dst->vendor_cmd_send.p_param_buf) { + memcpy(dst->vendor_cmd_send.p_param_buf, src->vendor_cmd_send.p_param_buf, src->vendor_cmd_send.param_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + } default: BTC_TRACE_ERROR("Unhandled deep copy %d\n", msg->act); break; @@ -1606,7 +1655,22 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) { + esp_ble_gap_cb_param_t *src = (esp_ble_gap_cb_param_t *)p_src; + esp_ble_gap_cb_param_t *dst = (esp_ble_gap_cb_param_t *) p_dest; + switch (msg->act) { + case ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT: { + if (src->vendor_cmd_cmpl.param_len) { + dst->vendor_cmd_cmpl.p_param_buf = osi_malloc(src->vendor_cmd_cmpl.param_len); + if (dst->vendor_cmd_cmpl.p_param_buf) { + memcpy(dst->vendor_cmd_cmpl.p_param_buf, src->vendor_cmd_cmpl.p_param_buf, + src->vendor_cmd_cmpl.param_len); + } else { + BTC_TRACE_ERROR("%s, malloc failed\n", __func__); + } + } + break; + } default: BTC_TRACE_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); break; @@ -1704,6 +1768,13 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) break; } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + case BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT: { + uint8_t *p_param_buf = ((btc_ble_gap_args_t *)msg->arg)->vendor_cmd_send.p_param_buf; + if (p_param_buf) { + osi_free(p_param_buf); + } + break; + } default: BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); break; @@ -1721,6 +1792,13 @@ void btc_gap_ble_cb_deep_free(btc_msg_t *msg) } break; } + case ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT: { + uint8_t *value = ((esp_ble_gap_cb_param_t *)msg->arg)->vendor_cmd_cmpl.p_param_buf; + if (value) { + osi_free(value); + } + break; + } default: BTC_TRACE_DEBUG("Unhandled deep free %d", msg->act); break; @@ -2192,6 +2270,12 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) btc_ble_dtm_enhance_rx_start(arg_5->dtm_enh_rx_start.rx_channel, arg_5->dtm_enh_rx_start.phy, arg_5->dtm_enh_rx_start.modulation_index, btc_dtm_rx_start_callback); break; #endif // if (BLE_50_FEATURE_SUPPORT == TRUE) + case BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT: + BTA_DmsendVendorHciCmd(arg->vendor_cmd_send.opcode, + arg->vendor_cmd_send.param_len, + arg->vendor_cmd_send.p_param_buf, + btc_ble_vendor_hci_cmd_complete_callback); + break; default: break; } diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h index 3fb5f4b34e..71d89359d9 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -102,6 +102,7 @@ typedef enum { #if (BLE_42_FEATURE_SUPPORT == TRUE) BTC_GAP_BLE_ACT_CLEAR_ADV, #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) + BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT, } btc_gap_ble_act_t; /* btc_ble_gap_args_t */ @@ -248,6 +249,12 @@ typedef union { struct dtm_rx_start_args { uint8_t rx_channel; } dtm_rx_start; + //BTC_DEV_VENDOR_HCI_CMD_EVT + struct vendor_cmd_send_args { + uint16_t opcode; + uint8_t param_len; + uint8_t *p_param_buf; + } vendor_cmd_send; } btc_ble_gap_args_t; #if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/components/bt/host/bluedroid/stack/btm/btm_devctl.c b/components/bt/host/bluedroid/stack/btm/btm_devctl.c index bffb5bbee0..21534d5a76 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -740,8 +740,9 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, break; } default: - break; + break; } +#endif // (BLE_INCLUDED == TRUE) tBTM_VSC_CMPL vcs_cplt_params; /* If there was a callback address for vcs complete, call it */ @@ -752,7 +753,7 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, vcs_cplt_params.p_param_buf = p; (*p_vsc_cplt_cback)(&vcs_cplt_params); /* Call the VSC complete callback function */ } -#endif + } /******************************************************************************* From 9b72c4ef54a86bff999a1d117648702edbaa6b4b Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Mon, 8 Apr 2024 20:16:28 +0800 Subject: [PATCH 2/3] feat(bt/common): Add bluerooth hci layer data stream record --- components/bt/CMakeLists.txt | 2 + components/bt/Kconfig | 25 ++ components/bt/common/hci_log/bt_hci_log.c | 334 ++++++++++++++++++ .../hci_log/include/hci_log/bt_hci_log.h | 108 ++++++ components/bt/common/include/bt_common.h | 20 +- components/bt/common/include/bt_user_config.h | 20 +- .../bt/host/bluedroid/api/esp_bluedroid_hci.c | 4 + .../bt/host/bluedroid/api/esp_bt_main.c | 12 +- components/bt/host/bluedroid/hci/hci_hal_h4.c | 13 +- .../host/nimble/esp-hci/src/esp_nimble_hci.c | 27 +- 10 files changed, 559 insertions(+), 6 deletions(-) create mode 100644 components/bt/common/hci_log/bt_hci_log.c create mode 100644 components/bt/common/hci_log/include/hci_log/bt_hci_log.h diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 63f7b1e9c5..c52392971c 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -30,6 +30,7 @@ set(common_include_dirs common/api/include/api common/btc/profile/esp/blufi/include common/btc/profile/esp/include + common/hci_log/include ) set(ble_mesh_include_dirs @@ -111,6 +112,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/btc/core/btc_manage.c" "common/btc/core/btc_task.c" "common/btc/profile/esp/blufi/blufi_prf.c" diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 0eba5dd7f3..1423b7fd51 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -80,6 +80,31 @@ menu "Bluetooth" We cannot split the memory into 3 different regions (IRAM, BLE-IRAM, DRAM). So this option will disable the PMP (ESP_SYSTEM_PMP_IDRAM_SPLIT) + config BT_HCI_LOG_DEBUG_EN + depends on BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED + bool "Enable Bluetooth HCI debug mode" + default n + help + This option is used to enable bluetooth debug mode, which saves the hci layer data stream. + + config BT_HCI_LOG_DATA_BUFFER_SIZE + depends on BT_HCI_LOG_DEBUG_EN + int "Size of the cache used for HCI data in Bluetooth HCI debug mode (N*1024 bytes)" + range 1 100 + default 5 + help + This option is to configure the buffer size of the hci data steam 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_ADV_BUFFER_SIZE + depends on BT_HCI_LOG_DEBUG_EN + int "Size of the cache used for adv report in Bluetooth HCI debug mode (N*1024 bytes)" + range 1 100 + default 8 + help + 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. + 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 new file mode 100644 index 0000000000..1cc95a46ce --- /dev/null +++ b/components/bt/common/hci_log/bt_hci_log.c @@ -0,0 +1,334 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "hci_log/bt_hci_log.h" +#include "bt_common.h" +#include "osi/mutex.h" +#include "esp_attr.h" + +#if (BT_HCI_LOG_INCLUDED == TRUE) +#define BT_HCI_LOG_PRINT_TAG (1) +#define BT_HCI_LOG_DATA_BUF_SIZE (1024 * HCI_LOG_DATA_BUFFER_SIZE) +#define BT_HCI_LOG_ADV_BUF_SIZE (1024 * HCI_LOG_ADV_BUFFER_SIZE) + +typedef struct { + osi_mutex_t mutex_lock; + uint64_t log_record_in; + uint64_t log_record_out; + uint64_t buf_size; + uint8_t *p_hci_log_buffer; + uint8_t index; + bool overflow; +} bt_hci_log_t; + +static const char s_hex_to_char_mapping[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +bt_hci_log_t g_bt_hci_log_data_ctl = {0}; +bt_hci_log_t g_bt_hci_log_adv_ctl = {0}; + +esp_err_t bt_hci_log_init(void) +{ + uint8_t *g_bt_hci_log_data_buffer = NULL; + uint8_t *g_bt_hci_log_adv_buffer = NULL; + + g_bt_hci_log_data_buffer = malloc(BT_HCI_LOG_DATA_BUF_SIZE); + if (!g_bt_hci_log_data_buffer) { + return ESP_ERR_NO_MEM; + } + g_bt_hci_log_adv_buffer = malloc(BT_HCI_LOG_ADV_BUF_SIZE); + if (!g_bt_hci_log_adv_buffer) { + if (g_bt_hci_log_data_buffer) { + free(g_bt_hci_log_data_buffer); + g_bt_hci_log_data_buffer = NULL; + } + return ESP_ERR_NO_MEM; + } + + memset(g_bt_hci_log_data_buffer, 0, BT_HCI_LOG_DATA_BUF_SIZE); + memset(g_bt_hci_log_adv_buffer, 0, BT_HCI_LOG_ADV_BUF_SIZE); + + memset(&g_bt_hci_log_data_ctl, 0, sizeof(bt_hci_log_t)); + g_bt_hci_log_data_ctl.buf_size = BT_HCI_LOG_DATA_BUF_SIZE; + g_bt_hci_log_data_ctl.p_hci_log_buffer = g_bt_hci_log_data_buffer; + + memset(&g_bt_hci_log_adv_ctl, 0, sizeof(bt_hci_log_t)); + g_bt_hci_log_adv_ctl.buf_size = BT_HCI_LOG_ADV_BUF_SIZE; + g_bt_hci_log_adv_ctl.p_hci_log_buffer = g_bt_hci_log_adv_buffer; + + osi_mutex_new((osi_mutex_t *)&g_bt_hci_log_data_ctl.mutex_lock); + osi_mutex_new((osi_mutex_t *)&g_bt_hci_log_adv_ctl.mutex_lock); + + return ESP_OK; +} + +esp_err_t bt_hci_log_deinit(void) +{ + if (g_bt_hci_log_data_ctl.p_hci_log_buffer) { + free(g_bt_hci_log_data_ctl.p_hci_log_buffer); + g_bt_hci_log_data_ctl.p_hci_log_buffer = NULL; + } + + if (g_bt_hci_log_adv_ctl.p_hci_log_buffer) { + free(g_bt_hci_log_adv_ctl.p_hci_log_buffer); + g_bt_hci_log_adv_ctl.p_hci_log_buffer = NULL; + } + + osi_mutex_free((osi_mutex_t *)&g_bt_hci_log_data_ctl.mutex_lock); + osi_mutex_free((osi_mutex_t *)&g_bt_hci_log_adv_ctl.mutex_lock); + + memset(&g_bt_hci_log_data_ctl, 0, sizeof(bt_hci_log_t)); + memset(&g_bt_hci_log_adv_ctl, 0, sizeof(bt_hci_log_t)); + + return ESP_OK; +} + +#if (BT_HCI_LOG_PRINT_TAG) +static char IRAM_ATTR *bt_data_type_to_str(uint8_t data_type) +{ + char *tag = NULL; + switch (data_type) + { + case HCI_LOG_DATA_TYPE_COMMAND: + // hci cmd data + tag = "CMD"; + break; + case HCI_LOG_DATA_TYPE_H2C_ACL: + // host to controller hci acl data + tag = "HAL"; + break; + case HCI_LOG_DATA_TYPE_SCO: + // hci sco data + tag = "SCO"; + break; + case HCI_LOG_DATA_TYPE_EVENT: + // hci event + tag = "EVT"; + break; + case HCI_LOG_DATA_TYPE_ADV: + // controller adv report data + tag = "ADV"; + break; + case HCI_LOG_DATA_TYPE_C2H_ACL: + // controller to host hci acl data + tag = "CAL"; + break; + case HCI_LOG_DATA_TYPE_SELF_DEFINE: + // self-defining data + tag = "ST"; + break; + default: + // unknown data type + tag = "UK"; + break; + } + + return tag; +} +#endif + +void bt_hci_log_record_hex(bt_hci_log_t *p_hci_log_ctl, uint8_t *hex, uint8_t hex_len) +{ + uint8_t hci_log_char; + uint8_t *g_hci_log_buffer; + + g_hci_log_buffer = p_hci_log_ctl->p_hci_log_buffer; + + while (hex_len--) + { + hci_log_char = ((*hex) >> 4); + + g_hci_log_buffer[p_hci_log_ctl->log_record_in] = s_hex_to_char_mapping [hci_log_char]; + + if (++ p_hci_log_ctl->log_record_in >= p_hci_log_ctl->buf_size) { + p_hci_log_ctl->log_record_in = 0; + } + if (p_hci_log_ctl->log_record_in == p_hci_log_ctl->log_record_out) { + p_hci_log_ctl->overflow = true; + } + + hci_log_char = ((*hex) & 0x0f); + + g_hci_log_buffer[p_hci_log_ctl->log_record_in] = s_hex_to_char_mapping [hci_log_char]; + + if (++p_hci_log_ctl->log_record_in >= p_hci_log_ctl->buf_size) { + p_hci_log_ctl->log_record_in = 0; + } + + if (p_hci_log_ctl->log_record_in == p_hci_log_ctl->log_record_out) { + p_hci_log_ctl->overflow = true; + } + + g_hci_log_buffer[p_hci_log_ctl->log_record_in] = ' '; + + if (++ p_hci_log_ctl->log_record_in >= p_hci_log_ctl->buf_size) { + p_hci_log_ctl->log_record_in = 0; + } + if (p_hci_log_ctl->log_record_in == p_hci_log_ctl->log_record_out) { + p_hci_log_ctl->overflow = true; + } + + ++ hex; + } +} + +void bt_hci_log_record_string(bt_hci_log_t *p_hci_log_ctl, char *string) +{ + uint8_t *g_hci_log_buffer; + + g_hci_log_buffer = p_hci_log_ctl->p_hci_log_buffer; + + while (*string != '\0') { + g_hci_log_buffer[p_hci_log_ctl->log_record_in] = *string; + ++string; + + if (++p_hci_log_ctl->log_record_in >= p_hci_log_ctl->buf_size) { + p_hci_log_ctl->log_record_in = 0; + } + + if (p_hci_log_ctl->log_record_in == p_hci_log_ctl->log_record_out) { + p_hci_log_ctl->overflow = true; + } + } +} + +esp_err_t IRAM_ATTR bt_hci_log_record_data(bt_hci_log_t *p_hci_log_ctl, char *str, uint8_t data_type, uint8_t *data, uint8_t data_len) +{ + osi_mutex_t mutex_lock; + uint8_t *g_hci_log_buffer; + + if (!p_hci_log_ctl->p_hci_log_buffer) { + return ESP_FAIL; + } + + g_hci_log_buffer = p_hci_log_ctl->p_hci_log_buffer; + + if (!g_hci_log_buffer) { + return ESP_FAIL; + } + + mutex_lock = p_hci_log_ctl->mutex_lock; + osi_mutex_lock(&mutex_lock, OSI_MUTEX_MAX_TIMEOUT); + +#if (1) + // Add hci data index + bt_hci_log_record_hex(p_hci_log_ctl, &p_hci_log_ctl->index, 1); +#endif + +#if (BT_HCI_LOG_PRINT_TAG) + char *tag = NULL; + tag = bt_data_type_to_str(data_type); + + if (tag) { + bt_hci_log_record_string(p_hci_log_ctl, tag); + + g_hci_log_buffer[p_hci_log_ctl->log_record_in] = ':'; + + if (++p_hci_log_ctl->log_record_in >= p_hci_log_ctl->buf_size) { + p_hci_log_ctl->log_record_in = 0; + } + + if (p_hci_log_ctl->log_record_in == p_hci_log_ctl->log_record_out) { + p_hci_log_ctl->overflow = true; + } + } +#endif + + if (str) { + bt_hci_log_record_string(p_hci_log_ctl, str); + } + + bt_hci_log_record_hex(p_hci_log_ctl, data, data_len); + + g_hci_log_buffer[p_hci_log_ctl->log_record_in] = '\n'; + + if (++p_hci_log_ctl->log_record_in >= p_hci_log_ctl->buf_size) { + p_hci_log_ctl->log_record_in = 0; + } + + if (p_hci_log_ctl->log_record_in == p_hci_log_ctl->log_record_out) { + p_hci_log_ctl->overflow = true; + } + + p_hci_log_ctl->index ++; + + osi_mutex_unlock(&mutex_lock); + + return ESP_OK; +} + +void bt_hci_log_data_show(bt_hci_log_t *p_hci_log_ctl) +{ + volatile uint64_t log_record_in,log_record_out; + uint8_t *g_hci_log_buffer; + + if (!p_hci_log_ctl->p_hci_log_buffer) { + return; + } + + osi_mutex_t mutex_lock = p_hci_log_ctl->mutex_lock; + + osi_mutex_lock(&mutex_lock, OSI_MUTEX_MAX_TIMEOUT); + + log_record_in = p_hci_log_ctl->log_record_in; + log_record_out = p_hci_log_ctl->log_record_out; + + g_hci_log_buffer = p_hci_log_ctl->p_hci_log_buffer; + + if (p_hci_log_ctl->overflow) { + log_record_out = log_record_in; + printf("%c",g_hci_log_buffer[log_record_out]); + + if (++log_record_out >= p_hci_log_ctl->buf_size) { + log_record_out = 0; + } + } + + while (log_record_in != log_record_out) + { + printf("%c",g_hci_log_buffer[log_record_out]); + + if (++log_record_out >= p_hci_log_ctl->buf_size) { + log_record_out = 0; + } + } + + p_hci_log_ctl->log_record_out = log_record_out; + p_hci_log_ctl->overflow = false; + + osi_mutex_unlock(&mutex_lock); +} + +esp_err_t IRAM_ATTR bt_hci_log_record_hci_data(uint8_t data_type, uint8_t *data, uint8_t data_len) +{ + return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, NULL, data_type, data, data_len); +} + +esp_err_t IRAM_ATTR bt_hci_log_record_custom_data(char *string, uint8_t *data, uint8_t data_len) +{ + return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, string, HCI_LOG_DATA_TYPE_SELF_DEFINE, data, data_len); +} + +esp_err_t IRAM_ATTR bt_hci_log_record_hci_adv(uint8_t data_type, uint8_t *data, uint8_t data_len) +{ + return bt_hci_log_record_data(&g_bt_hci_log_adv_ctl, NULL, data_type, data, data_len); +} + +void bt_hci_log_hci_data_show(void) +{ + bt_hci_log_data_show(&g_bt_hci_log_data_ctl); +} + +void bt_hci_log_hci_adv_show(void) +{ + bt_hci_log_data_show(&g_bt_hci_log_adv_ctl); +} + +#endif // (BT_HCI_LOG_INCLUDED == TRUE) 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 new file mode 100644 index 0000000000..512a307e44 --- /dev/null +++ b/components/bt/common/hci_log/include/hci_log/bt_hci_log.h @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ESP_BT_HCI_LOG_H__ +#define __ESP_BT_HCI_LOG_H__ + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define HCI_LOG_DATA_TYPE_COMMAND (1) +#define HCI_LOG_DATA_TYPE_H2C_ACL (2) +#define HCI_LOG_DATA_TYPE_SCO (3) +#define HCI_LOG_DATA_TYPE_EVENT (4) +#define HCI_LOG_DATA_TYPE_ADV (5) +#define HCI_LOG_DATA_TYPE_SELF_DEFINE (6) +#define HCI_LOG_DATA_TYPE_C2H_ACL (7) + +/** + * + * @brief This function is called to record self-defining data + * @param string : data identification + * @param data : data + * @param data_len : the length of data + * + * @return ESP_OK - success, other - failed + * + */ +esp_err_t bt_hci_log_record_custom_data(char *string, uint8_t *data, uint8_t data_len); +/** + * + * @brief This function is called to print all hci data record + * + * + * @return None + * + */ +void bt_hci_log_hci_data_show(void); + +/** + * + * @brief This function is called to print all adv report + * + * + * @return None + * + */ +void bt_hci_log_hci_adv_show(void); + +/** + * + * @brief This function is called to init hci log env + * + * + * @return ESP_OK - success, other - failed + * + */ +esp_err_t bt_hci_log_init(void); + +/** + * + * @brief This function is called to deinit hci debug mode, + * and can only be called internally by Bluetooth + * + * + * @return ESP_OK - success, other - failed + * + */ +esp_err_t bt_hci_log_deinit(void); + +/** + * + * @brief This function is called to record hci data without adv report event, + * and can only be called internally by Bluetooth + * + * @param str : data type, define in bt_data_type_to_str() + * @param data : data + * @param data_len : the length of data + * + * @return ESP_OK - success, other - failed + * + */ +esp_err_t bt_hci_log_record_hci_data(uint8_t data_type, uint8_t *data, uint8_t data_len); + +/** + * + * @brief This function is called to record hci adv report event only + * and can only be called internally by Bluetooth + * + * @param str : data type, define in bt_data_type_to_str() + * @param data : data + * @param data_len : the length of data + * @return ESP_OK - success, other - failed + * + */ +esp_err_t bt_hci_log_record_hci_adv(uint8_t data_type, uint8_t *data, uint8_t data_len); + +#ifdef __cplusplus +} +#endif + +#endif /* _ESP_BT_HCI_LOG_H__ */ diff --git a/components/bt/common/include/bt_common.h b/components/bt/common/include/bt_common.h index 134cf33c5d..f3c5ba0e0d 100644 --- a/components/bt/common/include/bt_common.h +++ b/components/bt/common/include/bt_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,6 +64,24 @@ #define BT_BLE_DYNAMIC_ENV_MEMORY FALSE #endif +#if UC_BT_HCI_LOG_DEBUG_EN +#define BT_HCI_LOG_INCLUDED UC_BT_HCI_LOG_DEBUG_EN +#else +#define BT_HCI_LOG_INCLUDED FALSE +#endif + +#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) +#endif + +#if UC_BT_HCI_ADV_BUFFER_SIZE +#define HCI_LOG_ADV_BUFFER_SIZE UC_BT_HCI_LOG_ADV_BUFFER_SIZE +#else +#define HCI_LOG_ADV_BUFFER_SIZE (5) +#endif + /* OS Configuration from User config (eg: sdkconfig) */ #define TASK_PINNED_TO_CORE UC_TASK_PINNED_TO_CORE #define BT_TASK_MAX_PRIORITIES configMAX_PRIORITIES diff --git a/components/bt/common/include/bt_user_config.h b/components/bt/common/include/bt_user_config.h index 738f4f2cd9..7f69b6730a 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-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -98,4 +98,22 @@ #define UC_BT_BLUEDROID_MEM_DEBUG FALSE #endif +#ifdef CONFIG_BT_HCI_LOG_DEBUG_EN +#define UC_BT_HCI_LOG_DEBUG_EN TRUE +#else +#define UC_BT_HCI_LOG_DEBUG_EN FALSE +#endif + +#ifdef CONFIG_BT_HCI_LOG_DATA_BUFFER_SIZE +#define UC_BT_HCI_LOG_DATA_BUFFER_SIZE CONFIG_BT_HCI_LOG_DATA_BUFFER_SIZE +#else +#define UC_BT_HCI_LOG_DATA_BUFFER_SIZE (5) +#endif + +#ifdef CONFIG_BT_HCI_LOG_ADV_BUFFER_SIZE +#define UC_BT_HCI_LOG_ADV_BUFFER_SIZE CONFIG_BT_HCI_LOG_ADV_BUFFER_SIZE +#else +#define UC_BT_HCI_LOG_ADV_BUFFER_SIZE (5) +#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 892f6790d6..d17ab91494 100644 --- a/components/bt/host/bluedroid/api/esp_bluedroid_hci.c +++ b/components/bt/host/bluedroid/api/esp_bluedroid_hci.c @@ -12,6 +12,7 @@ #if (BT_CONTROLLER_INCLUDED == TRUE) #include "esp_bt.h" #endif +#include "hci_log/bt_hci_log.h" #define LOG_TAG "HCI_API" @@ -59,6 +60,9 @@ 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, len); +#endif #if (BT_CONTROLLER_INCLUDED == TRUE) esp_vhci_host_send_packet(data, len); #else /* BT_CONTROLLER_INCLUDED == TRUE */ diff --git a/components/bt/host/bluedroid/api/esp_bt_main.c b/components/bt/host/bluedroid/api/esp_bt_main.c index 497ba769b6..92576442b7 100644 --- a/components/bt/host/bluedroid/api/esp_bt_main.c +++ b/components/bt/host/bluedroid/api/esp_bt_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,8 @@ #include "osi/future.h" #include "osi/allocator.h" #include "config/stack_config.h" +#include "hci_log/bt_hci_log.h" +#include "bt_common.h" static bool bd_already_enable = false; static bool bd_already_init = false; @@ -180,6 +182,10 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg) bd_already_init = true; +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_init(); +#endif // (BT_HCI_LOG_INCLUDED == TRUE) + return ESP_OK; } @@ -224,6 +230,10 @@ esp_err_t esp_bluedroid_deinit(void) bluedriod_config_deinit(); +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_deinit(); +#endif // (BT_HCI_LOG_INCLUDED == TRUE) + bd_already_init = false; return ESP_OK; diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index 2404779036..8f312e60a2 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -43,6 +43,7 @@ #include "l2c_int.h" #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE #include "stack/hcimsgs.h" +#include "hci_log/bt_hci_log.h" #define HCI_BLE_EVENT 0x3e #define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2) @@ -441,7 +442,7 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) uint8_t len = 0; STREAM_TO_UINT8(len, stream); #endif - HCI_TRACE_ERROR("Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d\n", + HCI_TRACE_ERROR("Workaround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d\n", packet->len, len); osi_free(packet); return; @@ -554,10 +555,14 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) bool is_adv_rpt = host_recv_adv_packet(data); if (!is_adv_rpt) { +#if (BT_HCI_LOG_INCLUDED == TRUE) + uint8_t data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : data[0]); + bt_hci_log_record_hci_data(data_type, data, len); +#endif // (BT_HCI_LOG_INCLUDED == TRUE) pkt_size = BT_HDR_SIZE + len; pkt = (BT_HDR *) osi_calloc(pkt_size); if (!pkt) { - HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__); + HCI_TRACE_ERROR("%s couldn't acquire memory for inbound data buffer.\n", __func__); assert(0); } @@ -567,6 +572,10 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) memcpy(pkt->data, data, len); fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT); } else { +#if (BT_HCI_LOG_INCLUDED == TRUE) + // data type is adv report + bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, data, len); +#endif // (BT_HCI_LOG_INCLUDED == TRUE) #if !BLE_ADV_REPORT_FLOW_CONTROL // drop the packets if pkt_queue length goes beyond upper limit if (pkt_queue_length(hci_hal_env.adv_rpt_q) > HCI_HAL_BLE_ADV_RPT_QUEUE_LEN_MAX) { 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 9d997389a2..8dbe78c36a 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,8 @@ #include "freertos/semphr.h" #include "esp_compiler.h" #include "soc/soc_caps.h" +#include "bt_common.h" +#include "hci_log/bt_hci_log.h" #define NIMBLE_VHCI_TIMEOUT_MS 2000 #define BLE_HCI_EVENT_HDR_LEN (2) @@ -75,6 +77,9 @@ int ble_hci_trans_hs_cmd_tx(uint8_t *cmd) } if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_record_hci_data(cmd[0], cmd, len); +#endif esp_vhci_host_send_packet(cmd, len); } else { rc = BLE_HS_ETIMEOUT_HCI; @@ -112,6 +117,9 @@ int ble_hci_trans_hs_acl_tx(struct os_mbuf *om) len += OS_MBUF_PKTLEN(om); if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_record_hci_data(data[0], data, len); +#endif esp_vhci_host_send_packet(data, len); } else { rc = BLE_HS_ETIMEOUT_HCI; @@ -215,12 +223,18 @@ static int host_rcv_pkt(uint8_t *data, uint16_t len) /* Allocate LE Advertising Report Event from lo pool only */ if ((data[1] == BLE_HCI_EVCODE_LE_META) && (data[3] == BLE_HCI_LE_SUBEV_ADV_RPT || data[3] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, data, len); +#endif evbuf = ble_transport_alloc_evt(1); /* Skip advertising report if we're out of memory */ if (!evbuf) { return 0; } } else { +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_record_hci_data(data[0], data, len); +#endif evbuf = ble_transport_alloc_evt(0); assert(evbuf != NULL); } @@ -231,6 +245,9 @@ static int host_rcv_pkt(uint8_t *data, uint16_t len) rc = ble_hci_trans_ll_evt_tx(evbuf); assert(rc == 0); } else if (data[0] == BLE_HCI_UART_H4_ACL) { +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_record_hci_data(HCI_LOG_DATA_TYPE_C2H_ACL, data, len); +#endif ble_hci_rx_acl(data + 1, len - 1); } return 0; @@ -265,6 +282,10 @@ esp_err_t esp_nimble_hci_init(void) goto err; } +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_init(); +#endif // (BT_HCI_LOG_INCLUDED == TRUE) + xSemaphoreGive(vhci_send_sem); #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) @@ -292,6 +313,10 @@ esp_err_t esp_nimble_hci_deinit(void) ble_buf_free(); +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_deinit(); +#endif // (BT_HCI_LOG_INCLUDED == TRUE) + #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) ble_adv_list_deinit(); #endif From a43f54ccc01e13c39621e9c8fff3b5d8c97affb6 Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Tue, 12 Mar 2024 11:48:14 +0800 Subject: [PATCH 3/3] fix(ble/bluedroid): Fixed adv not restart due to disconnection reason 0x3e --- .../host/bluedroid/stack/btm/btm_ble_5_gap.c | 8 ++++---- .../bt/host/bluedroid/stack/l2cap/l2c_link.c | 20 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c index 78711b589c..04ad4804bd 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c @@ -332,7 +332,7 @@ tBTM_STATUS BTM_BleSetExtendedAdvRandaddr(UINT8 instance, BD_ADDR rand_addr) __func__, btm_ble_hci_status_to_str(err), err); status = BTM_ILLEGAL_VALUE; } else { - // set random address success, update address infor + // set random address success, update address info if(extend_adv_cb.inst[instance].configured && extend_adv_cb.inst[instance].connetable) { BTM_BleSetStaticAddr(rand_addr); BTM_UpdateAddrInfor(BLE_ADDR_RANDOM, rand_addr); @@ -416,7 +416,7 @@ end: BTM_TRACE_ERROR("LE EA SetParams: cmd err=0x%x", err); status = BTM_ILLEGAL_VALUE; } else { - // set addr success, update address infor + // set addr success, update address info BTM_UpdateAddrInfor(BLE_ADDR_RANDOM, rand_addr); } } @@ -592,12 +592,12 @@ tBTM_STATUS BTM_BleStartExtAdvRestart(uint8_t con_handle) } } - if((index >= MAX_BLE_ADV_INSTANCE) || (!adv_record[index].invalid) || (adv_record[index].retry_count > GATTC_CONNECT_RETRY_COUNT)) { + if((index >= MAX_BLE_ADV_INSTANCE) || (!adv_record[index].invalid)) { return BTM_WRONG_MODE; } adv_record[index].retry_count ++; - BTM_TRACE_DEBUG("remote device did not reveive aux connect response, retatrt the extend adv to reconnect, adv handle %d con_handle %d\n", index, con_handle); + BTM_TRACE_DEBUG("remote device did not receive aux connect response, retatrt the extend adv to reconnect, adv handle %d con_handle %d\n", index, con_handle); ext_adv.instance = adv_record[index].instance; ext_adv.duration = adv_record[index].duration; ext_adv.max_events = adv_record[index].max_events; diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_link.c b/components/bt/host/bluedroid/stack/l2cap/l2c_link.c index 4b81b4b3b2..c3118fdd5c 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_link.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_link.c @@ -367,6 +367,11 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) if (reason != HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT) { BTM_Recovery_Pre_State(); } + #if (BLE_50_FEATURE_SUPPORT == TRUE) + if(btm_ble_inter_get() && reason == HCI_ERR_CONN_FAILED_ESTABLISHMENT) { + BTM_BleStartExtAdvRestart(handle); + } + #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #endif ///BLE_INCLUDED == TRUE status = FALSE; } else { @@ -438,7 +443,7 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) #endif { #if (L2CAP_NUM_FIXED_CHNLS > 0) - /* If we are going to re-use the LCB without dropping it, release all fixed channels + /* If we are going to reuse the LCB without dropping it, release all fixed channels here */ int xx; for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) { @@ -463,9 +468,9 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) } p_lcb->p_pending_ccb = NULL; -#if (BLE_INCLUDED == TRUE && GATTC_CONNECT_RETRY_EN == TRUE) +#if (BLE_INCLUDED == TRUE) if(reason == HCI_ERR_CONN_FAILED_ESTABLISHMENT && p_lcb->transport == BT_TRANSPORT_LE) { - + #if (GATTC_CONNECT_RETRY_EN == TRUE) if(p_lcb->link_role == HCI_ROLE_MASTER && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) { L2CAP_TRACE_DEBUG("master retry connect, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason); p_lcb->retry_create_con ++; @@ -475,9 +480,10 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) lcb_is_free = FALSE; /* still using this lcb */ } } + #endif // (GATTC_CONNECT_RETRY_EN == TRUE) #if (BLE_50_FEATURE_SUPPORT == TRUE) - if(btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) { + if(btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE) { p_lcb->retry_create_con ++; L2CAP_TRACE_DEBUG("slave restart extend adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason); BTM_BleStartExtAdvRestart(handle); @@ -485,7 +491,7 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_42_FEATURE_SUPPORT == TRUE) - if(!btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) { + if(!btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE) { p_lcb->retry_create_con ++; L2CAP_TRACE_DEBUG("slave resatrt adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason); btm_ble_start_adv(); @@ -909,7 +915,7 @@ UINT8 l2c_link_pkts_rcvd (UINT16 *num_pkts, UINT16 *handles) ** ** Function l2c_link_role_changed ** -** Description This function is called whan a link's master/slave role change +** Description This function is called when a link's master/slave role change ** event is received. It simply updates the link control block. ** ** Returns void @@ -947,7 +953,7 @@ void l2c_link_role_changed (BD_ADDR bd_addr, UINT8 new_role, UINT8 hci_status) ** ** Function l2c_pin_code_request ** -** Description This function is called whan a pin-code request is received +** Description This function is called when a pin-code request is received ** on a connection. If there are no channels active yet on the ** link, it extends the link first connection timer. Make sure ** that inactivity timer is not extended if PIN code happens