From 78afda7d5a6882559f32c0f08d1dc893a33ae086 Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Tue, 12 Aug 2025 21:33:32 +0800 Subject: [PATCH] feat(ble/bluedroid): Support multi-connection optimization vendor hci command (cherry picked from commit f0cfb6e33ceba049ca3d8d2c306cec97c65ddfaf) Co-authored-by: chenjianhua --- .../bt/host/bluedroid/api/esp_gap_ble_api.c | 36 +++++++++++++ .../api/include/api/esp_gap_ble_api.h | 54 +++++++++++++++++++ .../btc/profile/std/gap/btc_gap_ble.c | 25 +++++++-- 3 files changed, 111 insertions(+), 4 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 5cd266eaa8..42724d2245 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -1759,6 +1759,42 @@ esp_err_t esp_ble_gap_set_csa_support(uint8_t csa_select) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } + +#if CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION +esp_err_t esp_ble_gap_set_common_factor(uint32_t common_factor) +{ + esp_ble_vendor_cmd_params_t vs_cmd; + uint8_t cmd_param[5]; + + cmd_param[0] = common_factor & 0xFF; + cmd_param[1] = (common_factor >> 8) & 0xFF; + cmd_param[2] = (common_factor >> 16) & 0xFF; + cmd_param[3] = (common_factor >> 24) & 0xFF; + cmd_param[4] = 0x01; + vs_cmd.opcode = 0xFD0F; + vs_cmd.param_len = 5; + vs_cmd.p_param_buf = cmd_param; + + return esp_ble_gap_vendor_command_send(&vs_cmd); +} + +esp_err_t esp_ble_gap_set_sch_len(uint8_t role, uint32_t len) +{ + esp_ble_vendor_cmd_params_t vs_cmd; + uint8_t cmd_param[5]; + + cmd_param[0] = role; + cmd_param[1] = len & 0xFF; + cmd_param[2] = (len >> 8) & 0xFF; + cmd_param[3] = (len >> 16) & 0xFF; + cmd_param[4] = (len >> 24) & 0xFF; + vs_cmd.opcode = 0xFD10; + vs_cmd.param_len = 5; + vs_cmd.p_param_buf = cmd_param; + + return esp_ble_gap_vendor_command_send(&vs_cmd); +} +#endif // CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION #endif // (BLE_VENDOR_HCI_EN == TRUE) #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) 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 a75ae93999..409d76c843 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 @@ -246,6 +246,8 @@ typedef enum { ESP_GAP_BLE_SUBRATE_CHANGE_EVT, /*!< when Connection Subrate Update procedure has completed and some parameters of the specified connection have changed, the event comes */ ESP_GAP_BLE_SET_HOST_FEATURE_CMPL_EVT, /*!< When host feature set complete, the event comes */ ESP_GAP_BLE_READ_CHANNEL_MAP_COMPLETE_EVT, /*!< When BLE channel map result is received, the event comes */ + ESP_GAP_BLE_SET_COMMON_FACTOR_CMPL_EVT, /*!< When set the common factor complete, the event comes */ + ESP_GAP_BLE_SET_SCH_LEN_CMPL_EVT, /*!< When set the scheduling length complete, the event comes */ ESP_GAP_BLE_EVT_MAX, /*!< when maximum advertising event complete, the event comes */ } esp_gap_ble_cb_event_t; @@ -1748,6 +1750,18 @@ typedef union { uint8_t param_len; /*!< The length of the event parameter buffer (for internal use only) */ uint8_t *param_buf; /*!< The pointer of the event parameter buffer (for internal use only) */ } vendor_hci_evt; /*!< Event parameter of ESP_GAP_BLE_VENDOR_HCI_EVT */ + /** + * @brief ESP_GAP_BLE_SET_COMMON_FACTOR_CMPL_EVT + */ + struct ble_set_common_factor_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate common factor set operation success status */ + } set_common_factor_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_COMMON_FACTOR_CMPL_EVT */ + /** + * @brief ESP_GAP_BLE_SET_SCH_LEN_CMPL_EVT + */ + struct ble_set_sch_len_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate scheduling length set operation success status */ + } set_sch_len_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_SCH_LEN_CMPL_EVT */ #endif // #if (BLE_VENDOR_HCI_EN == TRUE) #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) /** @@ -3090,6 +3104,46 @@ esp_err_t esp_ble_gap_set_csa_support(uint8_t csa_select); */ esp_err_t esp_ble_gap_set_vendor_event_mask(esp_ble_vendor_evt_mask_t event_mask); +/** + * @brief This function is used to set a common connection interval factor for multiple central-role connections. + * When multiple BLE connections in the central role exist, it is recommended that + * each connection interval be configured to either the same value or an integer + * multiple of the others. And use this function to set the common factor of all + * connection intervalsin the controller. The controller will then arrange the scheduling + * of each connection based on this factor to minimize or avoid connection conflicts. + * + * @note - This function is used in multi-connection scenarios. + * - This function takes effect only when the connection role is central. + * - This function only needs to be called once and before establishing the connection. + * + * @param[in] common_factor: The common connection interval factor (in units of 625us) + * used for scheduling across all central-role connections. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_common_factor(uint32_t common_factor); + +/** + * @brief This function is used to Set the scheduling protection time for specific LE role. + * It can be used to configures the minimum protection time to be reserved for a + * connection's TX/RX operations, ensuring that a complete transmission and + * reception cycle is not interrupted. It helps prevent disconnect in scenarios + * with multiple connections competing for time slots. + * + * @note - This function is used in multi-connection scenarios. + * - This function must be called before establishing the connection. + * + * @param[in] role: 0: Central 1: Peripheral + * @param[in] len: The protection time length of the corresponding role (in units of us) + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_sch_len(uint8_t role, uint32_t len); + /** * @brief This function is used to read the current and maximum transmit power levels of the local Controller. * 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 07067748b1..2817365583 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 @@ -1441,10 +1441,23 @@ static void btc_ble_vendor_hci_cmd_complete_callback(tBTA_VSC_CMPL *p_param) 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; + switch (p_param->opcode) { + case 0xFD0F: + msg.act = ESP_GAP_BLE_SET_COMMON_FACTOR_CMPL_EVT; + param.set_common_factor_cmpl.status = p_param->p_param_buf[0]; + break; + case 0xFD10: + msg.act = ESP_GAP_BLE_SET_SCH_LEN_CMPL_EVT; + param.set_sch_len_cmpl.status = p_param->p_param_buf[0]; + break; + default: + 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; + break; + } } else { if (p_param) { param.vendor_cmd_cmpl.opcode = p_param->opcode; @@ -1455,7 +1468,11 @@ static void btc_ble_vendor_hci_cmd_complete_callback(tBTA_VSC_CMPL *p_param) 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 (msg.act == ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT) { + 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); + } else { + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + } if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);