Просмотр исходного кода

feat(ble/bluedroid): Add APIs for BLE direct test mode on bluedroid host

zhiweijian 2 лет назад
Родитель
Сommit
de148c3a5e

+ 97 - 0
components/bt/host/bluedroid/api/esp_gap_ble_api.c

@@ -818,6 +818,103 @@ esp_err_t esp_gap_ble_set_authorization(esp_bd_addr_t bd_addr, bool authorize)
     return ESP_FAIL;
 }
 
+#if (BLE_42_FEATURE_SUPPORT == TRUE)
+esp_err_t esp_ble_dtm_tx_start(const esp_ble_dtm_tx_t *tx_params)
+{
+    btc_msg_t msg = {0};
+    btc_ble_gap_args_t arg;
+
+    if (!tx_params) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GAP_BLE;
+    msg.act = BTC_GAP_BLE_DTM_TX_START;
+
+    memcpy(&arg.dtm_tx_start, tx_params, sizeof(esp_ble_dtm_tx_t));
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_dtm_rx_start(const esp_ble_dtm_rx_t *rx_params)
+{
+    btc_msg_t msg = {0};
+    btc_ble_gap_args_t arg;
+
+    if (!rx_params) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GAP_BLE;
+    msg.act = BTC_GAP_BLE_DTM_RX_START;
+
+     memcpy(&arg.dtm_rx_start, rx_params, sizeof(esp_ble_dtm_rx_t));
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE)
+
+#if (BLE_50_FEATURE_SUPPORT == TRUE)
+esp_err_t esp_ble_dtm_enh_tx_start(const esp_ble_dtm_enh_tx_t *tx_params)
+{
+    btc_msg_t msg = {0};
+    btc_ble_gap_args_t arg;
+
+    if (!tx_params) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GAP_BLE;
+    msg.act = BTC_GAP_BLE_DTM_ENH_TX_START;
+
+    memcpy(&arg.dtm_tx_start, tx_params, sizeof(esp_ble_dtm_enh_tx_t));
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_dtm_enh_rx_start(const esp_ble_dtm_enh_rx_t *rx_params)
+{
+    btc_msg_t msg = {0};
+    btc_ble_gap_args_t arg;
+
+    if (!rx_params) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GAP_BLE;
+    msg.act = BTC_GAP_BLE_DTM_ENH_RX_START;
+
+     memcpy(&arg.dtm_rx_start, rx_params, sizeof(esp_ble_dtm_enh_rx_t));
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
+
+esp_err_t esp_ble_dtm_stop(void)
+{
+    btc_msg_t msg = {0};
+
+    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GAP_BLE;
+    msg.act = BTC_GAP_BLE_DTM_STOP;
+
+    return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
 #if (BLE_50_FEATURE_SUPPORT == TRUE)
 
 esp_err_t esp_ble_gap_read_phy(esp_bd_addr_t bd_addr)

+ 133 - 0
components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h

@@ -208,6 +208,8 @@ typedef enum {
     ESP_GAP_BLE_PERIODIC_ADV_SET_INFO_TRANS_COMPLETE_EVT,        /*!< when periodic advertising set info transfer complete, the event comes */
     ESP_GAP_BLE_SET_PAST_PARAMS_COMPLETE_EVT,                    /*!< when set periodic advertising sync transfer params complete, the event comes */
     ESP_GAP_BLE_PERIODIC_ADV_SYNC_TRANS_RECV_EVT,                /*!< when periodic advertising sync transfer received, the event comes */
+    // DTM
+    ESP_GAP_BLE_DTM_TEST_UPDATE_EVT,                             /*!< when direct test mode state changes, the event comes */
     ESP_GAP_BLE_EVT_MAX,                                         /*!< when maximum advertising event complete, the event comes */
 } esp_gap_ble_cb_event_t;
 
@@ -339,7 +341,45 @@ typedef enum {
     ESP_BLE_SM_MAX_PARAM,
 } esp_ble_sm_param_t;
 
+typedef enum {
+    /// DTM TX start event
+    DTM_TX_START_EVT  = 0x00,
+    ///DTM RX start event
+    DTM_RX_START_EVT,
+    ///DTM test end event
+    DTM_TEST_STOP_EVT,
+} esp_ble_dtm_update_evt_t;
+
+typedef enum {
+    BLE_DTM_PKT_PAYLOAD_0x00,       /*!< PRBS9 sequence ‘11111111100000111101...’ (in transmission order) as described in [Vol 6] Part F, Section 4.1.5 */
+    BLE_DTM_PKT_PAYLOAD_0x01,       /*!< Repeated ‘11110000’ (in transmission order) sequence as described in [Vol 6] Part F, Section 4.1.5 */
+    BLE_DTM_PKT_PAYLOAD_0x02,       /*!< Repeated ‘10101010’ (in transmission order) sequence as described in [Vol 6] Part F, Section 4.1.5 */
+    BLE_DTM_PKT_PAYLOAD_0x03,       /*!< PRBS15 sequence as described in [Vol 6] Part F, Section 4.1.5 */
+    BLE_DTM_PKT_PAYLOAD_0x04,       /*!< Repeated ‘11111111’ (in transmission order) sequence */
+    BLE_DTM_PKT_PAYLOAD_0x05,       /*!< Repeated ‘00000000’ (in transmission order) sequence */
+    BLE_DTM_PKT_PAYLOAD_0x06,       /*!< Repeated ‘00001111’ (in transmission order) sequence */
+    BLE_DTM_PKT_PAYLOAD_0x07,       /*!< Repeated ‘01010101’ (in transmission order) sequence */
+    BLE_DTM_PKT_PAYLOAD_MAX,        /*!< 0x08 ~ 0xFF, Reserved for future use */
+} esp_ble_dtm_pkt_payload_t;
+
 #if (BLE_42_FEATURE_SUPPORT == TRUE)
+/**
+* @brief DTM TX parameters
+*/
+typedef struct
+{
+    uint8_t                         tx_channel;            /*!<  channel for sending test data, tx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */
+    uint8_t                         len_of_data;           /*!<  length in bytes of payload data in each packet */
+    esp_ble_dtm_pkt_payload_t       pkt_payload;           /*!<  packet payload type. value range: 0x00-0x07 */
+} esp_ble_dtm_tx_t;
+/**
+* @brief DTM RX parameters
+*/
+typedef struct
+{
+    uint8_t          rx_channel;            /*!<  channel for test data reception, rx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */
+} esp_ble_dtm_rx_t;
+
 /// Advertising parameters
 typedef struct {
     uint16_t                adv_int_min;        /*!< Minimum advertising interval for
@@ -918,6 +958,27 @@ typedef struct {
     uint8_t adv_clk_accuracy;                     /*!< periodic advertising clock accuracy */
 } esp_ble_gap_periodic_adv_sync_estab_t;
 
+/**
+* @brief DTM TX parameters
+*/
+typedef struct
+{
+    uint8_t                     tx_channel;            /*!<  channel for sending test data, tx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */
+    uint8_t                     len_of_data;           /*!<  length in bytes of payload data in each packet */
+    esp_ble_dtm_pkt_payload_t   pkt_payload;           /*!<  packet payload type. value range: 0x00-0x07 */
+    esp_ble_gap_phy_t           phy;                   /*!<  the phy type used by the transmitter, coded phy with S=2:0x04 */
+} esp_ble_dtm_enh_tx_t;
+
+/**
+* @brief DTM RX parameters
+*/
+typedef struct
+{
+    uint8_t             rx_channel;            /*!<  channel for test data reception, rx_channel = (Frequency -2402)/2, tx_channel range:0x00-0x27, Frequency range: 2402 MHz to 2480 MHz */
+    esp_ble_gap_phy_t   phy;                   /*!<  the phy type used by the receiver, 1M phy: 0x01, 2M phy:0x02, coded phy:0x03 */
+    uint8_t             modulation_idx;        /*!<  modulation index, 0x00:standard modulation index, 0x01:stable modulation index */
+} esp_ble_dtm_enh_rx_t;
+
 #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE)
 
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
@@ -1381,6 +1442,14 @@ typedef union {
         uint8_t adv_clk_accuracy;           /*!< Periodic advertising clock accuracy */
     } past_received;                        /*!< Event parameter of ESP_GAP_BLE_PERIODIC_ADV_SYNC_TRANS_RECV_EVT */
 #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
+    /**
+     * @brief ESP_GAP_BLE_DTM_TEST_UPDATE_EVT
+     */
+    struct ble_dtm_state_update_evt_param {
+        esp_bt_status_t status;                     /*!< Indicate DTM operation success status */
+        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 */
 } esp_ble_gap_cb_param_t;
 
 /**
@@ -2366,6 +2435,70 @@ esp_err_t esp_ble_gap_set_periodic_adv_sync_trans_params(esp_bd_addr_t addr,
                                                          const esp_ble_gap_past_params_t *params);
 #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
 
+#if (BLE_42_FEATURE_SUPPORT == TRUE)
+
+/**
+* @brief           This function is used to start a test where the DUT generates reference packets
+*                  at a fixed interval.
+*
+* @param[in]       tx_params : DTM Transmitter parameters
+*
+* @return            - ESP_OK : success
+*                    - other  : failed
+*
+*/
+esp_err_t esp_ble_dtm_tx_start(const esp_ble_dtm_tx_t *tx_params);
+
+/**
+* @brief           This function is used to start a test where the DUT receives test reference packets
+*                  at a fixed interval.
+*
+* @param[in]       rx_params : DTM Receiver parameters
+*
+* @return            - ESP_OK : success
+*                    - other  : failed
+*
+*/
+esp_err_t esp_ble_dtm_rx_start(const esp_ble_dtm_rx_t *rx_params);
+#endif //#if (BLE_42_FEATURE_SUPPORT == TRUE)
+
+#if (BLE_50_FEATURE_SUPPORT == TRUE)
+
+/**
+* @brief           This function is used to start a test where the DUT generates reference packets
+*                  at a fixed interval.
+*
+* @param[in]       tx_params : DTM Transmitter parameters
+*
+* @return            - ESP_OK : success
+*                    - other  : failed
+*
+*/
+esp_err_t esp_ble_dtm_enh_tx_start(const esp_ble_dtm_enh_tx_t *tx_params);
+
+/**
+* @brief           This function is used to start a test where the DUT receives test reference packets
+*                  at a fixed interval.
+*
+* @param[in]       rx_params : DTM Receiver parameters
+*
+* @return            - ESP_OK : success
+*                    - other  : failed
+*
+*/
+esp_err_t esp_ble_dtm_enh_rx_start(const esp_ble_dtm_enh_rx_t *rx_params);
+#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
+
+/**
+* @brief           This function is used to stop any test which is in progress
+*
+*
+* @return            - ESP_OK : success
+*                    - other  : failed
+*
+*/
+esp_err_t esp_ble_dtm_stop(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 28 - 0
components/bt/host/bluedroid/bta/dm/bta_dm_act.c

@@ -5686,7 +5686,35 @@ void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data)
                                     p_data->ble_multi_adv_disable.inst_id, p_ref, BTA_FAILURE);
     }
 }
+
+void bta_dm_ble_gap_dtm_tx_start(tBTA_DM_MSG *p_data)
+{
+    BTM_BleTransmitterTest(p_data->dtm_tx_start.tx_channel, p_data->dtm_tx_start.len_of_data, p_data->dtm_tx_start.pkt_payload, p_data->dtm_tx_start.p_dtm_cmpl_cback);
+}
+
+void bta_dm_ble_gap_dtm_rx_start(tBTA_DM_MSG *p_data)
+{
+    BTM_BleReceiverTest(p_data->dtm_rx_start.rx_channel, p_data->dtm_rx_start.p_dtm_cmpl_cback);
+}
+
+void bta_dm_ble_gap_dtm_stop(tBTA_DM_MSG *p_data)
+{
+    BTM_BleTestEnd(p_data->dtm_stop.p_dtm_cmpl_cback);
+}
+
 #if (BLE_50_FEATURE_SUPPORT == TRUE)
+void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data)
+{
+    BTM_BleEnhancedTransmitterTest(p_data->dtm_enh_tx_start.tx_channel, p_data->dtm_enh_tx_start.len_of_data,
+                                    p_data->dtm_enh_tx_start.pkt_payload, p_data->dtm_enh_tx_start.phy, p_data->dtm_enh_tx_start.p_dtm_cmpl_cback);
+}
+
+void bta_dm_ble_gap_dtm_enhance_rx_start(tBTA_DM_MSG *p_data)
+{
+    BTM_BleEnhancedReceiverTest(p_data->dtm_enh_rx_start.rx_channel, p_data->dtm_enh_rx_start.phy,
+                                    p_data->dtm_enh_rx_start.modulation_index, p_data->dtm_enh_rx_start.p_dtm_cmpl_cback);
+}
+
 void bta_dm_ble_gap_read_phy(tBTA_DM_MSG *p_data)
 {
     //tBTM_STATUS btm_status = 0;

+ 76 - 0
components/bt/host/bluedroid/bta/dm/bta_dm_api.c

@@ -2547,6 +2547,49 @@ void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length, tBTA_S
     }
 }
 
+void BTA_DmBleDtmTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+    tBTA_DM_API_BLE_DTM_TX_START *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_DTM_TX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_TX_START)))
+            != NULL) {
+        p_msg->hdr.event = BTA_DM_API_DTM_TX_START_EVT;
+        p_msg->tx_channel = tx_channel;
+        p_msg->len_of_data = len_of_data;
+        p_msg->pkt_payload = pkt_payload;
+        p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+void BTA_DmBleDtmRxStart(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+    tBTA_DM_API_BLE_DTM_RX_START *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_DTM_RX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_RX_START)))
+            != NULL) {
+        p_msg->hdr.event = BTA_DM_API_DTM_RX_START_EVT;
+        p_msg->rx_channel= rx_channel;
+        p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+    tBTA_DM_API_BLE_DTM_STOP *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_DTM_STOP *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_STOP)))
+            != NULL) {
+        p_msg->hdr.event = BTA_DM_API_DTM_STOP_EVT;
+        p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
 #endif
 
 /*******************************************************************************
@@ -3228,6 +3271,39 @@ void BTA_DmBleGapExtConnect(tBLE_ADDR_TYPE own_addr_type, const BD_ADDR peer_add
 
 }
 
+void BTA_DmBleDtmEnhTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+    tBTA_DM_API_BLE_DTM_ENH_TX_START *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_DTM_ENH_TX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_ENH_TX_START)))
+            != NULL) {
+        p_msg->hdr.event = BTA_DM_API_DTM_ENH_TX_START_EVT;
+        p_msg->tx_channel = tx_channel;
+        p_msg->len_of_data = len_of_data;
+        p_msg->pkt_payload = pkt_payload;
+        p_msg->phy = phy;
+        p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+void BTA_DmBleDtmEnhRxStart(uint8_t rx_channel, uint8_t phy, uint8_t modulation_index, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+    tBTA_DM_API_BLE_DTM_ENH_RX_START *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_DTM_ENH_RX_START *)osi_malloc(sizeof(tBTA_DM_API_BLE_DTM_ENH_RX_START)))
+            != NULL) {
+        p_msg->hdr.event = BTA_DM_API_DTM_ENH_RX_START_EVT;
+        p_msg->rx_channel= rx_channel;
+        p_msg->phy = phy;
+        p_msg->modulation_index = modulation_index;
+        p_msg->p_dtm_cmpl_cback = p_dtm_cmpl_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
 
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)

+ 7 - 0
components/bt/host/bluedroid/bta/dm/bta_dm_main.c

@@ -211,6 +211,8 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
     bta_dm_ble_gap_ext_scan,                /* BTA_DM_API_START_EXT_SCAN_EVT */
     bta_dm_ble_gap_set_prefer_ext_conn_params, /* BTA_DM_API_SET_PERF_EXT_CONN_PARAMS_EVT */
     NULL,                                   /* BTA_DM_API_EXT_CONN_EVT */
+    bta_dm_ble_gap_dtm_enhance_tx_start,    /* BTA_DM_API_DTM_ENH_TX_START_EVT */
+    bta_dm_ble_gap_dtm_enhance_rx_start,    /* BTA_DM_API_DTM_ENH_RX_START_EVT */
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
     bta_dm_ble_gap_periodic_adv_recv_enable, /* BTA_DM_API_PERIODIC_ADV_RECV_ENABLE_EVT */
@@ -218,6 +220,11 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
     bta_dm_ble_gap_periodic_adv_set_info_trans, /* BTA_DM_API_PERIODIC_ADV_SET_INFO_TRANS_EVT */
     bta_dm_ble_gap_set_periodic_adv_sync_trans_params, /* BTA_DM_API_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS_EVT */
 #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
+#if BLE_INCLUDED == TRUE
+    bta_dm_ble_gap_dtm_tx_start, /* BTA_DM_API_DTM_TX_START_EVT */
+    bta_dm_ble_gap_dtm_rx_start, /* BTA_DM_API_DTM_RX_START_EVT */
+    bta_dm_ble_gap_dtm_stop, /* BTA_DM_API_DTM_STOP_EVT */
+#endif
 };
 
 

+ 54 - 0
components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h

@@ -204,6 +204,8 @@ enum {
     BTA_DM_API_START_EXT_SCAN_EVT,
     BTA_DM_API_SET_PERF_EXT_CONN_PARAMS_EVT,
     BTA_DM_API_EXT_CONN_EVT,
+    BTA_DM_API_DTM_ENH_TX_START_EVT,
+    BTA_DM_API_DTM_ENH_RX_START_EVT,
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
     BTA_DM_API_PERIODIC_ADV_RECV_ENABLE_EVT,
@@ -211,6 +213,11 @@ enum {
     BTA_DM_API_PERIODIC_ADV_SET_INFO_TRANS_EVT,
     BTA_DM_API_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS_EVT,
 #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
+#if BLE_INCLUDED == TRUE
+    BTA_DM_API_DTM_TX_START_EVT,
+    BTA_DM_API_DTM_RX_START_EVT,
+    BTA_DM_API_DTM_STOP_EVT,
+#endif
     BTA_DM_MAX_EVT
 };
 
@@ -870,6 +877,25 @@ typedef struct {
     BD_ADDR     remote_bda;
 } tBTA_DM_API_BLE_DISCONNECT;
 
+typedef struct {
+    BT_HDR      hdr;
+    UINT8      tx_channel;
+    UINT8      len_of_data;
+    UINT8      pkt_payload;
+    tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback;
+} tBTA_DM_API_BLE_DTM_TX_START;
+
+typedef struct {
+    BT_HDR      hdr;
+    UINT8      rx_channel;
+    tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback;
+} tBTA_DM_API_BLE_DTM_RX_START;
+
+typedef struct {
+    BT_HDR      hdr;
+    tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback;
+} tBTA_DM_API_BLE_DTM_STOP;
+
 #endif /* BLE_INCLUDED */
 
 /* data type for BTA_DM_API_REMOVE_ACL_EVT */
@@ -926,6 +952,22 @@ typedef struct {
 #endif
 #if (BLE_50_FEATURE_SUPPORT == TRUE)
 
+typedef struct {
+    BT_HDR     hdr;
+    UINT8      tx_channel;
+    UINT8      len_of_data;
+    UINT8      pkt_payload;
+    UINT8      phy;
+    tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback;
+} tBTA_DM_API_BLE_DTM_ENH_TX_START;
+typedef struct {
+    BT_HDR     hdr;
+    UINT8      rx_channel;
+    UINT8      phy;
+    UINT8      modulation_index;
+    tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback;
+} tBTA_DM_API_BLE_DTM_ENH_RX_START;
+
 #define BTA_PHY_1M_MASK                   (1 << 0)
 #define BTA_PHY_2M_MASK                   (1 << 1)
 #define BTAS_PHY_CODED_MASK               (1 << 2)
@@ -1238,6 +1280,8 @@ typedef union {
     tBTA_DM_API_SET_EXT_SCAN_PARAMS     ble_set_ext_scan_params;
     tBTA_DM_API_EXT_SCAN                ble_ext_scan;
     tBTA_DM_API_SET_PER_EXT_CONN_PARAMS ble_set_per_ext_conn_params;
+    tBTA_DM_API_BLE_DTM_ENH_TX_START    dtm_enh_tx_start;
+    tBTA_DM_API_BLE_DTM_ENH_RX_START    dtm_enh_rx_start;
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
     tBTA_DM_API_PERIODIC_ADV_RECV_ENABLE ble_periodic_adv_recv_enable;
@@ -1245,6 +1289,10 @@ typedef union {
     tBTA_DM_API_PERIODIC_ADV_SET_INFO_TRANS ble_periodic_adv_set_info_trans;
     tBTA_DM_API_SET_PAST_PARAMS ble_set_past_params;
 #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
+
+    tBTA_DM_API_BLE_DTM_TX_START    dtm_tx_start;
+    tBTA_DM_API_BLE_DTM_RX_START    dtm_rx_start;
+    tBTA_DM_API_BLE_DTM_STOP        dtm_stop;
 #endif
 
     tBTA_DM_API_REMOVE_ACL              remove_acl;
@@ -1681,7 +1729,13 @@ extern void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_gap_dtm_tx_start(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_gap_dtm_rx_start(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_gap_dtm_stop(tBTA_DM_MSG *p_data);
+
 #if (BLE_50_FEATURE_SUPPORT == TRUE)
+extern void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_gap_dtm_enhance_rx_start(tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_gap_read_phy(tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_gap_set_prefer_default_phy(tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_gap_set_prefer_phy(tBTA_DM_MSG *p_data);

+ 10 - 0
components/bt/host/bluedroid/bta/include/bta/bta_api.h

@@ -425,6 +425,8 @@ typedef tBTM_UPDATE_WHITELIST_CBACK tBTA_UPDATE_WHITELIST_CBACK;
 
 typedef tBTM_SET_PKT_DATA_LENGTH_CBACK tBTA_SET_PKT_DATA_LENGTH_CBACK;
 
+typedef tBTM_DTM_CMD_CMPL_CBACK tBTA_DTM_CMD_CMPL_CBACK;
+
 typedef tBTM_SET_RAND_ADDR_CBACK tBTA_SET_RAND_ADDR_CBACK;
 
 typedef tBTM_SET_LOCAL_PRIVACY_CBACK tBTA_SET_LOCAL_PRIVACY_CBACK;
@@ -2815,6 +2817,10 @@ extern void BTA_DmBleDisconnect(BD_ADDR bd_addr);
 *******************************************************************************/
 extern void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length, tBTA_SET_PKT_DATA_LENGTH_CBACK *p_set_pkt_data_cback);
 
+extern void BTA_DmBleDtmTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback);
+extern void BTA_DmBleDtmRxStart(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback);
+extern void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback);
+
 /*******************************************************************************
 **
 ** Function         BTA_DmBleSetStorageParams
@@ -3069,6 +3075,10 @@ extern void BTA_DmBleGapPreferExtConnectParamsSet(BD_ADDR bd_addr,
                                                   const tBTA_DM_BLE_CONN_PARAMS *phy_coded_conn_params);
 
 extern void BTA_DmBleGapExtConnect(tBLE_ADDR_TYPE own_addr_type, const BD_ADDR peer_addr);
+
+extern void BTA_DmBleDtmEnhTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback);
+
+extern void BTA_DmBleDtmEnhRxStart(uint8_t rx_channel, uint8_t phy, uint8_t modulation_index, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback);
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
 
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)

+ 136 - 0
components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c

@@ -1145,6 +1145,91 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event,
     }
 }
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
+
+void btc_dtm_tx_start_callback(void *p1)
+{
+    UINT8 status;
+    UINT8 *p;
+    p = (UINT8*) p1;
+    if (p1) {
+        STREAM_TO_UINT8(status, p);
+        BTC_TRACE_DEBUG("DTM TX start, status 0x%x\n", status);
+        esp_ble_gap_cb_param_t param;
+        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_DTM_TEST_UPDATE_EVT;
+        param.dtm_state_update.status = status;
+        param.dtm_state_update.update_evt = DTM_TX_START_EVT;
+        param.dtm_state_update.num_of_pkt = 0;
+
+        ret = btc_transfer_context(&msg, &param,
+                                sizeof(esp_ble_gap_cb_param_t), NULL, NULL);
+
+        if (ret != BT_STATUS_SUCCESS) {
+            BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
+        }
+    }
+}
+
+void btc_dtm_rx_start_callback(void *p1)
+{
+
+    UINT8 status;
+    UINT8 *p;
+    p = (UINT8*) p1;
+    if (p1) {
+        STREAM_TO_UINT8(status, p);
+        BTC_TRACE_DEBUG("DTM RX start, status 0x%x\n", status);
+        esp_ble_gap_cb_param_t param;
+        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_DTM_TEST_UPDATE_EVT;
+        param.dtm_state_update.status = status;
+        param.dtm_state_update.update_evt = DTM_RX_START_EVT;
+        param.dtm_state_update.num_of_pkt = 0;
+
+        ret = btc_transfer_context(&msg, &param,
+                                sizeof(esp_ble_gap_cb_param_t), NULL, NULL);
+
+        if (ret != BT_STATUS_SUCCESS) {
+            BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
+        }
+    }
+}
+
+void btc_dtm_stop_callback(void *p1)
+{
+    UINT8 status;
+    UINT16 num_pkt;
+    UINT8 *p;
+    p = (UINT8*) p1;
+    if (p1) {
+        STREAM_TO_UINT8(status, p);
+        STREAM_TO_UINT16(num_pkt, p);
+        BTC_TRACE_DEBUG("DTM stop, status 0x%x num_pkt %d\n", status, num_pkt);
+        esp_ble_gap_cb_param_t param;
+        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_DTM_TEST_UPDATE_EVT;
+        param.dtm_state_update.status = status;
+        param.dtm_state_update.update_evt = DTM_TEST_STOP_EVT;
+        param.dtm_state_update.num_of_pkt = num_pkt;
+
+        ret = btc_transfer_context(&msg, &param,
+                                sizeof(esp_ble_gap_cb_param_t), NULL, NULL);
+
+        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);
@@ -1274,6 +1359,38 @@ static void btc_gap_ble_set_channels(esp_gap_ble_channels channels)
     BTA_DmBleSetChannels(channels, btc_gap_ble_set_channels_cmpl_callback);
 }
 
+#if (BLE_42_FEATURE_SUPPORT == TRUE)
+static void btc_ble_dtm_tx_start(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+    BTA_DmBleDtmTxStart(tx_channel, len_of_data, pkt_payload, p_dtm_cmpl_cback);
+}
+
+static void btc_ble_dtm_rx_start(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+
+    BTA_DmBleDtmRxStart(rx_channel, p_dtm_cmpl_cback);
+}
+#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE)
+
+#if (BLE_50_FEATURE_SUPPORT == TRUE)
+static void btc_ble_dtm_enhance_tx_start(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+    BTA_DmBleDtmEnhTxStart(tx_channel, len_of_data, pkt_payload, phy, p_dtm_cmpl_cback);
+}
+
+static void btc_ble_dtm_enhance_rx_start(uint8_t rx_channel, uint8_t phy, uint8_t modulation_index, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+
+    BTA_DmBleDtmEnhRxStart(rx_channel, phy, modulation_index, p_dtm_cmpl_cback);
+}
+#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
+
+static void btc_ble_dtm_stop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback)
+{
+
+    BTA_DmBleDtmStop(p_dtm_cmpl_cback);
+}
+
 
 void btc_gap_ble_cb_handler(btc_msg_t *msg)
 {
@@ -2019,6 +2136,25 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
                                                   (tBTA_DM_BLE_PAST_PARAMS *)&arg_5->set_periodic_adv_sync_trans_params.params);
         break;
 #endif
+#if (BLE_42_FEATURE_SUPPORT == TRUE)
+    case BTC_GAP_BLE_DTM_TX_START:
+        btc_ble_dtm_tx_start(arg->dtm_tx_start.tx_channel, arg->dtm_tx_start.len_of_data, arg->dtm_tx_start.pkt_payload, btc_dtm_tx_start_callback);
+        break;
+    case BTC_GAP_BLE_DTM_RX_START:
+        btc_ble_dtm_rx_start(arg->dtm_rx_start.rx_channel, btc_dtm_rx_start_callback);
+        break;
+#endif // if (BLE_42_FEATURE_SUPPORT == TRUE)
+    case BTC_GAP_BLE_DTM_STOP:
+        btc_ble_dtm_stop(btc_dtm_stop_callback);
+        break;
+#if (BLE_50_FEATURE_SUPPORT == TRUE)
+    case BTC_GAP_BLE_DTM_ENH_TX_START:
+        btc_ble_dtm_enhance_tx_start(arg_5->dtm_enh_tx_start.tx_channel, arg_5->dtm_enh_tx_start.len_of_data, arg_5->dtm_enh_tx_start.pkt_payload, arg_5->dtm_enh_tx_start.phy, btc_dtm_tx_start_callback);
+        break;
+    case BTC_GAP_BLE_DTM_ENH_RX_START:
+        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)
     default:
         break;
     }

+ 26 - 1
components/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h

@@ -84,6 +84,8 @@ typedef enum {
     BTC_GAP_BLE_START_EXT_SCAN,
     BTC_GAP_BLE_STOP_EXT_SCAN,
     BTC_GAP_BLE_SET_EXT_PEFER_CONNET_PARAMS,
+    BTC_GAP_BLE_DTM_ENH_TX_START,
+    BTC_GAP_BLE_DTM_ENH_RX_START,
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
     BTC_GAP_BLE_ACT_GET_DEV_NAME,
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
@@ -92,6 +94,11 @@ typedef enum {
     BTC_GAP_BLE_PERIODIC_ADV_SET_INFO_TRANS,
     BTC_GAP_BLE_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS,
 #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
+#if (BLE_42_FEATURE_SUPPORT == TRUE)
+    BTC_GAP_BLE_DTM_TX_START,
+    BTC_GAP_BLE_DTM_RX_START,
+#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE)
+    BTC_GAP_BLE_DTM_STOP,
 } btc_gap_ble_act_t;
 
 /* btc_ble_gap_args_t */
@@ -230,6 +237,14 @@ typedef union {
     struct set_channels_args {
        esp_gap_ble_channels channels;
     } set_channels;
+    struct dtm_tx_start_args {
+        uint8_t tx_channel;
+        uint8_t len_of_data;
+        uint8_t pkt_payload;
+    } dtm_tx_start;
+    struct dtm_rx_start_args {
+        uint8_t rx_channel;
+    } dtm_rx_start;
 } btc_ble_gap_args_t;
 #if (BLE_50_FEATURE_SUPPORT == TRUE)
 
@@ -373,7 +388,17 @@ typedef union {
         esp_ble_gap_past_params_t params;
     } set_periodic_adv_sync_trans_params;
 #endif
-
+     struct dtm_enh_tx_start_args {
+        uint8_t tx_channel;
+        uint8_t len_of_data;
+        uint8_t pkt_payload;
+        uint8_t phy;
+    } dtm_enh_tx_start;
+    struct dtm_enh_rx_start_args {
+        uint8_t rx_channel;
+        uint8_t phy;
+        uint8_t modulation_index;
+    } dtm_enh_rx_start;
 } btc_ble_5_gap_args_t;
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
 

+ 6 - 2
components/bt/host/bluedroid/stack/hcic/hciblecmds.c

@@ -1169,7 +1169,9 @@ UINT8 btsnd_hcic_ble_enhand_rx_test(UINT8 rx_channel, UINT8 phy,
     UINT8_TO_STREAM(pp, phy);
     UINT8_TO_STREAM(pp, modulation_idx);
 
-    return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p);
+    btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return TRUE;
 }
 
 UINT8 btsnd_hcic_ble_enhand_tx_test(UINT8 tx_channel, UINT8 len,
@@ -1191,7 +1193,9 @@ UINT8 btsnd_hcic_ble_enhand_tx_test(UINT8 tx_channel, UINT8 len,
     UINT8_TO_STREAM(pp, packect);
     UINT8_TO_STREAM(pp, phy);
 
-    return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p);
+    btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return TRUE;
 }
 
 UINT8 btsnd_hcic_ble_set_extend_rand_address(UINT8 adv_handle, BD_ADDR rand_addr)

+ 2 - 0
components/bt/host/bluedroid/stack/include/stack/btm_api.h

@@ -189,6 +189,8 @@ typedef void (tBTM_UPDATE_CONN_PARAM_CBACK) (UINT8 status, BD_ADDR bd_addr, tBTM
 
 typedef void (tBTM_SET_PKT_DATA_LENGTH_CBACK) (UINT8 status, tBTM_LE_SET_PKT_DATA_LENGTH_PARAMS *data_length_params);
 
+typedef void (tBTM_DTM_CMD_CMPL_CBACK) (void *p1);
+
 typedef void (tBTM_SET_RAND_ADDR_CBACK) (UINT8 status);
 
 typedef void (tBTM_UPDATE_WHITELIST_CBACK) (UINT8 status, tBTM_WL_OPERATION wl_opration);

+ 5 - 0
components/bt/host/bluedroid/stack/include/stack/btm_ble_api.h

@@ -2688,6 +2688,11 @@ tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params);
 tBTM_STATUS BTM_BleExtendedScan(BOOLEAN enable, UINT16 duration, UINT16 period);
 
 void BTM_BleSetPreferExtenedConnParams(BD_ADDR bd_addr, tBTM_EXT_CONN_PARAMS *params);
+
+void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_index, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+void BTM_BleEnhancedTransmitterTest(UINT8 tx_freq, UINT8 test_data_len, UINT8 packet_payload, UINT8 phy, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
 
 #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)