Przeglądaj źródła

feat(bt/api): Add new apis for hfp to get the numbers of packet status received and sent

chenqingqing 2 lat temu
rodzic
commit
75efaa6465
23 zmienionych plików z 499 dodań i 49 usunięć
  1. 22 2
      components/bt/host/bluedroid/api/esp_hf_ag_api.c
  2. 22 3
      components/bt/host/bluedroid/api/esp_hf_client_api.c
  3. 31 0
      components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h
  4. 32 1
      components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h
  5. 25 3
      components/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c
  6. 13 5
      components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c
  7. 27 0
      components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c
  8. 11 1
      components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h
  9. 22 1
      components/bt/host/bluedroid/bta/hf_client/bta_hf_client_api.c
  10. 9 2
      components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c
  11. 25 1
      components/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c
  12. 9 0
      components/bt/host/bluedroid/bta/hf_client/include/bta_hf_client_int.h
  13. 27 0
      components/bt/host/bluedroid/bta/include/bta/bta_ag_api.h
  14. 26 0
      components/bt/host/bluedroid/bta/include/bta/bta_hf_client_api.h
  15. 30 1
      components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c
  16. 33 20
      components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c
  17. 8 2
      components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h
  18. 8 1
      components/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h
  19. 79 0
      components/bt/host/bluedroid/stack/btm/btm_sco.c
  20. 1 0
      components/bt/host/bluedroid/stack/btm/include/btm_int.h
  21. 22 0
      components/bt/host/bluedroid/stack/include/stack/btm_api.h
  22. 9 3
      examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c
  23. 8 3
      examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c

+ 22 - 2
components/bt/host/bluedroid/api/esp_hf_ag_api.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -512,10 +512,30 @@ esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_h
 }
 
 #if (BTM_SCO_HCI_INCLUDED == TRUE)
+esp_err_t esp_hf_ag_pkt_stat_nums_get(uint16_t sync_conn_handle)
+{
+    if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    btc_msg_t msg;
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_HF;
+    msg.act = BTC_HF_REQUEST_PKT_STAT_EVT;
+
+    btc_hf_args_t arg;
+    memset(&arg, 0, sizeof(btc_hf_args_t));
+    arg.pkt_sync_hd.sync_conn_handle = sync_conn_handle;
+
+    /* Switch to BTC context */
+    bt_status_t status = btc_transfer_context(&msg, &arg, sizeof(btc_hf_args_t), NULL, NULL);
+    return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
+}
+
 void esp_hf_ag_outgoing_data_ready(void)
 {
     btc_hf_ci_sco_data();
 }
-#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
+#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */
 
 #endif // BTC_HF_INCLUDED

+ 22 - 3
components/bt/host/bluedroid/api/esp_hf_client_api.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -515,8 +515,27 @@ esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t
     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
 }
 
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+esp_err_t esp_hf_client_pkt_stat_nums_get(uint16_t sync_conn_handle)
+{
+    if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    btc_msg_t msg;
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_HF_CLIENT;
+    msg.act = BTC_HF_CLIENT_REQUEST_PKT_STAT_EVT;
+
+    btc_hf_client_args_t arg;
+    memset(&arg, 0, sizeof(btc_hf_client_args_t));
+    arg.pkt_sync_hd.sync_conn_handle = sync_conn_handle;
+
+    /* Switch to BTC context */
+    bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL, NULL);
+    return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
+}
 
-#if (BTM_SCO_HCI_INCLUDED == TRUE )
 void esp_hf_client_outgoing_data_ready(void)
 {
     BTA_HfClientCiData();
@@ -537,6 +556,6 @@ int32_t esp_hf_client_pcm_resample(void *src, uint32_t in_bytes, void *dst)
     return BTA_DmPcmResample(src, in_bytes, dst);
 }
 
-#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
+#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */
 
 #endif /* BTC_HF_CLIENT_INCLUDED */

+ 31 - 0
components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h

@@ -62,6 +62,7 @@ typedef enum
     ESP_HF_DIAL_EVT,                          /*!< Origin an outgoing call with specific number or the dial the last number */
     ESP_HF_WBS_RESPONSE_EVT,                  /*!< Codec Status */
     ESP_HF_BCS_RESPONSE_EVT,                  /*!< Final Codec Choice */
+    ESP_HF_PKT_STAT_NUMS_GET_EVT,             /*!< Request number of packet different status */
 } esp_hf_cb_event_t;
 
 /// Dial type of ESP_HF_DIAL_EVT
@@ -91,6 +92,7 @@ typedef union
     struct hf_audio_stat_param {
         esp_bd_addr_t remote_addr;                /*!< Remote bluetooth device address */
         esp_hf_audio_state_t state;               /*!< Audio connection state */
+        uint16_t sync_conn_handle;                /*!< (e)SCO connection handle */
     } audio_stat;                                 /*!< AG callback param of ESP_HF_AUDIO_STATE_EVT */
 
     /**
@@ -208,6 +210,19 @@ typedef union
         esp_hf_wbs_config_t mode;                 /*!< codec mode CVSD or mSBC */
     } bcs_rep;                                    /*!< AG callback param of ESP_HF_BCS_RESPONSE_EVT */
 
+    /**
+     * @brief ESP_HF_PKT_STAT_NUMS_GET_EVT
+     */
+    struct ag_pkt_status_nums {
+        uint32_t rx_total;        /*!< the total number of packets received */
+        uint32_t rx_correct;      /*!< the total number of packets data correctly received */
+        uint32_t rx_err;          /*!< the total number of packets data with possible invalid */
+        uint32_t rx_none;         /*!< the total number of packets data no received */
+        uint32_t rx_lost;         /*!< the total number of packets data partially lost */
+        uint32_t tx_total;        /*!< the total number of packets send */
+        uint32_t tx_discarded;    /*!< the total number of packets send lost */
+    } pkt_nums;                   /*!< AG callback param of ESP_HF_PKT_STAT_NUMS_GET_EVT */
+
 } esp_hf_cb_param_t;                              /*!< HFP AG callback param compound*/
 
 /**
@@ -637,6 +652,22 @@ esp_err_t esp_hf_ag_end_call(esp_bd_addr_t remote_addr, int num_active, int num_
  */
 esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send);
 
+/**
+ *
+ * @brief           Get the number of packets received and sent
+ *
+ *                  This function is only used in the case that Voice Over HCI is enabled and the audio state is connected.
+ *                  When the operation is completed, the callback function will be called with ESP_HF_PKT_STAT_NUMS_GET_EVT.
+ *
+ * @param[in]       sync_conn_handle: the (e)SCO connection handle
+ *
+ * @return
+ *                  - ESP_OK: if the request is sent successfully
+ *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
+ *                  - ESP_FAIL: others
+ *
+ */
+esp_err_t esp_hf_ag_pkt_stat_nums_get(uint16_t sync_conn_handle);
 
 /**
  * @brief           Trigger the lower-layer to fetch and send audio data.

+ 32 - 1
components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -96,6 +96,7 @@ typedef enum {
     ESP_HF_CLIENT_BSIR_EVT,                          /*!< setting of in-band ring tone */
     ESP_HF_CLIENT_BINP_EVT,                          /*!< requested number of last voice tag from AG */
     ESP_HF_CLIENT_RING_IND_EVT,                      /*!< ring indication event */
+    ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT,             /*!< requested number of packet different status */
 } esp_hf_client_cb_event_t;
 
 /// HFP client callback parameters
@@ -116,6 +117,7 @@ typedef union {
     struct hf_client_audio_stat_param {
         esp_hf_client_audio_state_t state;       /*!< audio connection state */
         esp_bd_addr_t remote_bda;                /*!< remote bluetooth device address */
+        uint16_t  sync_conn_handle;              /*!< (e)SCO connection handle */
     } audio_stat;                                /*!< HF callback param of ESP_HF_CLIENT_AUDIO_STATE_EVT */
 
     /**
@@ -251,6 +253,19 @@ typedef union {
         const char *number;                      /*!< phone number corresponding to the last voice tag in the HF */
     } binp;                                      /*!< HF callback param of ESP_HF_CLIENT_BINP_EVT */
 
+    /**
+     * @brief ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT
+     */
+    struct hf_client_pkt_status_nums {
+        uint32_t rx_total;        /*!< the total number of packets received */
+        uint32_t rx_correct;      /*!< the total number of packets data correctly received */
+        uint32_t rx_err;          /*!< the total number of packets data with possible invalid */
+        uint32_t rx_none;         /*!< the total number of packets data no received */
+        uint32_t rx_lost;         /*!< the total number of packets data partially lost */
+        uint32_t tx_total;        /*!< the total number of packets send */
+        uint32_t tx_discarded;    /*!< the total number of packets send lost */
+    } pkt_nums;                   /*!< HF callback param of ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT */
+
 } esp_hf_client_cb_param_t;                      /*!< HFP client callback parameters */
 
 /**
@@ -655,6 +670,22 @@ esp_err_t esp_hf_client_send_nrec(void);
 esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv,
                                                esp_hf_client_outgoing_data_cb_t send);
 
+/**
+ *
+ * @brief           Get the number of packets received and sent
+ *                  This function is only used in the case that Voice Over HCI is enabled and the audio state is connected.
+ *                  When the operation is completed, the callback function will be called with ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT.
+ *
+ * @param[in]       sync_conn_handle: the (e)SCO connection handle
+ *
+ * @return
+ *                  - ESP_OK: if the request is sent successfully
+ *                  - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
+ *                  - ESP_FAIL: others
+ *
+ */
+esp_err_t esp_hf_client_pkt_stat_nums_get(uint16_t sync_conn_handle);
+
 /**
  * @brief           Trigger the lower-layer to fetch and send audio data.
  *                  This function is only only used in the case that Voice Over HCI is enabled. After this

+ 25 - 3
components/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c

@@ -245,7 +245,6 @@ void BTA_AgAudioClose(UINT16 handle)
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         BTA_AgResult
@@ -297,7 +296,30 @@ void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec)
     }
 }
 
-#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_AgPktStatsNumsGet
+**
+** Description      Specify the sync_conn_handle to be used for the packet numbers
+**                  received or send.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgPktStatsNumsGet(UINT16 handle, UINT16 sync_conn_handle)
+{
+    tBTA_AG_PKT_STAT_GET  *p_buf;
+
+    if ((p_buf = (tBTA_AG_PKT_STAT_GET *) osi_malloc(sizeof(tBTA_AG_PKT_STAT_GET))) != NULL) {
+        p_buf->hdr.event = BTA_AG_PKT_STAT_NUMS_GET_EVT;
+        p_buf->hdr.layer_specific = handle;
+        p_buf->sync_conn_handle = sync_conn_handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
 /************************************************************************************************
  * Function        BTA_AgCiData
  *
@@ -317,6 +339,6 @@ void BTA_AgCiData(UINT16 handle)
         bta_sys_sendmsg(p_buf);
     }
 }
-#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
+#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */
 
 #endif /* #if (BTA_AG_INCLUDED == TRUE)*/

+ 13 - 5
components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c

@@ -91,6 +91,7 @@ enum
     BTA_AG_CI_SCO_DATA,
     BTA_AG_CI_RX_DATA,
     BTA_AG_RCVD_SLC_READY,
+    BTA_AG_PKT_STAT_NUMS,
     BTA_AG_NUM_ACTIONS
 };
 
@@ -133,7 +134,8 @@ const tBTA_AG_ACTION bta_ag_action[] =
     bta_ag_send_ring,
     bta_ag_ci_sco_data,
     bta_ag_ci_rx_data,
-    bta_ag_rcvd_slc_ready
+    bta_ag_rcvd_slc_ready,
+    bta_ag_pkt_stat_nums
 };
 
 /* state table information */
@@ -167,7 +169,8 @@ const UINT8 bta_ag_st_init[][BTA_AG_NUM_COLS] =
 /* RING_TOUT_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
 /* SVC_TOUT_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
 /* CI_SCO_DATA_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
-/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST}
+/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* PKT_STAT_NUMS_GET_EVT */ {BTA_AG_PKT_STAT_NUMS,  BTA_AG_IGNORE,          BTA_AG_INIT_ST}
 };
 
 /* state table for opening state */
@@ -196,7 +199,8 @@ const UINT8 bta_ag_st_opening[][BTA_AG_NUM_COLS] =
 /* RING_TOUT_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
 /* SVC_TOUT_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
 /* CI_SCO_DATA_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
-/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST}
+/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* PKT_STAT_NUMS_GET_EVT */ {BTA_AG_PKT_STAT_NUMS,  BTA_AG_IGNORE,          BTA_AG_OPENING_ST}
 };
 
 /* state table for open state */
@@ -225,7 +229,8 @@ const UINT8 bta_ag_st_open[][BTA_AG_NUM_COLS] =
 /* RING_TOUT_EVT */         {BTA_AG_SEND_RING,      BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
 /* SVC_TOUT_EVT */          {BTA_AG_START_CLOSE,    BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
 /* CI_SCO_DATA_EVT */       {BTA_AG_CI_SCO_DATA,    BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
-/* CI_SLC_READY_EVT */      {BTA_AG_RCVD_SLC_READY, BTA_AG_IGNORE,          BTA_AG_OPEN_ST}
+/* CI_SLC_READY_EVT */      {BTA_AG_RCVD_SLC_READY, BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* PKT_STAT_NUMS_GET_EVT */ {BTA_AG_PKT_STAT_NUMS,  BTA_AG_IGNORE,          BTA_AG_OPEN_ST}
 };
 
 /* state table for closing state */
@@ -254,7 +259,8 @@ const UINT8 bta_ag_st_closing[][BTA_AG_NUM_COLS] =
 /* RING_TOUT_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
 /* SVC_TOUT_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
 /* CI_SCO_DATA_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
-/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST}
+/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* PKT_STAT_NUMS_GET_EVT */ {BTA_AG_PKT_STAT_NUMS,  BTA_AG_IGNORE,          BTA_AG_CLOSING_ST}
 };
 
 /* type for state table */
@@ -357,6 +363,8 @@ static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result)
         return "SCO data Callin";
     case BTA_AG_CI_SLC_READY_EVT:
         return "SLC Ready Callin";
+    case BTA_AG_PKT_STAT_NUMS_GET_EVT:
+        return "Get Packet Nums";
     default:
         return "Unknown AG Event";
     }

+ 27 - 0
components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c

@@ -475,6 +475,7 @@ static void bta_ag_cback_sco(tBTA_AG_SCB *p_scb, UINT8 event)
 
     sco.handle = bta_ag_scb_to_idx(p_scb);
     sco.app_id = p_scb->app_id;
+    sco.sync_conn_handle = BTM_ReadScoHandle(p_scb->sco_idx);
 
     /* call close cback */
     (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &sco);
@@ -1477,6 +1478,32 @@ void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result)
 }
 #endif
 
+/*******************************************************************************
+**
+** Function         bta_ag_pkt_stat_nums
+**
+** Description      Get the number of packet states
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_pkt_stat_nums(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UNUSED(p_scb);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+    tBTA_AG_PKT_STAT_NUMS pkt_stat_nums;
+    uint16_t sync_conn_handle = p_data->pkt_stat.sync_conn_handle;
+    BTM_PktStatNumsGet(sync_conn_handle, (tBTM_SCO_PKT_STAT_NUMS *) &pkt_stat_nums);
+
+    /* call app cback */
+    if (bta_ag_cb.p_cback) {
+        (*bta_ag_cb.p_cback)(BTA_AG_PKT_NUMS_GET_EVT, (tBTA_AG*) &pkt_stat_nums);
+    }
+#endif
+}
+
 /*******************************************************************************
 **
 ** Function         bta_ag_sco_shutdown

+ 11 - 1
components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h

@@ -114,6 +114,7 @@ enum
     BTA_AG_SVC_TOUT_EVT,
     BTA_AG_CI_SCO_DATA_EVT,
     BTA_AG_CI_SLC_READY_EVT,
+    BTA_AG_PKT_STAT_NUMS_GET_EVT,
     BTA_AG_MAX_EVT,
 
     /* these events are handled outside of the state machine */
@@ -219,6 +220,13 @@ typedef struct
     char            p_data[BTA_AG_MTU+1];
 } tBTA_AG_CI_RX_WRITE;
 
+/* data type for BTA_AG_PKT_STAT_NUMS_GET_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT16          sync_conn_handle;
+} tBTA_AG_PKT_STAT_GET;
+
 /* union of all event datatypes */
 typedef union
 {
@@ -233,6 +241,7 @@ typedef union
     tBTA_AG_DISC_RESULT     disc_result;
     tBTA_AG_RFC             rfc;
     tBTA_AG_CI_RX_WRITE     ci_rx_write;
+    tBTA_AG_PKT_STAT_GET    pkt_stat;
 } tBTA_AG_DATA;
 
 /* type for each profile */
@@ -277,7 +286,7 @@ typedef struct
     tBTA_AG_SCO_MSBC_SETTINGS codec_msbc_settings; /* settings to be used for the impending eSCO */
     TIMER_LIST_ENT      cn_timer;       /* codec negotiation timer */
 #endif
-    UINT16              sco_idx;        /* SCO handle */
+    UINT16              sco_idx;        /* SCO connection index */
     BOOLEAN             in_use;         /* scb in use */
     BOOLEAN             dealloc;        /* TRUE if service shutting down */
     BOOLEAN             clip_enabled;   /* set to TRUE if HF enables CLIP reporting */
@@ -438,6 +447,7 @@ extern void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
 extern void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param);
 extern void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
 extern void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_pkt_stat_nums(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
 
 #endif /* #if (BTA_AG_INCLUDED == TRUE) */
 

+ 22 - 1
components/bt/host/bluedroid/bta/hf_client/bta_hf_client_api.c

@@ -299,7 +299,28 @@ void BTA_HfClientSendAT(UINT16 handle, tBTA_HF_CLIENT_AT_CMD_TYPE at, UINT32 val
         bta_sys_sendmsg(p_buf);
     }
 }
-#if (BTM_SCO_HCI_INCLUDED == TRUE )
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_HfClientPktStatsNumsGet
+**
+** Description      Get the packet ststus numbers received and send for a specific (e)SCO connection handle.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HfClientPktStatsNumsGet(UINT16 sync_conn_handle)
+{
+    tBTA_HF_CLIENT_PKT_STAT_GET *p_buf;
+    if ((p_buf = (tBTA_HF_CLIENT_PKT_STAT_GET *) osi_malloc(sizeof(tBTA_HF_CLIENT_PKT_STAT_GET))) != NULL) {
+        p_buf->hdr.event = BTA_HF_CLIENT_PKT_NUMS_GET_EVT;
+        p_buf->sync_conn_handle = sync_conn_handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
 void BTA_HfClientCiData(void)
 {
     BT_HDR *p_buf;

+ 9 - 2
components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c

@@ -75,6 +75,7 @@ enum {
     BTA_HF_CLIENT_SEND_AT_CMD,
 #if (BTM_SCO_HCI_INCLUDED == TRUE)
     BTA_HF_CLIENT_CI_SCO_DATA,
+    BTA_HF_CLIENT_PKT_STAT_NUMS,
 #endif
     BTA_HF_CLIENT_NUM_ACTIONS,
 };
@@ -111,8 +112,9 @@ const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = {
     /* BTA_HF_CLIENT_DISC_ACP_RES */  bta_hf_client_disc_acp_res,
     /* BTA_HF_CLIENT_SVC_CONN_OPEN */ bta_hf_client_svc_conn_open,
     /* BTA_HF_CLIENT_SEND_AT_CMD */   bta_hf_client_send_at_cmd,
-#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
     /* BTA_HF_CLIENT_CI_SCO_DATA */   bta_hf_client_ci_sco_data,
+    /* BTA_HF_CLIENT_PKT_STAT_NUMS */ bta_hf_client_pkt_stat_nums,
 #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
 };
 
@@ -143,6 +145,7 @@ const UINT8 bta_hf_client_st_init[][BTA_HF_CLIENT_NUM_COLS] = {
     /* SEND_AT_CMD_EVT */       {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
     /* CI_SCO_DATA_EVT */       {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
+    /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS,  BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_INIT_ST},
 #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
 };
 
@@ -166,8 +169,9 @@ const UINT8 bta_hf_client_st_opening[][BTA_HF_CLIENT_NUM_COLS] = {
     /* SCO_OPEN_EVT */          {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPENING_ST},
     /* SCO_CLOSE_EVT */         {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPENING_ST},
     /* SEND_AT_CMD_EVT */       {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPENING_ST},
-#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
     /* CI_SCO_DATA_EVT */       {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPENING_ST},
+    /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS,  BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPENING_ST},
 #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
 };
 
@@ -193,6 +197,7 @@ const UINT8 bta_hf_client_st_open[][BTA_HF_CLIENT_NUM_COLS] = {
     /* SEND_AT_CMD_EVT */       {BTA_HF_CLIENT_SEND_AT_CMD,    BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPEN_ST},
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
     /* CI_SCO_DATA_EVT */       {BTA_HF_CLIENT_CI_SCO_DATA,    BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPEN_ST},
+    /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS,  BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_OPEN_ST},
 #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
 };
 
@@ -218,6 +223,7 @@ const UINT8 bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = {
     /* SEND_AT_CMD_EVT */       {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
     /* CI_SCO_DATA_EVT */       {BTA_HF_CLIENT_IGNORE,         BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
+    /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS,  BTA_HF_CLIENT_IGNORE,          BTA_HF_CLIENT_CLOSING_ST},
 #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
 };
 
@@ -640,6 +646,7 @@ static char *bta_hf_client_evt_str(UINT16 event)
         CASE_RETURN_STR(BTA_HF_CLIENT_SCO_OPEN_EVT)
         CASE_RETURN_STR(BTA_HF_CLIENT_SCO_CLOSE_EVT)
         CASE_RETURN_STR(BTA_HF_CLIENT_SEND_AT_CMD_EVT)
+        CASE_RETURN_STR(BTA_HF_CLIENT_PKT_NUMS_GET_EVT)
     default:
         return "Unknown HF Client Event";
     }

+ 25 - 1
components/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c

@@ -155,6 +155,7 @@ void bta_hf_client_cback_sco(UINT8 event)
     tBTA_HF_CLIENT_HDR    evt;
 
     memset(&evt, 0, sizeof(evt));
+    evt.sync_conn_handle = BTM_ReadScoHandle(bta_hf_client_cb.scb.sco_idx);
 
     /* call app cback */
     (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT_HDR *) &evt);
@@ -237,7 +238,29 @@ static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
     BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
 }
 
-#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_hf_client_pkt_stat_nums
+**
+** Description      Get the packet status number
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hf_client_pkt_stat_nums(tBTA_HF_CLIENT_DATA *p_data)
+{
+    tBTA_SCO_PKT_STAT_NUMS pkt_stat_nums;
+    uint16_t sync_conn_handle = p_data->pkt_stat.sync_conn_handle;
+    BTM_PktStatNumsGet(sync_conn_handle, (tBTM_SCO_PKT_STAT_NUMS *) &pkt_stat_nums);
+
+    /* call app cback */
+    if (bta_hf_client_cb.p_cback) {
+        (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_PKT_STAT_NUMS_GET_EVT, (void*) &pkt_stat_nums);
+    }
+}
+
 /*******************************************************************************
 **
 ** Function         bta_hf_client_ci_sco_data
@@ -254,6 +277,7 @@ void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data)
     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CI_DATA_E);
 }
 #endif
+
 /*******************************************************************************
 **
 ** Function         bta_hf_client_sco_connreq_cback

+ 9 - 0
components/bt/host/bluedroid/bta/hf_client/include/bta_hf_client_int.h

@@ -65,6 +65,7 @@ enum {
     BTA_HF_CLIENT_SEND_AT_CMD_EVT,
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
     BTA_HF_CLIENT_CI_SCO_DATA_EVT,
+    BTA_HF_CLIENT_PKT_NUMS_GET_EVT,
 #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
     BTA_HF_CLIENT_MAX_EVT,
 
@@ -121,6 +122,12 @@ typedef struct {
     char            str[BTA_HF_CLIENT_MAX_LEN + 1];
 } tBTA_HF_CLIENT_DATA_VAL;
 
+/* data type for BTA_HF_CLIENT_PKT_NUMS_GET_EVT */
+typedef struct {
+    BT_HDR          hdr;
+    UINT16          sync_conn_handle;
+} tBTA_HF_CLIENT_PKT_STAT_GET;
+
 /* union of all event datatypes */
 typedef union {
     BT_HDR                         hdr;
@@ -130,6 +137,7 @@ typedef union {
     tBTA_HF_CLIENT_DISC_RESULT     disc_result;
     tBTA_HF_CLIENT_RFC             rfc;
     tBTA_HF_CLIENT_DATA_VAL        val;
+    tBTA_HF_CLIENT_PKT_STAT_GET    pkt_stat;
 
 } tBTA_HF_CLIENT_DATA;
 
@@ -302,6 +310,7 @@ extern void bta_hf_client_binp(char *number);
 extern void bta_hf_client_dial(tBTA_HF_CLIENT_DATA *p_data);
 extern void bta_hf_client_send_at_cmd(tBTA_HF_CLIENT_DATA *p_data);
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
+extern void bta_hf_client_pkt_stat_nums(tBTA_HF_CLIENT_DATA *p_data);
 extern void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data);
 #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
 #endif /* #if (BTA_HF_INCLUDED == TRUE) */

+ 27 - 0
components/bt/host/bluedroid/bta/include/bta/bta_ag_api.h

@@ -158,6 +158,8 @@ typedef UINT8 tBTA_AG_RES;
 #endif
 #define BTA_AG_AUDIO_MSBC_OPEN_EVT 32 /* Audio connection with mSBC codec open */
 
+#define BTA_AG_PKT_NUMS_GET_EVT 33 /* AG packet status nums */
+
 /* Values below are for HFP only */
 #define BTA_AG_AT_A_EVT         10 /* Answer a incoming call */
 #define BTA_AG_AT_D_EVT         11 /* Place a call using number or memory dial */
@@ -327,6 +329,7 @@ typedef struct
     UINT16              handle;
     UINT8               app_id;
     tBTA_AG_STATUS      status;
+    UINT16              sync_conn_handle;
 } tBTA_AG_HDR;
 
 /* data associated with BTA_AG_REGISTER_EVT */
@@ -405,6 +408,17 @@ typedef struct {
     char                       number[BTA_AG_NUMBER_LEN + 1];
 } tBTA_AG_CNUM;
 
+/* data associated with BTA_HF_CLIENT_PKT_STAT_NUMS_GET_EVT */
+typedef struct {
+    UINT32 rx_total;
+    UINT32 rx_correct;
+    UINT32 rx_err;
+    UINT32 rx_none;
+    UINT32 rx_lost;
+    UINT32 tx_total;
+    UINT32 tx_discarded;
+} tBTA_AG_PKT_STAT_NUMS;
+
 /* union of data associated with AG callback */
 typedef union
 {
@@ -421,6 +435,7 @@ typedef union
     tBTA_AG_AT_RESULT        result;
     tBTA_AG_CLCC             clcc;
     tBTA_AG_CNUM             cnum;
+    tBTA_AG_PKT_STAT_NUMS    pkt_num;
 } tBTA_AG;
 
 /* AG callback */
@@ -581,6 +596,18 @@ void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec);
 
 
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function         BTA_AgPktStatsNumsGet
+**
+** Description      Get the Number of packets status received
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgPktStatsNumsGet(UINT16 handle, UINT16 sync_conn_handle);
+
 /*******************************************************************************
 **
 ** Function         BTA_AgCiData

+ 26 - 0
components/bt/host/bluedroid/bta/include/bta/bta_hf_client_api.h

@@ -113,6 +113,7 @@ typedef UINT8 tBTA_HF_CLIENT_AT_RESULT_TYPE;
 #define BTA_HF_CLIENT_BINP_EVT              20 /* binp number event */
 #define BTA_HF_CLIENT_RING_INDICATION       21 /* HF Client ring indication */
 #define BTA_HF_CLIENT_DISABLE_EVT           30 /* HF Client disabled */
+#define BTA_HF_CLIENT_PKT_STAT_NUMS_GET_EVT 31 /* HF Client packet status nums */
 
 typedef UINT8 tBTA_HF_CLIENT_EVT;
 
@@ -163,6 +164,7 @@ typedef UINT8 tBTA_HF_CLIENT_AT_CMD_TYPE;
 /* data associated with most non-AT events */
 /* placeholder, if not needed should be removed*/
 typedef struct {
+    UINT16       sync_conn_handle;
 } tBTA_HF_CLIENT_HDR;
 
 /* data associated with BTA_HF_CLIENT_REGISTER_EVT */
@@ -232,6 +234,17 @@ typedef struct {
     UINT16                     value;
 } tBTA_HF_CLIENT_VAL;
 
+/* data associated with BTA_HF_CLIENT_PKT_STAT_NUMS_GET_EVT */
+typedef struct {
+    UINT32 rx_total;
+    UINT32 rx_correct;
+    UINT32 rx_err;
+    UINT32 rx_none;
+    UINT32 rx_lost;
+    UINT32 tx_total;
+    UINT32 tx_discarded;
+} tBTA_SCO_PKT_STAT_NUMS;
+
 /* union of data associated with AG callback */
 typedef union {
     tBTA_HF_CLIENT_HDR              hdr;
@@ -245,6 +258,7 @@ typedef union {
     tBTA_HF_CLIENT_AT_RESULT        result;
     tBTA_HF_CLIENT_CLCC             clcc;
     tBTA_HF_CLIENT_CNUM             cnum;
+    tBTA_SCO_PKT_STAT_NUMS          pkt_num;
 } tBTA_HF_CLIENT;
 
 typedef UINT32 tBTA_HF_CLIENT_FEAT;
@@ -380,6 +394,18 @@ void BTA_HfClientAudioClose(UINT16 handle);
 void BTA_HfClientSendAT(UINT16 handle, tBTA_HF_CLIENT_AT_CMD_TYPE at, UINT32 val1, UINT32 val2, const char *str);
 
 #if (BTM_SCO_HCI_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function         BTA_HfClientPktStatsNumsGet
+**
+** Description      Get the Number of packets status received and send
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HfClientPktStatsNumsGet(UINT16 sync_conn_handle);
+
 void BTA_HfClientCiData(void);
 #endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE ) */
 

+ 30 - 1
components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -410,6 +410,21 @@ bt_status_t btc_hf_disconnect_audio(bt_bdaddr_t *bd_addr)
     return BT_STATUS_FAIL;
 }
 
+static bt_status_t btc_hf_pkt_stat_nums_get(UINT16 sync_conn_handle)
+{
+    bt_status_t status = BT_STATUS_FAIL;
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+    int idx = btc_hf_latest_connected_idx();
+    CHECK_HF_SLC_CONNECTED(idx);
+
+    if (idx != BTC_HF_INVALID_IDX) {
+        BTA_AgPktStatsNumsGet(hf_local_param[idx].btc_hf_cb.handle, sync_conn_handle);
+        status = BT_STATUS_SUCCESS;
+    }
+#endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE) */
+    return status;
+}
+
 /************************************************************************************
 **  AT cmd Handle
 ************************************************************************************/
@@ -1175,8 +1190,13 @@ void btc_hf_call_handler(btc_msg_t *msg)
         case BTC_HF_REGISTER_DATA_CALLBACK_EVT:
         {
             btc_hf_reg_data_cb(arg->reg_data_cb.recv, arg->reg_data_cb.send);
+            break;
         }
+        case BTC_HF_REQUEST_PKT_STAT_EVT:
+        {
+            btc_hf_pkt_stat_nums_get(arg->pkt_sync_hd.sync_conn_handle);
             break;
+        }
 
         default:
             BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
@@ -1298,6 +1318,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
             do {
                 param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED;
                 memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
+                param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
                 btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param);
             } while(0);
             break;
@@ -1310,6 +1331,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
             do {
                 param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED_MSBC;
                 memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
+                param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
                 btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param);
             } while (0);
             break;
@@ -1321,6 +1343,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
             do {
                 param.audio_stat.state = ESP_HF_AUDIO_STATE_DISCONNECTED;
                 memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
+                param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
                 btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param);
             } while(0);
             break;
@@ -1540,6 +1563,12 @@ void btc_hf_cb_handler(btc_msg_t *msg)
             break;
         }
 #endif
+        case BTA_AG_PKT_NUMS_GET_EVT:
+        {
+            memcpy(&param.pkt_nums, &p_data->pkt_num, sizeof(struct ag_pkt_status_nums));
+            btc_hf_cb_to_app(ESP_HF_PKT_STAT_NUMS_GET_EVT, &param);
+            break;
+        }
         default:
             BTC_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
             break;

+ 33 - 20
components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -677,6 +677,24 @@ static bt_status_t btc_hf_client_send_nrec(void)
     return BT_STATUS_UNSUPPORTED;
 }
 
+/*******************************************************************************
+**
+** Function         btc_hf_client_pkt_stat_nums_get;
+**
+** Description      Request packet status numbers for a specific (e)SCO connection handle
+**
+** Returns          bt_status_t
+**
+*******************************************************************************/
+static bt_status_t btc_hf_client_pkt_stat_nums_get(UINT16 sync_conn_handle)
+{
+    CHECK_HF_CLIENT_SLC_CONNECTED();
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+    BTA_HfClientPktStatsNumsGet(sync_conn_handle);
+#endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE) */
+    return BT_STATUS_SUCCESS;
+}
+
 /*******************************************************************************
 **
 ** Function         bte_hf_client_evt
@@ -802,6 +820,8 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
     esp_hf_client_cb_param_t param;
     bdstr_t bdstr;
 
+    memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
+
     switch (event)
     {
         case BTA_HF_CLIENT_ENABLE_EVT:
@@ -832,7 +852,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             }
 
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.conn_stat.state = hf_client_local_param.btc_hf_client_cb.state;
                 param.conn_stat.peer_feat = 0;
                 param.conn_stat.chld_feat = 0;
@@ -858,7 +877,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             hf_client_local_param.btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED;
 
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.conn_stat.state = hf_client_local_param.btc_hf_client_cb.state;
                 param.conn_stat.peer_feat = hf_client_local_param.btc_hf_client_cb.peer_feat;
                 param.conn_stat.chld_feat = hf_client_local_param.btc_hf_client_cb.chld_feat;
@@ -873,7 +891,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             if (hf_client_local_param.btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_INBAND)
             {
                 do {
-                    memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                     param.bsir.state =  ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED;
                     btc_hf_client_cb_to_app(ESP_HF_CLIENT_BSIR_EVT, &param);
                 } while (0);
@@ -885,7 +902,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
         case BTA_HF_CLIENT_CLOSE_EVT:
             hf_client_local_param.btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED;
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.conn_stat.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED;
                 param.conn_stat.peer_feat = 0;
                 param.conn_stat.chld_feat = 0;
@@ -906,7 +922,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             break;
         case BTA_HF_CLIENT_MIC_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.volume_control.type = ESP_HF_VOLUME_CONTROL_TARGET_MIC;
                 param.volume_control.volume = p_data->val.value;
 
@@ -915,7 +930,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             break;
         case BTA_HF_CLIENT_SPK_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.volume_control.type = ESP_HF_VOLUME_CONTROL_TARGET_SPK;
                 param.volume_control.volume = p_data->val.value;
 
@@ -924,7 +938,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             break;
         case BTA_HF_CLIENT_VOICE_REC_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.bvra.value = p_data->val.value;
 
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_BVRA_EVT, &param);
@@ -932,35 +945,30 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             break;
         case BTA_HF_CLIENT_OPERATOR_NAME_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.cops.name = p_data->operator.name;
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT, &param);
             } while (0);
             break;
         case BTA_HF_CLIENT_CLIP_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.clip.number = p_data->number.number;
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CLIP_EVT, &param);
             } while (0);
             break;
         case BTA_HF_CLIENT_BINP_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.binp.number = p_data->number.number;
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_BINP_EVT, &param);
             } while (0);
             break;
         case BTA_HF_CLIENT_CCWA_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.ccwa.number = p_data->number.number;
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_CCWA_EVT, &param);
             } while (0);
             break;
         case BTA_HF_CLIENT_AT_RESULT_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.at_response.code = p_data->result.type;
                 param.at_response.cme = p_data->result.cme;
 
@@ -969,7 +977,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             break;
         case BTA_HF_CLIENT_CLCC_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.clcc.idx = p_data->clcc.idx;
                 param.clcc.dir = p_data->clcc.inc ? ESP_HF_CURRENT_CALL_DIRECTION_INCOMING :
                     ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING;
@@ -982,7 +989,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             break;
         case BTA_HF_CLIENT_CNUM_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.cnum.number = p_data->cnum.number;
                 if (p_data->cnum.service == 4) {
                     param.cnum.type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE;
@@ -998,7 +1004,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
         case BTA_HF_CLIENT_BTRH_EVT:
             if (p_data->val.value <= ESP_HF_BTRH_STATUS_REJECTED) {
                 do {
-                    memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                     param.btrh.status = p_data->val.value;
 
                     btc_hf_client_cb_to_app(ESP_HF_CLIENT_BTRH_EVT, &param);
@@ -1006,7 +1011,6 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             }
             break;
         case BTA_HF_CLIENT_BSIR_EVT:
-            memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
             if (p_data->val.value != 0)
             {
                 param.bsir.state = ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED;
@@ -1019,28 +1023,28 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
             break;
         case BTA_HF_CLIENT_AUDIO_OPEN_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED;
                 memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
                        sizeof(esp_bd_addr_t));
+                param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
             } while (0);
             break;
         case BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC;
                 memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
                        sizeof(esp_bd_addr_t));
+                param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
             } while (0);
             break;
         case BTA_HF_CLIENT_AUDIO_CLOSE_EVT:
             do {
-                memset(&param, 0, sizeof(esp_hf_client_cb_param_t));
                 param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
                 memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
                        sizeof(esp_bd_addr_t));
+                param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
             } while (0);
             break;
@@ -1049,6 +1053,12 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
                 btc_hf_client_cb_to_app(ESP_HF_CLIENT_RING_IND_EVT, NULL);
             } while (0);
             break;
+        case BTA_HF_CLIENT_PKT_STAT_NUMS_GET_EVT:
+        {
+            memcpy(&param.pkt_nums, &p_data->pkt_num, sizeof(struct hf_client_pkt_status_nums));
+            btc_hf_client_cb_to_app(ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT, &param);
+            break;
+        }
         default:
             BTC_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
             break;
@@ -1132,6 +1142,9 @@ void btc_hf_client_call_handler(btc_msg_t *msg)
     case BTC_HF_CLIENT_SEND_IPHONEACCEV_EVT:
         btc_hf_client_send_iphoneaccev(arg->send_iphoneaccev.bat_level, arg->send_iphoneaccev.docked);
         break;
+    case BTC_HF_CLIENT_REQUEST_PKT_STAT_EVT:
+        btc_hf_client_pkt_stat_nums_get(arg->pkt_sync_hd.sync_conn_handle);
+        break;
     default:
         BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
     }

+ 8 - 2
components/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -55,7 +55,8 @@ typedef enum
     BTC_HF_OUT_CALL_EVT,
     BTC_HF_END_CALL_EVT,
     //REG
-    BTC_HF_REGISTER_DATA_CALLBACK_EVT
+    BTC_HF_REGISTER_DATA_CALLBACK_EVT,
+    BTC_HF_REQUEST_PKT_STAT_EVT
 } btc_hf_act_t;
 
 /* btc_hf_args_t */
@@ -180,6 +181,11 @@ typedef union
         esp_hf_outgoing_data_cb_t send;
     } reg_data_cb;
 
+    // BTC_HF_REQUEST_PKT_STAT_EVT
+    struct req_pkt_stat_sync_handle {
+        UINT16            sync_conn_handle;
+    } pkt_sync_hd;
+
 } btc_hf_args_t;
 
 /************************************************************************************

+ 8 - 1
components/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -52,6 +52,7 @@ typedef enum {
     BTC_HF_CLIENT_SEND_NREC_EVT,
     BTC_HF_CLIENT_SEND_XAPL_EVT,
     BTC_HF_CLIENT_SEND_IPHONEACCEV_EVT,
+    BTC_HF_CLIENT_REQUEST_PKT_STAT_EVT,
 } btc_hf_client_act_t;
 
 /* btc_hf_client_args_t */
@@ -117,6 +118,12 @@ typedef union {
         uint32_t bat_level;
         bool docked;
     } send_iphoneaccev;
+
+    // BTC_HF_CLIENT_REQUEST_PKT_STAT_EVT
+    struct req_pkt_stat_sync_handle {
+        UINT16            sync_conn_handle;
+    } pkt_sync_hd;
+
 } btc_hf_client_args_t;
 
 /************************************************************************************

+ 79 - 0
components/bt/host/bluedroid/stack/btm/btm_sco.c

@@ -341,6 +341,82 @@ void btm_sco_process_num_completed_pkts (UINT8 *p)
 
     return;
 }
+
+/*******************************************************************************
+**
+** Function         btm_pkt_stat_nums_update
+**
+** Description      Update the number of received SCO data packet status.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_pkt_stat_nums_update(uint16_t sco_inx, uint8_t pkt_status)
+{
+    tSCO_CONN   *p_ccb = &btm_cb.sco_cb.sco_db[sco_inx];
+    p_ccb->pkt_stat_nums.rx_total++;
+    if (pkt_status == BTM_SCO_DATA_CORRECT) {
+        p_ccb->pkt_stat_nums.rx_correct++;
+    } else if (pkt_status == BTM_SCO_DATA_PAR_ERR) {
+        p_ccb->pkt_stat_nums.rx_err++;
+    } else if (pkt_status == BTM_SCO_DATA_NONE) {
+        p_ccb->pkt_stat_nums.rx_none++;
+    } else {
+        p_ccb->pkt_stat_nums.rx_lost++;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_pkt_stat_send_nums_update
+**
+** Description      Update the number of send packet status.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_pkt_stat_send_nums_update(uint16_t sco_inx, uint8_t pkt_status)
+{
+    tSCO_CONN   *p_ccb = &btm_cb.sco_cb.sco_db[sco_inx];
+    p_ccb->pkt_stat_nums.tx_total++;
+    if (pkt_status != BTM_SUCCESS) {
+        p_ccb->pkt_stat_nums.tx_discarded++;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_pkt_stat_nums_reset
+**
+** Description      This function is called to reset the number of packet status struct
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_pkt_stat_nums_reset(uint16_t sco_inx)
+{
+    memset(&btm_cb.sco_cb.sco_db[sco_inx].pkt_stat_nums, 0, sizeof(tBTM_SCO_PKT_STAT_NUMS));
+}
+
+/*******************************************************************************
+**
+** Function         BTM_PktStatNumsGet
+**
+** Description      This function is called to get the number of packet status struct
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTM_PktStatNumsGet(uint16_t sync_conn_handle, tBTM_SCO_PKT_STAT_NUMS *p_pkt_nums)
+{
+    uint16_t sco_inx = btm_find_scb_by_handle(sync_conn_handle);
+    if (sco_inx < BTM_MAX_SCO_LINKS) {
+        memcpy(p_pkt_nums, &btm_cb.sco_cb.sco_db[sco_inx].pkt_stat_nums, sizeof(tBTM_SCO_PKT_STAT_NUMS));
+    } else {
+        memset(p_pkt_nums, 0, sizeof(tBTM_SCO_PKT_STAT_NUMS));
+    }
+}
+
 #endif /* BTM_SCO_HCI_INCLUDED == TRUE */
 
 /*******************************************************************************
@@ -374,6 +450,7 @@ void  btm_route_sco_data(BT_HDR *p_msg)
         {
             osi_free (p_msg);
         } else {
+            btm_pkt_stat_nums_update(sco_inx, pkt_status);
             (*btm_cb.sco_cb.p_data_cb)(sco_inx, p_msg, (tBTM_SCO_DATA_FLAG) pkt_status);
         }
     } else { /* no mapping handle SCO connection is active, free the buffer */
@@ -461,6 +538,7 @@ tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf)
         BTM_TRACE_WARNING ("stat %d", status);
         osi_free(p_buf);
     }
+    btm_pkt_stat_send_nums_update(sco_inx, status);
     return (status);
 
 #else
@@ -994,6 +1072,7 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle,
             }
 #if BTM_SCO_HCI_INCLUDED == TRUE
             p->sent_not_acked = 0;
+            btm_pkt_stat_nums_reset(xx);
 #endif
             p->state = SCO_ST_CONNECTED;
             p->hci_handle = hci_handle;

+ 1 - 0
components/bt/host/bluedroid/stack/btm/include/btm_int.h

@@ -436,6 +436,7 @@ typedef struct {
 #define BTM_SCO_XMIT_QUEUE_HIGH_WM  20
     fixed_queue_t   *xmit_data_q;       /* SCO data transmitting queue  */
     INT16           sent_not_acked;
+    tBTM_SCO_PKT_STAT_NUMS pkt_stat_nums;
 #endif
     tBTM_SCO_CB     *p_conn_cb;         /* Callback for when connected  */
     tBTM_SCO_CB     *p_disc_cb;         /* Callback for when disconnect */

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

@@ -1079,6 +1079,17 @@ enum {
 };
 typedef UINT8 tBTM_SCO_DATA_FLAG;
 
+/* Count the number of SCO Data Packet Status */
+typedef struct {
+    UINT32 rx_total;
+    UINT32 rx_correct;
+    UINT32 rx_err;
+    UINT32 rx_none;
+    UINT32 rx_lost;
+    UINT32 tx_total;
+    UINT32 tx_discarded;
+} tBTM_SCO_PKT_STAT_NUMS;
+
 /***************************
 **  SCO Callback Functions
 ****************************/
@@ -4221,6 +4232,17 @@ tBTM_STATUS BTM_SetAfhChannels (AFH_CHANNELS channels, tBTM_CMPL_CB *p_afh_chann
 *******************************************************************************/
 tBTM_STATUS BTM_BleSetChannels (BLE_CHANNELS channels, tBTM_CMPL_CB *p_ble_channels_cmpl_cback);
 
+/*******************************************************************************
+**
+** Function         BTM_PktStatNumsGet
+**
+** Description      This function is called to get the number of packet status struct
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTM_PktStatNumsGet(UINT16 sync_conn_handle, tBTM_SCO_PKT_STAT_NUMS *pkt_nums);
+
 #ifdef __cplusplus
 }
 #endif

+ 9 - 3
examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Unlicense OR CC0-1.0
  */
@@ -45,6 +45,7 @@ const char *c_hf_evt_str[] = {
     "DIAL_EVT",                          /*!< DIAL INCOMING EVT */
     "WBS_EVT",                           /*!< CURRENT CODEC EVT */
     "BCS_EVT",                           /*!< CODEC NEGO EVT */
+    "PKT_STAT_EVT",                      /*!< REQUEST PACKET STATUS EVT */
 };
 
 //esp_hf_connection_state_t
@@ -212,7 +213,7 @@ static void bt_app_send_data_timer_cb(void *arg)
 static void bt_app_send_data_task(void *arg)
 {
     uint64_t frame_data_num;
-    uint32_t item_size = 0;
+    size_t item_size = 0;
     uint8_t *buf = NULL;
     for (;;) {
         if (xSemaphoreTake(s_send_data_Semaphore, (TickType_t)portMAX_DELAY)) {
@@ -292,7 +293,7 @@ void bt_app_send_data_shut_down(void)
 
 void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
 {
-    if (event <= ESP_HF_BCS_RESPONSE_EVT) {
+    if (event <= ESP_HF_PKT_STAT_NUMS_GET_EVT) {
         ESP_LOGI(BT_HF_TAG, "APP HFP event: %s", c_hf_evt_str[event]);
     } else {
         ESP_LOGE(BT_HF_TAG, "APP HFP invalid event %d", event);
@@ -477,6 +478,11 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
             ESP_LOGI(BT_HF_TAG, "--Consequence of codec negotiation: %s",c_codec_mode_str[param->bcs_rep.mode]);
             break;
         }
+        case ESP_HF_PKT_STAT_NUMS_GET_EVT:
+        {
+            ESP_LOGI(BT_HF_TAG, "ESP_HF_PKT_STAT_NUMS_GET_EVT: %d.", event);
+            break;
+        }
 
         default:
             ESP_LOGI(BT_HF_TAG, "Unsupported HF_AG EVT: %d.", event);

+ 8 - 3
examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Unlicense OR CC0-1.0
  */
@@ -48,6 +48,7 @@ const char *c_hf_evt_str[] = {
     "INBAND_RING_TONE_EVT",              /*!< in-band ring tone settings */
     "LAST_VOICE_TAG_NUMBER_EVT",         /*!< requested number from AG event */
     "RING_IND_EVT",                      /*!< ring indication event */
+    "PKT_STAT_EVT",                      /*!< requested number of packet status event */
 };
 
 // esp_hf_client_connection_state_t
@@ -228,7 +229,7 @@ static void bt_app_hf_client_incoming_cb(const uint8_t *buf, uint32_t sz)
 /* callback for HF_CLIENT */
 void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param)
 {
-    if (event <= ESP_HF_CLIENT_RING_IND_EVT) {
+    if (event <= ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT) {
         ESP_LOGI(BT_HF_TAG, "APP HFP event: %s", c_hf_evt_str[event]);
     } else {
         ESP_LOGE(BT_HF_TAG, "APP HFP invalid event %d", event);
@@ -393,7 +394,11 @@ void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_
                     (param->binp.number == NULL) ? "NULL" : param->binp.number);
             break;
         }
-
+        case ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT:
+        {
+            ESP_LOGE(BT_HF_TAG, "ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT: %d", event);
+            break;
+        }
         default:
             ESP_LOGE(BT_HF_TAG, "HF_CLIENT EVT: %d", event);
             break;