From ea68f1efd1ad093d993d0aa1095f49a232bf48e0 Mon Sep 17 00:00:00 2001 From: Zhi Wei Jian Date: Fri, 26 Jun 2026 09:08:16 +0800 Subject: [PATCH] feat(ble/bluedroid): add LE UTP host support (Core 6.2) (cherry picked from commit 3844e242076dac335f6f9a15247348b0417c020b) Co-authored-by: zhiweijian --- components/bt/host/bluedroid/Kconfig.in | 8 +++ .../bt/host/bluedroid/api/esp_gap_ble_api.c | 44 ++++++++++++ .../api/include/api/esp_gap_ble_api.h | 67 ++++++++++++++++++- .../bt/host/bluedroid/bta/dm/bta_dm_act.c | 11 +++ .../bt/host/bluedroid/bta/dm/bta_dm_api.c | 35 ++++++++++ .../bt/host/bluedroid/bta/dm/bta_dm_main.c | 4 ++ .../bluedroid/bta/dm/include/bta_dm_int.h | 27 ++++++++ .../host/bluedroid/bta/include/bta/bta_api.h | 9 +++ .../btc/profile/std/gap/btc_gap_ble.c | 58 ++++++++++++++++ .../btc/profile/std/include/btc_gap_ble.h | 13 ++++ .../include/common/bluedroid_user_config.h | 19 ++++-- .../common/include/common/bt_target.h | 5 ++ .../host/bluedroid/stack/btm/btm_ble_5_gap.c | 52 ++++++++++++++ .../bluedroid/stack/btm/include/btm_ble_int.h | 3 + .../bt/host/bluedroid/stack/hcic/hciblecmds.c | 42 ++++++++++++ .../stack/include/stack/btm_ble_api.h | 18 +++++ .../bluedroid/stack/include/stack/hcidefs.h | 7 ++ .../bluedroid/stack/include/stack/hcimsgs.h | 9 +++ 18 files changed, 423 insertions(+), 8 deletions(-) diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index a5304797378..10584dbff98 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -1562,6 +1562,14 @@ config BT_BLE_FEAT_SHORTER_CONN_INTERVALS esp_ble_gap_set_default_rate_parameters(), esp_ble_gap_read_min_supported_connection_interval() and ESP_BLE_GAP_CONN_RATE_* conversion macros in esp_gap_ble_api.h. +config BT_BLE_FEAT_LE_UTP + bool "Enable BLE Unified Test Protocol (UTP)" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_LE_UTP_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable LE Unified Test Protocol (Bluetooth Core 6.2). + Supports LE Enable UTP OTA Mode, LE UTP Send commands and LE UTP Receive event. + menuconfig BT_BLE_42_FEATURES_SUPPORTED bool "Enable BLE 4.2 features(please disable BLE 5.0 if enable BLE 4.2)" depends on BT_BLE_ENABLED 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 132aa31e773..718faa8bf3a 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -2249,6 +2249,50 @@ esp_err_t esp_ble_gap_read_min_supported_connection_interval(void) } #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +esp_err_t esp_ble_gap_enable_utp_ota_mode(const esp_ble_gap_enable_utp_ota_mode_params_t *params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + memset(&arg, 0, sizeof(arg)); + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (params == NULL || params->enable > 1) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ENABLE_UTP_OTA_MODE; + arg.enable_utp_ota_mode.enable = params->enable; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_utp_send(const esp_ble_gap_utp_send_params_t *params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + memset(&arg, 0, sizeof(arg)); + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (params == NULL || params->data == NULL || + params->data_len == 0 || params->data_len > ESP_BLE_GAP_UTP_DATA_MAX_LEN) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_UTP_SEND; + arg.utp_send.data_len = params->data_len; + arg.utp_send.data = (uint8_t *)params->data; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), + btc_gap_ble_arg_deep_copy, btc_gap_ble_arg_deep_free) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #endif //#if (BLE_50_FEATURE_SUPPORT == 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 257e081c929..5571130b3be 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 @@ -282,6 +282,9 @@ typedef enum { ESP_GAP_BLE_CONN_RATE_CHANGE_EVT, /*!< When connection rate change event is received, the event comes */ ESP_GAP_BLE_SET_DEFAULT_RATE_PARAMETERS_COMPLETE_EVT, /*!< When set default rate parameters complete, the event comes */ ESP_GAP_BLE_READ_MIN_SUPP_CONN_INTERVAL_COMPLETE_EVT, /*!< When read minimum supported connection interval complete, the event comes */ + ESP_GAP_BLE_ENABLE_UTP_OTA_MODE_COMPLETE_EVT, /*!< When enable UTP OTA mode complete, the event comes */ + ESP_GAP_BLE_UTP_SEND_COMPLETE_EVT, /*!< When UTP send complete, the event comes */ + ESP_GAP_BLE_UTP_RECEIVE_EVT, /*!< When UTP data is received, the event comes */ ESP_GAP_BLE_EVT_MAX, /*!< when maximum advertising event complete, the event comes */ } esp_gap_ble_cb_event_t; @@ -1411,6 +1414,24 @@ typedef struct { } esp_ble_gap_min_conn_interval_group_t; #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +#define ESP_BLE_GAP_UTP_DATA_MAX_LEN 254 + +/** + * @brief Parameters for enabling or disabling LE Unified Test Protocol (UTP) OTA mode + */ +typedef struct { + uint8_t enable; /*!< 0x00: Disable UTP OTA mode, 0x01: Enable UTP OTA mode */ +} esp_ble_gap_enable_utp_ota_mode_params_t; + +/** + * @brief Parameters for sending LE Unified Test Protocol (UTP) data + */ +typedef struct { + uint8_t data_len; /*!< UTP data length, range: 0x01 to 0xFE */ + const uint8_t *data; /*!< Pointer to UTP data */ +} esp_ble_gap_utp_send_params_t; +#endif // #if (BLE_FEAT_LE_UTP == TRUE) typedef enum { ESP_BLE_NETWORK_PRIVACY_MODE = 0X00, /*!< Network Privacy Mode for peer device (default) */ @@ -2449,9 +2470,30 @@ typedef union { esp_bt_status_t status; /*!< Indicate read minimum supported connection interval operation success status */ uint8_t min_supported_conn_interval; /*!< Minimum supported connection interval in 125 us units */ uint8_t num_groups; /*!< Number of supported interval groups; 0 if only RCV is supported */ - esp_ble_gap_min_conn_interval_group_t groups[ESP_BLE_GAP_CONN_RATE_MAX_INTERVAL_GROUPS]; + esp_ble_gap_min_conn_interval_group_t groups[ESP_BLE_GAP_CONN_RATE_MAX_INTERVAL_GROUPS]; /*!< Supported interval groups; valid when num_groups > 0 */ } read_min_supp_conn_interval; /*!< Event parameter of ESP_GAP_BLE_READ_MIN_SUPP_CONN_INTERVAL_COMPLETE_EVT */ #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + /** + * @brief ESP_GAP_BLE_ENABLE_UTP_OTA_MODE_COMPLETE_EVT + */ + struct ble_enable_utp_ota_mode_cmpl_param { + esp_bt_status_t status; /*!< Indicate enable UTP OTA mode operation success status */ + } enable_utp_ota_mode_cmpl; /*!< Event parameter of ESP_GAP_BLE_ENABLE_UTP_OTA_MODE_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_UTP_SEND_COMPLETE_EVT + */ + struct ble_utp_send_cmpl_param { + esp_bt_status_t status; /*!< Indicate UTP send operation success status */ + } utp_send_cmpl; /*!< Event parameter of ESP_GAP_BLE_UTP_SEND_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_UTP_RECEIVE_EVT + */ + struct ble_utp_receive_evt { + uint8_t len; /*!< UTP data length */ + uint8_t data[ESP_BLE_GAP_UTP_DATA_MAX_LEN]; /*!< UTP data */ + } utp_receive; /*!< Event parameter of ESP_GAP_BLE_UTP_RECEIVE_EVT */ +#endif // #if (BLE_FEAT_LE_UTP == TRUE) /** * @brief ESP_GAP_BLE_CHANNEL_SELECT_ALGORITHM_EVT */ @@ -4429,6 +4471,29 @@ esp_err_t esp_ble_gap_set_default_rate_parameters(const esp_ble_gap_default_rate esp_err_t esp_ble_gap_read_min_supported_connection_interval(void); #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +/** +* @brief Enable or disable LE Unified Test Protocol (UTP) OTA mode. +* +* @param[in] params : Pointer to enable UTP OTA mode parameters. +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_gap_enable_utp_ota_mode(const esp_ble_gap_enable_utp_ota_mode_params_t *params); + +/** +* @brief Send LE UTP data. +* +* @param[in] params : Pointer to UTP send parameters. +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_gap_utp_send(const esp_ble_gap_utp_send_params_t *params); +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) 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 615ba3e56de..b00f23c8b00 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -6062,6 +6062,17 @@ void bta_dm_ble_gap_read_min_supp_conn_interval(tBTA_DM_MSG *p_data) } #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +void bta_dm_ble_gap_enable_utp_ota_mode(tBTA_DM_MSG *p_data) +{ + BTM_BleEnableUtpOtaMode(p_data->ble_enable_utp_ota_mode.enable); +} + +void bta_dm_ble_gap_utp_send(tBTA_DM_MSG *p_data) +{ + BTM_BleUtpSend(p_data->ble_utp_send.data_len, p_data->ble_utp_send.data); +} +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) 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 5e1c7211075..6ccc7e9d1ea 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -3428,6 +3428,41 @@ void BTA_DmBleGapReadMinSuppConnInterval(void) } #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +void BTA_DmBleGapEnableUtpOtaMode(UINT8 enable) +{ + tBTA_DM_API_BLE_ENABLE_UTP_OTA_MODE *p_msg; + APPL_TRACE_API("%s", __func__); + if ((p_msg = (tBTA_DM_API_BLE_ENABLE_UTP_OTA_MODE *) + osi_malloc(sizeof(tBTA_DM_API_BLE_ENABLE_UTP_OTA_MODE))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_ENABLE_UTP_OTA_MODE)); + p_msg->hdr.event = BTA_DM_API_ENABLE_UTP_OTA_MODE_EVT; + p_msg->enable = enable; + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleGapUtpSend(UINT8 data_len, const UINT8 *p_data) +{ + tBTA_DM_API_BLE_UTP_SEND *p_msg; + APPL_TRACE_API("%s", __func__); + if (data_len == 0 || data_len > BLE_UTP_DATA_MAX_LEN || p_data == NULL) { + APPL_TRACE_ERROR("%s invalid params", __func__); + return; + } + if ((p_msg = (tBTA_DM_API_BLE_UTP_SEND *) osi_malloc(sizeof(tBTA_DM_API_BLE_UTP_SEND))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_UTP_SEND)); + p_msg->hdr.event = BTA_DM_API_UTP_SEND_EVT; + p_msg->data_len = data_len; + memcpy(p_msg->data, p_data, data_len); + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) 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 96697706b4e..b85c91663b9 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -344,6 +344,10 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_ble_gap_set_default_rate_parameters, /* BTA_DM_API_SET_DEFAULT_RATE_PARAMETERS_EVT */ bta_dm_ble_gap_read_min_supp_conn_interval, /* BTA_DM_API_READ_MIN_SUPP_CONN_INTERVAL_EVT */ #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + bta_dm_ble_gap_enable_utp_ota_mode, /* BTA_DM_API_ENABLE_UTP_OTA_MODE_EVT */ + bta_dm_ble_gap_utp_send, /* BTA_DM_API_UTP_SEND_EVT */ +#endif // #if (BLE_FEAT_LE_UTP == TRUE) }; diff --git a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index 396abcd3946..eed23f69050 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 @@ -25,6 +25,9 @@ #define BTA_DM_INT_H #include "common/bt_target.h" +#if (BLE_FEAT_DBAF == TRUE) || (BLE_FEAT_LL_EXT_FEAT == TRUE) || (BLE_FEAT_LE_UTP == TRUE) +#include "stack/hcimsgs.h" +#endif #include "freertos/semphr.h" #include "bta/bta_sys.h" #if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)) @@ -338,6 +341,10 @@ enum { BTA_DM_API_SET_DEFAULT_RATE_PARAMETERS_EVT, BTA_DM_API_READ_MIN_SUPP_CONN_INTERVAL_EVT, #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + BTA_DM_API_ENABLE_UTP_OTA_MODE_EVT, + BTA_DM_API_UTP_SEND_EVT, +#endif // #if (BLE_FEAT_LE_UTP == TRUE) BTA_DM_MAX_EVT }; @@ -1468,6 +1475,18 @@ typedef struct { } tBTA_DM_API_BLE_READ_MIN_SUPP_CONN_INTERVAL; #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +typedef struct { + BT_HDR hdr; + UINT8 enable; +} tBTA_DM_API_BLE_ENABLE_UTP_OTA_MODE; + +typedef struct { + BT_HDR hdr; + UINT8 data_len; + UINT8 data[BLE_UTP_DATA_MAX_LEN]; +} tBTA_DM_API_BLE_UTP_SEND; +#endif // #if (BLE_FEAT_LE_UTP == TRUE) typedef struct { BT_HDR hdr; @@ -1921,6 +1940,10 @@ typedef union { tBTA_DM_API_BLE_SET_DEFAULT_RATE_PARAMETERS ble_set_default_rate_parameters; tBTA_DM_API_BLE_READ_MIN_SUPP_CONN_INTERVAL ble_read_min_supp_conn_interval; #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + tBTA_DM_API_BLE_ENABLE_UTP_OTA_MODE ble_enable_utp_ota_mode; + tBTA_DM_API_BLE_UTP_SEND ble_utp_send; +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_42_DTM_TEST_EN == TRUE) tBTA_DM_API_BLE_DTM_TX_START dtm_tx_start; tBTA_DM_API_BLE_DTM_RX_START dtm_rx_start; @@ -2620,6 +2643,10 @@ extern void bta_dm_ble_gap_set_default_rate_parameters(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_read_min_supp_conn_interval(tBTA_DM_MSG *p_data); #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +extern void bta_dm_ble_gap_enable_utp_ota_mode(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_gap_utp_send(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) 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 27b1cde936b..5295770db22 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -1626,6 +1626,11 @@ typedef struct { #define BTA_DM_BLE_5_GAP_READ_MIN_SUPP_CONN_INTERVAL_COMPLETE_EVT BTM_BLE_5_GAP_READ_MIN_SUPP_CONN_INTERVAL_COMPLETE_EVT #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +#define BTA_DM_BLE_5_GAP_ENABLE_UTP_OTA_MODE_COMPLETE_EVT BTM_BLE_5_GAP_ENABLE_UTP_OTA_MODE_COMPLETE_EVT +#define BTA_DM_BLE_5_GAP_UTP_SEND_COMPLETE_EVT BTM_BLE_5_GAP_UTP_SEND_COMPLETE_EVT +#define BTA_DM_BLE_5_GAP_UTP_RECEIVE_EVT BTM_BLE_5_GAP_UTP_RECEIVE_EVT +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BT_BLE_FEAT_PAWR_EN == TRUE) #define BTA_BLE_GAP_SET_PERIODIC_ADV_SUBEVT_DATA_EVT BTM_BLE_GAP_SET_PERIODIC_ADV_SUBEVT_DATA_EVT @@ -3112,6 +3117,10 @@ extern void BTA_DmBleGapSetDefaultRateParameters(UINT16 conn_interval_min, UINT1 extern void BTA_DmBleGapReadMinSuppConnInterval(void); #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +extern void BTA_DmBleGapEnableUtpOtaMode(UINT8 enable); +extern void BTA_DmBleGapUtpSend(UINT8 data_len, const UINT8 *p_data); +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_ISO_EN == TRUE) #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE) 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 9b304a559c4..0d8e2ca07c9 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 @@ -1382,6 +1382,29 @@ void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, break; } #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + case BTA_DM_BLE_5_GAP_ENABLE_UTP_OTA_MODE_COMPLETE_EVT: { + msg.act = ESP_GAP_BLE_ENABLE_UTP_OTA_MODE_COMPLETE_EVT; + param.enable_utp_ota_mode_cmpl.status = btc_btm_status_to_esp_status(params->status); + break; + } + case BTA_DM_BLE_5_GAP_UTP_SEND_COMPLETE_EVT: { + msg.act = ESP_GAP_BLE_UTP_SEND_COMPLETE_EVT; + param.utp_send_cmpl.status = btc_btm_status_to_esp_status(params->status); + break; + } + case BTA_DM_BLE_5_GAP_UTP_RECEIVE_EVT: { + msg.act = ESP_GAP_BLE_UTP_RECEIVE_EVT; + param.utp_receive.len = params->utp_receive.len; + if (params->utp_receive.data && params->utp_receive.len > 0) { + if (params->utp_receive.len > ESP_BLE_GAP_UTP_DATA_MAX_LEN) { + param.utp_receive.len = ESP_BLE_GAP_UTP_DATA_MAX_LEN; + } + memcpy(param.utp_receive.data, params->utp_receive.data, param.utp_receive.len); + } + break; + } +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_50_EXTEND_ADV_EN == TRUE) case BTA_DM_BLE_5_GAP_ADV_TERMINATED_EVT: { param.adv_terminate.status = params->adv_term.status; @@ -2654,6 +2677,24 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) break; } #endif // #if (BLE_FEAT_DBAF == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + case BTC_GAP_BLE_UTP_SEND: { + btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src; + btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest; + + dst->utp_send.data = NULL; + if (src->utp_send.data_len > 0 && src->utp_send.data) { + dst->utp_send.data = osi_malloc(src->utp_send.data_len); + if (dst->utp_send.data) { + memcpy(dst->utp_send.data, src->utp_send.data, src->utp_send.data_len); + } else { + BTC_TRACE_WARNING("%s no mem, utp data drop %u", __func__, src->utp_send.data_len); + dst->utp_send.data_len = 0; + } + } + break; + } +#endif // #if (BLE_FEAT_LE_UTP == TRUE) default: BTC_TRACE_ERROR("Unhandled deep copy %d\n", msg->act); break; @@ -2958,6 +2999,15 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) break; } #endif // #if (BLE_FEAT_DBAF == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + case BTC_GAP_BLE_UTP_SEND: { + uint8_t *data = ((btc_ble_5_gap_args_t *)msg->arg)->utp_send.data; + if (data) { + osi_free(data); + } + break; + } +#endif // #if (BLE_FEAT_LE_UTP == TRUE) default: BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); break; @@ -3678,6 +3728,14 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) BTA_DmBleGapReadMinSuppConnInterval(); break; #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + case BTC_GAP_BLE_ENABLE_UTP_OTA_MODE: + BTA_DmBleGapEnableUtpOtaMode(arg_5->enable_utp_ota_mode.enable); + break; + case BTC_GAP_BLE_UTP_SEND: + BTA_DmBleGapUtpSend(arg_5->utp_send.data_len, arg_5->utp_send.data); + break; +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BT_BLE_FEAT_PAWR_EN == TRUE) case BTC_GAP_BLE_SET_PA_SUBEVT_DATA: BTA_DmBleGapSetPASubevtData(arg_5->per_adv_subevent_data_params.adv_handle, arg_5->per_adv_subevent_data_params.num_subevents_with_data, (uint8_t *)(arg_5->per_adv_subevent_data_params.subevent_params)); 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 b66538f76a7..7f4d6e590f8 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 @@ -163,6 +163,10 @@ typedef enum { BTC_GAP_BLE_SET_DEFAULT_RATE_PARAMETERS, BTC_GAP_BLE_READ_MIN_SUPP_CONN_INTERVAL, #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + BTC_GAP_BLE_ENABLE_UTP_OTA_MODE, + BTC_GAP_BLE_UTP_SEND, +#endif // #if (BLE_FEAT_LE_UTP == TRUE) BTC_GAP_BLE_READ_CHANNEL_MAP, #if (BT_BLE_FEAT_PAWR_EN == TRUE) BTC_GAP_BLE_SET_PA_SUBEVT_DATA, @@ -658,6 +662,15 @@ typedef union { uint16_t max_ce_len; } set_default_rate_parameters; #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + struct enable_utp_ota_mode_args { + uint8_t enable; + } enable_utp_ota_mode; + struct utp_send_args { + uint8_t data_len; + uint8_t *data; + } utp_send; +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BT_BLE_FEAT_PAWR_EN == TRUE) // BTC_GAP_BLE_SET_PA_SUBEVT_DATA struct per_adv_subevent_data_params_args { diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 1d36d769c7c..66575a782fd 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -350,13 +350,6 @@ #define UC_BT_BLE_FEAT_ADV_MONITOR FALSE #endif -#ifdef CONFIG_BT_BLE_FEAT_FRAME_SPACE_UPDATE -#define UC_BT_BLE_FEAT_FRAME_SPACE_UPDATE CONFIG_BT_BLE_FEAT_FRAME_SPACE_UPDATE -#else -#define UC_BT_BLE_FEAT_FRAME_SPACE_UPDATE FALSE -#endif - - #ifdef CONFIG_BT_BLE_FEAT_DBAF #define UC_BT_BLE_FEAT_DBAF CONFIG_BT_BLE_FEAT_DBAF #else @@ -376,6 +369,18 @@ #define UC_BT_BLE_FEAT_SHORTER_CONN_INTERVALS FALSE #endif +#ifdef CONFIG_BT_BLE_FEAT_LE_UTP +#define UC_BT_BLE_FEAT_LE_UTP CONFIG_BT_BLE_FEAT_LE_UTP +#else +#define UC_BT_BLE_FEAT_LE_UTP FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_FRAME_SPACE_UPDATE +#define UC_BT_BLE_FEAT_FRAME_SPACE_UPDATE CONFIG_BT_BLE_FEAT_FRAME_SPACE_UPDATE +#else +#define UC_BT_BLE_FEAT_FRAME_SPACE_UPDATE FALSE +#endif + #ifdef CONFIG_BT_BLE_VENDOR_HCI_EN #define UC_BT_BLE_VENDOR_HCI_EN CONFIG_BT_BLE_VENDOR_HCI_EN diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 66266553401..14a68cacd7a 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -437,6 +437,11 @@ #define BLE_FEAT_SHORTER_CONN_INTERVALS FALSE #endif +#if (BLE_50_FEATURE_SUPPORT == TRUE) && (UC_BT_BLE_FEAT_LE_UTP == TRUE) +#define BLE_FEAT_LE_UTP TRUE +#else +#define BLE_FEAT_LE_UTP FALSE +#endif #if (UC_BT_BLE_VENDOR_HCI_EN == TRUE) #define BLE_VENDOR_HCI_EN TRUE 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 e70f3aae9af..4ccdec8174e 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 @@ -1713,6 +1713,58 @@ void btm_ble_read_min_supp_conn_interval_complete(UINT8 *p) } #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +tBTM_STATUS BTM_BleEnableUtpOtaMode(UINT8 enable) +{ + tHCI_STATUS err; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_enable_utp_ota_mode(enable)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("LE EnableUtpOtaMode: cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.status = status; + BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_ENABLE_UTP_OTA_MODE_COMPLETE_EVT, &cb_params); + return status; +} + +tBTM_STATUS BTM_BleUtpSend(UINT8 data_len, const UINT8 *p_data) +{ + tHCI_STATUS err; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_utp_send(data_len, p_data)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("LE UtpSend: cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.status = status; + BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_UTP_SEND_COMPLETE_EVT, &cb_params); + return status; +} + +void btm_ble_utp_receive_evt(UINT8 *p, UINT16 len) +{ + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + UINT8 data_len; + + if (!p || len < 1) { + return; + } + + STREAM_TO_UINT8(data_len, p); + if (data_len == 0 || len < (UINT16)(1 + data_len)) { + return; + } + + cb_params.utp_receive.len = data_len; + cb_params.utp_receive.data = p; + BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_UTP_RECEIVE_EVT, &cb_params); +} +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_50_EXTEND_ADV_EN == TRUE) void btm_ble_scan_req_received_evt(tBTM_BLE_SCAN_REQ_RECEIVED *params) diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h index 3ca39f4bec7..398c2fec990 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h @@ -610,6 +610,9 @@ void btm_ble_read_all_remote_features_complete_evt(UINT8 *p); void btm_ble_conn_rate_change_evt(tBTM_BLE_CONN_RATE_CHANGE *params); void btm_ble_read_min_supp_conn_interval_complete(UINT8 *p); #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +void btm_ble_utp_receive_evt(UINT8 *p, UINT16 len); +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BT_BLE_FEAT_PAWR_EN == TRUE) void btm_ble_pa_subevt_data_req_evt(tBTM_BLE_PA_SUBEVT_DATA_REQ_EVT *params); void btm_ble_pa_rsp_rpt_evt(tBTM_BLE_PA_RSP_REPORT_EVT *params); diff --git a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c index d9782abfd7f..cb725a94ba2 100644 --- a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c @@ -3186,6 +3186,48 @@ UINT8 btsnd_hcic_ble_read_all_remote_features(UINT16 conn_handle, UINT8 page_req } #endif // #if (BLE_FEAT_LL_EXT_FEAT == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +UINT8 btsnd_hcic_ble_enable_utp_ota_mode(UINT8 enable) +{ + BT_HDR *p; + UINT8 *pp; + + if (enable > 1) { + return HCI_ERR_ILLEGAL_PARAMETER_FMT; + } + + HCIC_BLE_CMD_CREATED_U8(p, pp, HCIC_PARAM_SIZE_ENABLE_UTP_OTA_MODE); + UINT16_TO_STREAM(pp, HCI_BLE_ENABLE_UTP_OTA_MODE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ENABLE_UTP_OTA_MODE); + UINT8_TO_STREAM(pp, enable); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_utp_send(UINT8 data_len, const UINT8 *p_data) +{ + BT_HDR *p; + UINT8 *pp; + UINT16 param_len; + + if (data_len == 0 || data_len > BLE_UTP_DATA_MAX_LEN || p_data == NULL) { + return HCI_ERR_ILLEGAL_PARAMETER_FMT; + } + + param_len = HCIC_PARAM_SIZE_UTP_SEND_HDR + data_len; + if (param_len > HCIC_PARAM_SIZE_UTP_SEND_MAX) { + return HCI_ERR_ILLEGAL_PARAMETER_FMT; + } + + HCIC_BLE_CMD_CREATED_U8(p, pp, param_len); + UINT16_TO_STREAM(pp, HCI_BLE_UTP_SEND); + UINT8_TO_STREAM(pp, param_len); + UINT8_TO_STREAM(pp, data_len); + ARRAY_TO_STREAM(pp, p_data, data_len); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) UINT8 btsnd_hcic_ble_connection_rate_request(UINT16 conn_handle, UINT16 conn_interval_min, diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h index eb2428c1764..cdc884c627d 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h @@ -1007,6 +1007,11 @@ typedef void (tBTM_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK) (tBTM_STATUS st #define BTM_BLE_5_GAP_SET_DEFAULT_RATE_PARAMETERS_COMPLETE_EVT 86 #define BTM_BLE_5_GAP_READ_MIN_SUPP_CONN_INTERVAL_COMPLETE_EVT 87 #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +#define BTM_BLE_5_GAP_ENABLE_UTP_OTA_MODE_COMPLETE_EVT 83 +#define BTM_BLE_5_GAP_UTP_SEND_COMPLETE_EVT 84 +#define BTM_BLE_5_GAP_UTP_RECEIVE_EVT 85 +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #define BTM_BLE_5_GAP_UNKNOWN_EVT 91 typedef UINT8 tBTM_BLE_5_GAP_EVENT; @@ -1320,6 +1325,12 @@ typedef struct { } tBTM_BLE_READ_MIN_SUPP_CONN_INTERVAL; #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +typedef struct { + UINT8 len; + UINT8 *data; +} tBTM_BLE_UTP_RECEIVE; +#endif // #if (BLE_FEAT_LE_UTP == TRUE) typedef struct { UINT16 sync_handle; @@ -2043,6 +2054,9 @@ typedef union { tBTM_BLE_CONN_RATE_CHANGE conn_rate_change; tBTM_BLE_READ_MIN_SUPP_CONN_INTERVAL read_min_supp_conn_interval; #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) + tBTM_BLE_UTP_RECEIVE utp_receive; +#endif // #if (BLE_FEAT_LE_UTP == TRUE) } tBTM_BLE_5_GAP_CB_PARAMS; typedef struct { @@ -3234,6 +3248,10 @@ void BTM_BleSetDefaultRateParameters(UINT16 conn_interval_min, UINT16 conn_inter tBTM_STATUS BTM_BleReadMinSuppConnInterval(void); #endif // #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +tBTM_STATUS BTM_BleEnableUtpOtaMode(UINT8 enable); +tBTM_STATUS BTM_BleUtpSend(UINT8 data_len, const UINT8 *p_data); +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_50_DTM_TEST_EN == TRUE) diff --git a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h index c96524d626d..14259213170 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h @@ -494,6 +494,10 @@ #endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +#define HCI_BLE_ENABLE_UTP_OTA_MODE (0x009F | HCI_GRP_BLE_CMDS) +#define HCI_BLE_UTP_SEND (0x00A0 | HCI_GRP_BLE_CMDS) +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) #define HCI_BLE_CONNECTION_RATE_REQUEST (0x00A1 | HCI_GRP_BLE_CMDS) @@ -1004,6 +1008,9 @@ #define HCI_BLE_FRAME_SPACE_UPDATE_COMPLETE_EVT 0x35 #endif // #if (BLE_FEAT_FRAME_SPACE_UPDATE == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +#define HCI_BLE_UTP_RECEIVE_EVT 0x36 +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) #define HCI_BLE_CONN_RATE_CHANGE_EVT 0x37 diff --git a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h index 75c4f7ed95e..f9e6c91c20d 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h @@ -858,6 +858,15 @@ BOOLEAN btsnd_hcic_ble_read_all_local_supp_features(void); UINT8 btsnd_hcic_ble_read_all_remote_features(UINT16 conn_handle, UINT8 page_requested); #endif // #if (BLE_FEAT_LL_EXT_FEAT == TRUE) +#if (BLE_FEAT_LE_UTP == TRUE) +#define HCIC_PARAM_SIZE_ENABLE_UTP_OTA_MODE 1 +#define HCIC_PARAM_SIZE_UTP_SEND_HDR 1 +#define HCIC_PARAM_SIZE_UTP_SEND_MAX 255 +#define BLE_UTP_DATA_MAX_LEN 254 + +UINT8 btsnd_hcic_ble_enable_utp_ota_mode(UINT8 enable); +UINT8 btsnd_hcic_ble_utp_send(UINT8 data_len, const UINT8 *p_data); +#endif // #if (BLE_FEAT_LE_UTP == TRUE) #if (BLE_FEAT_SHORTER_CONN_INTERVALS == TRUE) #define HCIC_PARAM_SIZE_CONNECTION_RATE_REQUEST 20