refactor(bt/bluedroid): Refactor hfp audio data path

- Refactor audio APIs, optimize audio data path, reduce memory copy operations
- Support using external codec in application layer
This commit is contained in:
linruihao
2025-01-22 17:22:05 +08:00
parent 4fe1529fd4
commit eda7ea3f49
26 changed files with 1833 additions and 172 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -528,6 +528,8 @@ esp_err_t esp_hf_ag_out_call(esp_bd_addr_t remote_addr, int num_active, int num_
return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
#if (BTM_SCO_HCI_INCLUDED == TRUE)
esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
@@ -548,7 +550,73 @@ esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_h
return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
#if (BTM_SCO_HCI_INCLUDED == TRUE)
esp_err_t esp_hf_ag_register_audio_data_callback(esp_hf_ag_audio_data_cb_t callback)
{
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_REGISTER_AUDIO_DATA_CALLBACK_EVT;
btc_hf_args_t arg;
memset(&arg, 0, sizeof(btc_hf_args_t));
arg.reg_audio_data_cb.callback = callback;
/* 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;
}
esp_hf_audio_buff_t *esp_hf_ag_audio_buff_alloc(uint16_t size)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return NULL;
}
if (size == 0) {
return NULL;
}
uint8_t *p_buf = NULL, *p_data;
BTA_AgAudioBuffAlloc(size, &p_buf, &p_data);
if (p_buf == NULL) {
return NULL;
}
esp_hf_audio_buff_t *audio_buf = (esp_hf_audio_buff_t *)p_buf;
audio_buf->buff_size = size;
audio_buf->data_len = 0;
audio_buf->data = p_data;
return audio_buf;
}
void esp_hf_ag_audio_buff_free(esp_hf_audio_buff_t *audio_buf)
{
if (audio_buf == NULL) {
return;
}
BTA_AgAudioBuffFree((UINT8 *)audio_buf);
}
esp_err_t esp_hf_ag_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
if (audio_buf == NULL || audio_buf->data_len == 0) {
return ESP_ERR_INVALID_ARG;
}
if (btc_hf_ag_audio_data_send(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len)) {
return ESP_OK;
}
return ESP_FAIL;
}
esp_err_t esp_hf_ag_pkt_stat_nums_get(uint16_t sync_conn_handle)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -541,6 +541,71 @@ void esp_hf_client_outgoing_data_ready(void)
BTA_HfClientCiData();
}
esp_err_t esp_hf_client_register_audio_data_callback(esp_hf_client_audio_data_cb_t callback)
{
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_REGISTER_AUDIO_DATA_CALLBACK_EVT;
btc_hf_client_args_t arg;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
arg.reg_audio_data_cb.callback = callback;
/* 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;
}
esp_hf_audio_buff_t *esp_hf_client_audio_buff_alloc(uint16_t size)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return NULL;
}
if (size == 0) {
return NULL;
}
uint8_t *p_buf = NULL, *p_data;
BTA_HfClientAudioBuffAlloc(size, &p_buf, &p_data);
if (p_buf == NULL) {
return NULL;
}
esp_hf_audio_buff_t *audio_buf = (esp_hf_audio_buff_t *)p_buf;
audio_buf->buff_size = size;
audio_buf->data_len = 0;
audio_buf->data = p_data;
return audio_buf;
}
void esp_hf_client_audio_buff_free(esp_hf_audio_buff_t *audio_buf)
{
if (audio_buf == NULL) {
return;
}
BTA_HfClientAudioBuffFree((UINT8 *)audio_buf);
}
esp_err_t esp_hf_client_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
if (audio_buf == NULL || audio_buf->data_len == 0) {
return ESP_ERR_INVALID_ARG;
}
BTA_HfClientAudioDataSend(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len);
return ESP_OK;
}
void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels)
{
BTA_DmPcmInitSamples(src_sps, bits, channels);

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,7 @@
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_hf_defs.h"
#include "esp_hf_ag_legacy_api.h"
#ifdef __cplusplus
extern "C" {
@@ -93,7 +94,8 @@ 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 */
esp_hf_sync_conn_hdl_t sync_conn_handle; /*!< (e)SCO connection handle */
uint16_t preferred_frame_size; /*!< Valid only when Voice Over HCI is enabled, recommended frame size to send */
} audio_stat; /*!< AG callback param of ESP_HF_AUDIO_STATE_EVT */
/**
@@ -233,35 +235,6 @@ typedef union
} esp_hf_cb_param_t; /*!< HFP AG callback param compound*/
/**
* @brief AG incoming data callback function, the callback is useful in case of
* Voice Over HCI.
*
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
*
* @param[in] len : size(in bytes) in buf
*/
typedef void (* esp_hf_incoming_data_cb_t)(const uint8_t *buf, uint32_t len);
/**
* @brief AG outgoing data callback function, the callback is useful in case of
* Voice Over HCI. Once audio connection is set up and the application layer has
* prepared data to send, the lower layer will call this function to read data
* and then send. This callback is supposed to be implemented as non-blocking,
* and if data is not enough, return value 0 is supposed.
*
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
*
* @param[in] len : size(in bytes) in buf
*
* @return length of data successfully read
*/
typedef uint32_t (* esp_hf_outgoing_data_cb_t) (uint8_t *buf, uint32_t len);
/**
* @brief HF AG callback function type
*
@@ -271,6 +244,20 @@ typedef uint32_t (* esp_hf_outgoing_data_cb_t) (uint8_t *buf, uint32_t len);
*/
typedef void (* esp_hf_cb_t) (esp_hf_cb_event_t event, esp_hf_cb_param_t *param);
/**
* @brief HFP AG incoming audio data callback function, user should copy audio_buf struct
* to other place before return. This callback is used in case of Voice Over HCI.
*
* @param[in] sync_conn_hdl: (e)SCO connection handle
*
* @param[in] audio_buf: pointer to incoming data(payload of HCI synchronous data packet), user
* should free audio buffer by calling esp_hf_ag_audio_buff_free
*
* @param[in] is_bad_frame: whether this packet is marked as bad frame by baseband
*
*/
typedef void (* esp_hf_ag_audio_data_cb_t)(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf, bool is_bad_frame);
/************************************************************************************
** ESP HF API
************************************************************************************/
@@ -678,19 +665,58 @@ esp_err_t esp_hf_ag_end_call(esp_bd_addr_t remote_addr, int num_active, int num_
char *number, esp_hf_call_addr_type_t call_addr_type);
/**
* @brief Register AG data output function.
* The callback is only used in the case that Voice Over HCI is enabled.
* @brief Register HFP AG audio data output function; the callback is only used in
* the case that Voice Over HCI is enabled.
*
* @param[in] recv: HFP client incoming data callback function
* @param[in] send: HFP client outgoing data callback function
* @param[in] callback: HFP AG incoming audio data callback function
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: if callback is a NULL function pointer
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send);
esp_err_t esp_hf_ag_register_audio_data_callback(esp_hf_ag_audio_data_cb_t callback);
/**
* @brief Allocate a audio buffer to store and send audio data. This function is only
* used in the case that Voice Over HCI is enabled.
*
* @param[in] size: buffer size to allocate
*
* @return allocated audio buffer, if Bluedroid is not enabled, no memory, or size is
* zeros, will return NULL
*
*/
esp_hf_audio_buff_t *esp_hf_ag_audio_buff_alloc(uint16_t size);
/**
* @brief Free a audio buffer allocated by esp_hf_ag_audio_buff_alloc. This function
* is only used in the case that Voice Over HCI is enabled.
*
* @param[in] audio_buf: audio buffer to free
*
*/
void esp_hf_ag_audio_buff_free(esp_hf_audio_buff_t *audio_buf);
/**
* @brief Send audio data, the audio buffer should by allocated by esp_hf_ag_audio_buff_alloc.
* If the length of the audio data is equal to preferred_frame_size indicated by
* ESP_HF_AUDIO_STATE_EVT, then we can reduce one memory copy inside the Bluedroid stack.
* This function is only used in the case that Voice Over HCI is enabled.
*
* @param[in] sync_conn_hdl: (e)SCO connection handle
*
* @param[in] audio_buf: audio buffer that audio data stored
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_ERR_INVALID_ARG: invalid parameter
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_ag_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf);
/**
*
@@ -709,16 +735,6 @@ esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_h
*/
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.
*
* This function is only used in the case that Voice Over HCI is enabled.
* As a precondition to use this API, Service Level Connection shall exist with HFP client.
* After this function is called, lower layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data
*
*/
void esp_hf_ag_outgoing_data_ready(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,77 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Some legacy APIs of HFP AG, will be removed in the future
*/
#pragma once
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_hf_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief AG incoming data callback function, the callback is useful in case of
* Voice Over HCI.
*
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
*
* @param[in] len : size(in bytes) in buf
*/
typedef void (* esp_hf_incoming_data_cb_t)(const uint8_t *buf, uint32_t len);
/**
* @brief AG outgoing data callback function, the callback is useful in case of
* Voice Over HCI. Once audio connection is set up and the application layer has
* prepared data to send, the lower layer will call this function to read data
* and then send. This callback is supposed to be implemented as non-blocking,
* and if data is not enough, return value 0 is supposed.
*
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
*
* @param[in] len : size(in bytes) in buf
*
* @return length of data successfully read
*/
typedef uint32_t (* esp_hf_outgoing_data_cb_t) (uint8_t *buf, uint32_t len);
/**
* @brief Register AG data output function.
* The callback is only used in the case that Voice Over HCI is enabled.
*
* @param[in] recv: HFP client incoming data callback function
* @param[in] send: HFP client outgoing data callback function
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: if callback is a NULL function pointer
*
*/
esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send);
/**
* @brief Trigger the lower-layer to fetch and send audio data.
*
* This function is only used in the case that Voice Over HCI is enabled.
* As a precondition to use this API, Service Level Connection shall exist with HFP client.
* After this function is called, lower layer will invoke esp_hf_ag_outgoing_data_cb_t to fetch data
*
*/
void esp_hf_ag_outgoing_data_ready(void);
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,7 @@
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_hf_defs.h"
#include "esp_hf_client_legacy_api.h"
#ifdef __cplusplus
extern "C" {
@@ -118,7 +119,8 @@ 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 */
esp_hf_sync_conn_hdl_t sync_conn_handle; /*!< (e)SCO connection handle */
uint16_t preferred_frame_size; /*!< valid only when Voice Over HCI is enabled, recommended frame size to send */
} audio_stat; /*!< HF callback param of ESP_HF_CLIENT_AUDIO_STATE_EVT */
/**
@@ -277,32 +279,18 @@ typedef union {
} esp_hf_client_cb_param_t; /*!< HFP client callback parameters */
/**
* @brief HFP client incoming data callback function, the callback is useful in case of
* Voice Over HCI.
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
* @param[in] len : size(in bytes) in buf
*/
typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t len);
/**
* @brief HFP client outgoing data callback function, the callback is useful in case of
* Voice Over HCI. Once audio connection is set up and the application layer has
* prepared data to send, the lower layer will call this function to read data
* and then send. This callback is supposed to be implemented as non-blocking,
* and if data is not enough, return value 0 is supposed.
* @brief HFP client incoming audio data callback function, user should copy audio_buf struct
* to other place before return. This callback is used in case of Voice Over HCI.
*
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
* @param[in] sync_conn_hdl: (e)SCO connection handle
*
* @param[in] len : size(in bytes) in buf
* @param[in] audio_buf: pointer to incoming data(payload of HCI synchronous data packet), user
* should free audio buffer by calling esp_hf_client_audio_buff_free
*
* @return length of data successfully read
* @param[in] is_bad_frame: whether this packet is marked as bad frame by baseband
*
*/
typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len);
typedef void (* esp_hf_client_audio_data_cb_t)(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf, bool is_bad_frame);
/**
* @brief HFP client callback function type
@@ -662,24 +650,6 @@ esp_err_t esp_hf_client_request_last_voice_tag_number(void);
*/
esp_err_t esp_hf_client_send_nrec(void);
/**
* @brief Register HFP client data output function; the callback is only used in
* the case that Voice Over HCI is enabled.
*
* @param[in] recv: HFP client incoming data callback function
*
* @param[in] send: HFP client outgoing data callback function
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: if callback is a NULL function pointer
*
*/
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
@@ -697,15 +667,57 @@ esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t
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
* function is called, lower layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data.
* @brief Register HFP client audio data output function; the callback is only used in
* the case that Voice Over HCI is enabled.
*
* As a precondition to use this API, Service Level Connection shall exist with AG.
* @param[in] callback: HFP client incoming audio data callback function
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
void esp_hf_client_outgoing_data_ready(void);
esp_err_t esp_hf_client_register_audio_data_callback(esp_hf_client_audio_data_cb_t callback);
/**
* @brief Allocate a audio buffer to store and send audio data. This function is only
* used in the case that Voice Over HCI is enabled.
*
* @param[in] size: buffer size to allocate
*
* @return allocated audio buffer, if Bluedroid is not enabled, no memory, or size is
* zeros, will return NULL
*
*/
esp_hf_audio_buff_t *esp_hf_client_audio_buff_alloc(uint16_t size);
/**
* @brief Free a audio buffer allocated by esp_hf_client_audio_buff_alloc. This function
* is only used in the case that Voice Over HCI is enabled.
*
* @param[in] audio_buf: audio buffer to free
*
*/
void esp_hf_client_audio_buff_free(esp_hf_audio_buff_t *audio_buf);
/**
* @brief Send audio data, the audio buffer should by allocated by esp_hf_client_audio_buff_alloc.
* If the length of the audio data is equal to preferred_frame_size indicated by
* ESP_HF_CLIENT_AUDIO_STATE_EVT, then we can reduce one memory copy inside the Bluedroid stack.
* This function is only used in the case that Voice Over HCI is enabled.
*
* @param[in] sync_conn_hdl: (e)SCO connection handle
*
* @param[in] audio_buf: audio buffer that audio data stored
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_ERR_INVALID_ARG: invalid parameter
*
*/
esp_err_t esp_hf_client_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf);
/**
* @brief Initialize the down sampling converter. This is a utility function that can

View File

@@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Some legacy APIs of HFP HF, will be removed in the future
*/
#pragma once
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_hf_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief HFP client incoming data callback function, the callback is useful in case of
* Voice Over HCI.
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
* @param[in] len : size(in bytes) in buf
*/
typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t len);
/**
* @brief HFP client outgoing data callback function, the callback is useful in case of
* Voice Over HCI. Once audio connection is set up and the application layer has
* prepared data to send, the lower layer will call this function to read data
* and then send. This callback is supposed to be implemented as non-blocking,
* and if data is not enough, return value 0 is supposed.
*
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
*
* @param[in] len : size(in bytes) in buf
*
* @return length of data successfully read
*
*/
typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len);
/**
* @brief Register HFP client data output function; the callback is only used in
* the case that Voice Over HCI is enabled.
*
* @param[in] recv: HFP client incoming data callback function
*
* @param[in] send: HFP client outgoing data callback function
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: if callback is a NULL function pointer
*
*/
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 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
* function is called, lower layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data.
*
* As a precondition to use this API, Service Level Connection shall exist with AG.
*
*/
void esp_hf_client_outgoing_data_ready(void);
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,6 +13,8 @@
extern "C" {
#endif
typedef uint16_t esp_hf_sync_conn_hdl_t;
/// profile states
typedef enum {
ESP_HF_INIT_SUCCESS = 0, /*!< Indicate init successful */
@@ -249,6 +251,25 @@ typedef enum {
ESP_HF_CME_NETWORK_NOT_ALLOWED = 32, /*!< network not allowed --emergency calls only */
} esp_hf_cme_err_t;
/* Since HFP uses a fixed set of mSBC codec parameters, define it here */
#define ESP_HF_MSBC_CHANNEL_MODE "Mono" /*!< mSBC channel mode */
#define ESP_HF_MSBC_SAMPLING_RATE "16 kHz" /*!< mSBC sampling rate */
#define ESP_HF_MSBC_ALLOCATION_METHOD "Loudness" /*!< mSBC allocation method */
#define ESP_HF_MSBC_SUBBANDS 8 /*!< mSBC subbands */
#define ESP_HF_MSBC_BLOCK_LENGTH 15 /*!< mSBC block length */
#define ESP_HF_MSBC_BITPOOL 26 /*!< mSBC bitpool */
/* frame size after mSBC encoded */
#define ESP_HF_MSBC_ENCODED_FRAME_SIZE 57 /*!< mSBC frame size */
/**
* @brief HFP audio buffer
*/
typedef struct {
uint16_t buff_size; /*!< buffer size */
uint16_t data_len; /*!< audio data length, data length should not greater than buffer size */
uint8_t *data; /*!< pointer to audio data start */
} esp_hf_audio_buff_t; /*!< struct to store audio data */
#ifdef __cplusplus
}
#endif