forked from espressif/esp-idf
refactor(bt/bluedroid): Refactor a2dp audio data path
- Refactor audio APIs, optimize audio data path, reduce memory copy operations - Support using external codec in application layer - The internal codec will not be compiled if not use
This commit is contained in:
@@ -288,7 +288,9 @@ if(CONFIG_BT_ENABLED)
|
|||||||
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c"
|
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c"
|
||||||
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c"
|
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c"
|
||||||
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c"
|
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c"
|
||||||
|
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c"
|
||||||
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c"
|
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c"
|
||||||
|
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source_ext_codec.c"
|
||||||
"host/bluedroid/btc/profile/std/a2dp/btc_av.c"
|
"host/bluedroid/btc/profile/std/a2dp/btc_av.c"
|
||||||
"host/bluedroid/btc/profile/std/avrc/btc_avrc.c"
|
"host/bluedroid/btc/profile/std/avrc/btc_avrc.c"
|
||||||
"host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c"
|
"host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c"
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -14,6 +14,37 @@
|
|||||||
|
|
||||||
#if BTC_AV_INCLUDED
|
#if BTC_AV_INCLUDED
|
||||||
|
|
||||||
|
esp_a2d_audio_buff_t *esp_a2d_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;
|
||||||
|
btc_av_audio_buff_alloc(size, &p_buf, &p_data);
|
||||||
|
if (p_buf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_a2d_audio_buff_t *audio_buf = (esp_a2d_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_a2d_audio_buff_free(esp_a2d_audio_buff_t *audio_buf)
|
||||||
|
{
|
||||||
|
if (audio_buf == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btc_av_audio_buff_free((uint8_t *)audio_buf);
|
||||||
|
}
|
||||||
|
|
||||||
#if BTC_AV_SINK_INCLUDED
|
#if BTC_AV_SINK_INCLUDED
|
||||||
esp_err_t esp_a2d_sink_init(void)
|
esp_err_t esp_a2d_sink_init(void)
|
||||||
{
|
{
|
||||||
@@ -36,6 +67,35 @@ esp_err_t esp_a2d_sink_init(void)
|
|||||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_a2d_sink_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc)
|
||||||
|
{
|
||||||
|
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seid >= ESP_A2D_MAX_SEPS) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
btc_msg_t msg;
|
||||||
|
msg.sig = BTC_SIG_API_CALL;
|
||||||
|
msg.pid = BTC_PID_A2DP;
|
||||||
|
msg.act = BTC_AV_SINK_API_REG_SEP_EVT;
|
||||||
|
|
||||||
|
btc_av_args_t arg;
|
||||||
|
memset(&arg, 0, sizeof(btc_av_args_t));
|
||||||
|
arg.reg_sep.seid = seid;
|
||||||
|
memcpy(&arg.reg_sep.mcc, mcc, sizeof(esp_a2d_mcc_t));
|
||||||
|
|
||||||
|
/* Switch to BTC context */
|
||||||
|
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
|
||||||
|
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_a2d_sink_deinit(void)
|
esp_err_t esp_a2d_sink_deinit(void)
|
||||||
{
|
{
|
||||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||||
@@ -81,6 +141,30 @@ esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback)
|
|||||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_a2d_sink_register_audio_data_callback(esp_a2d_sink_audio_data_cb_t callback)
|
||||||
|
{
|
||||||
|
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_a2dp_sink_ongoing_deinit) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
btc_msg_t msg;
|
||||||
|
msg.sig = BTC_SIG_API_CALL;
|
||||||
|
msg.pid = BTC_PID_A2DP;
|
||||||
|
msg.act = BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT;
|
||||||
|
|
||||||
|
btc_av_args_t arg;
|
||||||
|
memset(&arg, 0, sizeof(btc_av_args_t));
|
||||||
|
arg.audio_data_cb = callback;
|
||||||
|
|
||||||
|
/* Switch to BTC context */
|
||||||
|
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
|
||||||
|
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda)
|
esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda)
|
||||||
{
|
{
|
||||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||||
@@ -251,6 +335,35 @@ esp_err_t esp_a2d_source_init(void)
|
|||||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc)
|
||||||
|
{
|
||||||
|
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seid >= ESP_A2D_MAX_SEPS) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
btc_msg_t msg;
|
||||||
|
msg.sig = BTC_SIG_API_CALL;
|
||||||
|
msg.pid = BTC_PID_A2DP;
|
||||||
|
msg.act = BTC_AV_SRC_API_REG_SEP_EVT;
|
||||||
|
|
||||||
|
btc_av_args_t arg;
|
||||||
|
memset(&arg, 0, sizeof(btc_av_args_t));
|
||||||
|
arg.reg_sep.seid = seid;
|
||||||
|
memcpy(&arg.reg_sep.mcc, mcc, sizeof(esp_a2d_mcc_t));
|
||||||
|
|
||||||
|
/* Switch to BTC context */
|
||||||
|
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
|
||||||
|
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_a2d_source_deinit(void)
|
esp_err_t esp_a2d_source_deinit(void)
|
||||||
{
|
{
|
||||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||||
@@ -348,6 +461,26 @@ esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callbac
|
|||||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_a2d_source_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf)
|
||||||
|
{
|
||||||
|
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED || !btc_av_is_started()) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audio_buf == NULL || audio_buf->data_len == 0 || conn_hdl == 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!btc_a2d_src_audio_mtu_check(audio_buf->data_len)) {
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btc_a2d_src_audio_data_send(conn_hdl, audio_buf) != BT_STATUS_SUCCESS) {
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* BTC_AV_SRC_INCLUDED */
|
#endif /* BTC_AV_SRC_INCLUDED */
|
||||||
|
|
||||||
#endif /* #if BTC_AV_INCLUDED */
|
#endif /* #if BTC_AV_INCLUDED */
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -9,11 +9,16 @@
|
|||||||
|
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_bt_defs.h"
|
#include "esp_bt_defs.h"
|
||||||
|
#include "esp_a2dp_legacy_api.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ESP_A2D_MAX_SEPS 1 /*!< Maximum number of Stream Endpoint that supported */
|
||||||
|
|
||||||
|
typedef uint16_t esp_a2d_conn_hdl_t; /*!< Connection handle, associate with specific device that connected */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Media codec types supported by A2DP.
|
* @brief Media codec types supported by A2DP.
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +35,102 @@ typedef uint8_t esp_a2d_mct_t;
|
|||||||
#define ESP_A2D_PSC_DELAY_RPT (1<<0) /*!< Delay Report */
|
#define ESP_A2D_PSC_DELAY_RPT (1<<0) /*!< Delay Report */
|
||||||
typedef uint16_t esp_a2d_psc_t;
|
typedef uint16_t esp_a2d_psc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP SBC sampling frequency bit mask in CIE
|
||||||
|
*/
|
||||||
|
#define ESP_A2D_SBC_CIE_SF_16K (0x8) /*!< SBC sampling frequency 16kHz */
|
||||||
|
#define ESP_A2D_SBC_CIE_SF_32K (0x4) /*!< SBC sampling frequency 32kHz */
|
||||||
|
#define ESP_A2D_SBC_CIE_SF_44K (0x2) /*!< SBC sampling frequency 44.1kHz */
|
||||||
|
#define ESP_A2D_SBC_CIE_SF_48K (0x1) /*!< SBC sampling frequency 48kHz */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP SBC channel mode bit mask in CIE
|
||||||
|
*/
|
||||||
|
#define ESP_A2D_SBC_CIE_CH_MODE_MONO (0x8) /*!< SBC channel mode Mono */
|
||||||
|
#define ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL (0x4) /*!< SBC channel mode Dual Channel */
|
||||||
|
#define ESP_A2D_SBC_CIE_CH_MODE_STEREO (0x2) /*!< SBC channel mode Stereo */
|
||||||
|
#define ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO (0x1) /*!< SBC channel mode Stereo */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP SBC block length bit mask in CIE
|
||||||
|
*/
|
||||||
|
#define ESP_A2D_SBC_CIE_BLOCK_LEN_4 (0x8) /*!< SBC block length 4 */
|
||||||
|
#define ESP_A2D_SBC_CIE_BLOCK_LEN_8 (0x4) /*!< SBC block length 8 */
|
||||||
|
#define ESP_A2D_SBC_CIE_BLOCK_LEN_12 (0x2) /*!< SBC block length 12 */
|
||||||
|
#define ESP_A2D_SBC_CIE_BLOCK_LEN_16 (0x1) /*!< SBC block length 16 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP SBC number of subbands bit mask in CIE
|
||||||
|
*/
|
||||||
|
#define ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 (0x2) /*!< SBC number of subbands 4 */
|
||||||
|
#define ESP_A2D_SBC_CIE_NUM_SUBBANDS_8 (0x1) /*!< SBC number of subbands 8 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP SBC allocation method bit mask in CIE
|
||||||
|
*/
|
||||||
|
#define ESP_A2D_SBC_CIE_ALLOC_MTHD_SRN (0x2) /*!< SBC allocation method SNR */
|
||||||
|
#define ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS (0x1) /*!< SBC allocation method Loudness */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP SBC media codec capabilities information struct
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ch_mode : 4; /*!< Channel mode */
|
||||||
|
uint8_t samp_freq : 4; /*!< Sampling frequency */
|
||||||
|
uint8_t alloc_mthd : 2; /*!< Allocation method */
|
||||||
|
uint8_t num_subbands : 2; /*!< Number of subbands */
|
||||||
|
uint8_t block_len : 4; /*!< Block length */
|
||||||
|
uint8_t min_bitpool; /*!< Minimum bitpool */
|
||||||
|
uint8_t max_bitpool; /*!< Maximum bitpool */
|
||||||
|
} __attribute__((packed)) esp_a2d_cie_sbc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP MPEG-1, 2 media codec capabilities information struct (Not supported yet)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ch_mode : 4; /*!< Channel mode */
|
||||||
|
uint8_t crc : 1; /*!< CRC protection */
|
||||||
|
uint8_t layer : 3; /*!< Layers of MPEG-1,2 Audio */
|
||||||
|
uint8_t samp_freq : 6; /*!< Sampling frequency */
|
||||||
|
uint8_t mpf : 1; /*!< Media payload format */
|
||||||
|
uint8_t rfu : 1; /*!< Reserved */
|
||||||
|
uint8_t bri1 : 7; /*!< Bit rate index part 1 */
|
||||||
|
uint8_t vbr : 1; /*!< Support of VBR */
|
||||||
|
uint8_t bri2; /*!< Bit rate index part 2 */
|
||||||
|
} __attribute__((packed)) esp_a2d_cie_m12_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP MPEG-2, 4 media codec capabilities information struct (Not supported yet)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t drc : 1; /*!< Support of MPEG-D DRC */
|
||||||
|
uint8_t obj_type : 7; /*!< Object type */
|
||||||
|
uint8_t samp_freq1 : 8; /*!< Sampling frequency part 1 */
|
||||||
|
uint8_t ch : 4; /*!< Channels */
|
||||||
|
uint8_t samp_freq2 : 4; /*!< Sampling frequency part 2 */
|
||||||
|
uint8_t br1 : 7; /*!< Bit rate part 1 */
|
||||||
|
uint8_t vbr : 1; /*!< Support of VBR */
|
||||||
|
uint8_t br2; /*!< Bit rate part 2 */
|
||||||
|
uint8_t br3; /*!< Bit rate part 3 */
|
||||||
|
} __attribute__((packed)) esp_a2d_cie_m24_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP ATRAC media codec capabilities information struct (Not supported yet)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t rfu1 : 2; /*!< Reserved */
|
||||||
|
uint8_t ch_mode : 3; /*!< Channel mode */
|
||||||
|
uint8_t version : 3; /*!< Version */
|
||||||
|
uint8_t bri1 : 3; /*!< Bit rate index part 1 */
|
||||||
|
uint8_t vbr : 1; /*!< Support of VBR */
|
||||||
|
uint8_t samp_freq : 2; /*!< Sampling frequency */
|
||||||
|
uint8_t rfu2 : 2; /*!< Reserved */
|
||||||
|
uint8_t bri2; /*!< Bit rate index part 2 */
|
||||||
|
uint8_t bri3; /*!< Bit rate index part 3 */
|
||||||
|
uint16_t max_sul; /*!< Maximum SUL */
|
||||||
|
uint8_t rfu3; /*!< Reserved */
|
||||||
|
} __attribute__((packed)) esp_a2d_cie_atrac_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A2DP media codec capabilities union
|
* @brief A2DP media codec capabilities union
|
||||||
*/
|
*/
|
||||||
@@ -40,10 +141,15 @@ typedef struct {
|
|||||||
#define ESP_A2D_CIE_LEN_M24 (6)
|
#define ESP_A2D_CIE_LEN_M24 (6)
|
||||||
#define ESP_A2D_CIE_LEN_ATRAC (7)
|
#define ESP_A2D_CIE_LEN_ATRAC (7)
|
||||||
union {
|
union {
|
||||||
uint8_t sbc[ESP_A2D_CIE_LEN_SBC]; /*!< SBC codec capabilities */
|
uint8_t sbc[ESP_A2D_CIE_LEN_SBC] __attribute__((deprecated)); /*!< SBC codec capabilities, deprecated, use sbc_info instead */
|
||||||
uint8_t m12[ESP_A2D_CIE_LEN_M12]; /*!< MPEG-1,2 audio codec capabilities */
|
uint8_t m12[ESP_A2D_CIE_LEN_M12] __attribute__((deprecated)); /*!< MPEG-1,2 audio codec capabilities, deprecated, use m12_info instead */
|
||||||
uint8_t m24[ESP_A2D_CIE_LEN_M24]; /*!< MPEG-2, 4 AAC audio codec capabilities */
|
uint8_t m24[ESP_A2D_CIE_LEN_M24] __attribute__((deprecated)); /*!< MPEG-2, 4 AAC audio codec capabilities, deprecated, use m24_info instead */
|
||||||
uint8_t atrac[ESP_A2D_CIE_LEN_ATRAC]; /*!< ATRAC family codec capabilities */
|
uint8_t atrac[ESP_A2D_CIE_LEN_ATRAC] __attribute__((deprecated)); /*!< ATRAC family codec capabilities, deprecated, use atrac_info instead */
|
||||||
|
|
||||||
|
esp_a2d_cie_sbc_t sbc_info; /*!< SBC codec capabilities */
|
||||||
|
esp_a2d_cie_m12_t m12_info; /*!< MPEG-1,2 audio codec capabilities */
|
||||||
|
esp_a2d_cie_m24_t m24_info; /*!< MPEG-2, 4 AAC audio codec capabilities */
|
||||||
|
esp_a2d_cie_atrac_t atrac_info; /*!< ATRAC family codec capabilities */
|
||||||
} cie; /*!< A2DP codec information element */
|
} cie; /*!< A2DP codec information element */
|
||||||
} __attribute__((packed)) esp_a2d_mcc_t;
|
} __attribute__((packed)) esp_a2d_mcc_t;
|
||||||
|
|
||||||
@@ -103,6 +209,16 @@ typedef enum {
|
|||||||
ESP_A2D_INIT_SUCCESS /*!< A2DP profile deinit successful event */
|
ESP_A2D_INIT_SUCCESS /*!< A2DP profile deinit successful event */
|
||||||
} esp_a2d_init_state_t;
|
} esp_a2d_init_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bluetooth A2DP SEP register states
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ESP_A2D_SEP_REG_SUCCESS = 0, /*!< A2DP stream endpoint register success */
|
||||||
|
ESP_A2D_SEP_REG_FAIL, /*!< A2DP stream endpoint register generic fail */
|
||||||
|
ESP_A2D_SEP_REG_UNSUPPORTED, /*!< A2DP stream endpoint register fail, unsupported codec type or param */
|
||||||
|
ESP_A2D_SEP_REG_INVALID_STATE, /*!< A2DP stream endpoint register fail, invalid state */
|
||||||
|
} esp_a2d_sep_reg_state_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Bluetooth A2DP set delay report value states
|
* @brief Bluetooth A2DP set delay report value states
|
||||||
*/
|
*/
|
||||||
@@ -117,15 +233,27 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
ESP_A2D_CONNECTION_STATE_EVT = 0, /*!< connection state changed event */
|
ESP_A2D_CONNECTION_STATE_EVT = 0, /*!< connection state changed event */
|
||||||
ESP_A2D_AUDIO_STATE_EVT, /*!< audio stream transmission state changed event */
|
ESP_A2D_AUDIO_STATE_EVT, /*!< audio stream transmission state changed event */
|
||||||
ESP_A2D_AUDIO_CFG_EVT, /*!< audio codec is configured, only used for A2DP SINK */
|
ESP_A2D_AUDIO_CFG_EVT, /*!< audio codec is configured */
|
||||||
ESP_A2D_MEDIA_CTRL_ACK_EVT, /*!< acknowledge event in response to media control commands */
|
ESP_A2D_MEDIA_CTRL_ACK_EVT, /*!< acknowledge event in response to media control commands */
|
||||||
ESP_A2D_PROF_STATE_EVT, /*!< indicate a2dp init&deinit complete */
|
ESP_A2D_PROF_STATE_EVT, /*!< indicate a2dp init&deinit complete */
|
||||||
|
ESP_A2D_SEP_REG_STATE_EVT, /*!< indicate a2dp steam endpoint register status */
|
||||||
ESP_A2D_SNK_PSC_CFG_EVT, /*!< protocol service capabilities configured,only used for A2DP SINK */
|
ESP_A2D_SNK_PSC_CFG_EVT, /*!< protocol service capabilities configured,only used for A2DP SINK */
|
||||||
ESP_A2D_SNK_SET_DELAY_VALUE_EVT, /*!< indicate a2dp sink set delay report value complete, only used for A2DP SINK */
|
ESP_A2D_SNK_SET_DELAY_VALUE_EVT, /*!< indicate a2dp sink set delay report value complete, only used for A2DP SINK */
|
||||||
ESP_A2D_SNK_GET_DELAY_VALUE_EVT, /*!< indicate a2dp sink get delay report value complete, only used for A2DP SINK */
|
ESP_A2D_SNK_GET_DELAY_VALUE_EVT, /*!< indicate a2dp sink get delay report value complete, only used for A2DP SINK */
|
||||||
ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT, /*!< report delay value, only used for A2DP SRC */
|
ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT, /*!< report delay value, only used for A2DP SRC */
|
||||||
} esp_a2d_cb_event_t;
|
} esp_a2d_cb_event_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A2DP audio buffer
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint16_t buff_size; /*!< audio buff size */
|
||||||
|
uint16_t number_frame; /*!< number of encoded frame in this buff */
|
||||||
|
uint32_t timestamp; /*!< timestamp of the first frame */
|
||||||
|
uint16_t data_len; /*!< audio data len */
|
||||||
|
uint8_t *data; /*!< pointer to audio data start */
|
||||||
|
} esp_a2d_audio_buff_t; /*!< struct to store audio data */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A2DP state callback parameters
|
* @brief A2DP state callback parameters
|
||||||
*/
|
*/
|
||||||
@@ -136,6 +264,8 @@ typedef union {
|
|||||||
struct a2d_conn_stat_param {
|
struct a2d_conn_stat_param {
|
||||||
esp_a2d_connection_state_t state; /*!< one of values from esp_a2d_connection_state_t */
|
esp_a2d_connection_state_t state; /*!< one of values from esp_a2d_connection_state_t */
|
||||||
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
|
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
|
||||||
|
esp_a2d_conn_hdl_t conn_hdl; /*!< connection handle */
|
||||||
|
uint16_t audio_mtu; /*!< MTU of audio connection */
|
||||||
esp_a2d_disc_rsn_t disc_rsn; /*!< reason of disconnection for "DISCONNECTED" */
|
esp_a2d_disc_rsn_t disc_rsn; /*!< reason of disconnection for "DISCONNECTED" */
|
||||||
} conn_stat; /*!< A2DP connection status */
|
} conn_stat; /*!< A2DP connection status */
|
||||||
|
|
||||||
@@ -144,7 +274,8 @@ typedef union {
|
|||||||
*/
|
*/
|
||||||
struct a2d_audio_stat_param {
|
struct a2d_audio_stat_param {
|
||||||
esp_a2d_audio_state_t state; /*!< one of the values from esp_a2d_audio_state_t */
|
esp_a2d_audio_state_t state; /*!< one of the values from esp_a2d_audio_state_t */
|
||||||
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
|
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address*/
|
||||||
|
esp_a2d_conn_hdl_t conn_hdl; /*!< connection handle */
|
||||||
} audio_stat; /*!< audio stream playing state */
|
} audio_stat; /*!< audio stream playing state */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,6 +283,7 @@ typedef union {
|
|||||||
*/
|
*/
|
||||||
struct a2d_audio_cfg_param {
|
struct a2d_audio_cfg_param {
|
||||||
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
|
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
|
||||||
|
esp_a2d_conn_hdl_t conn_hdl; /*!< connection handle */
|
||||||
esp_a2d_mcc_t mcc; /*!< A2DP media codec capability information */
|
esp_a2d_mcc_t mcc; /*!< A2DP media codec capability information */
|
||||||
} audio_cfg; /*!< media codec configuration information */
|
} audio_cfg; /*!< media codec configuration information */
|
||||||
|
|
||||||
@@ -170,6 +302,14 @@ typedef union {
|
|||||||
esp_a2d_init_state_t init_state; /*!< a2dp profile state param */
|
esp_a2d_init_state_t init_state; /*!< a2dp profile state param */
|
||||||
} a2d_prof_stat; /*!< status to indicate a2d prof init or deinit */
|
} a2d_prof_stat; /*!< status to indicate a2d prof init or deinit */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ESP_A2D_SEP_REG_STATE_EVT
|
||||||
|
*/
|
||||||
|
struct a2d_sep_reg_stat_param {
|
||||||
|
uint8_t seid; /*!< the stream endpoint to register */
|
||||||
|
esp_a2d_sep_reg_state_t reg_state; /*!< stream endpoint register state */
|
||||||
|
} a2d_sep_reg_stat; /*!< status to indicate a2d sep register success or not */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ESP_A2D_SNK_PSC_CFG_EVT
|
* @brief ESP_A2D_SNK_PSC_CFG_EVT
|
||||||
*/
|
*/
|
||||||
@@ -213,25 +353,31 @@ typedef void (* esp_a2d_cb_t)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *para
|
|||||||
/**
|
/**
|
||||||
* @brief A2DP sink data callback function
|
* @brief A2DP sink data callback function
|
||||||
*
|
*
|
||||||
* @param[in] buf : pointer to the data received from A2DP source device and is PCM format decoded from SBC decoder;
|
* @param[in] conn_hdl: connection handle
|
||||||
* buf references to a static memory block and can be overwritten by upcoming data
|
|
||||||
*
|
*
|
||||||
* @param[in] len : size(in bytes) in buf
|
* @param[in] audio_buf: pointer to the data received from A2DP source device, should be freed by
|
||||||
|
* calling esp_a2d_audio_buff_free
|
||||||
*/
|
*/
|
||||||
typedef void (* esp_a2d_sink_data_cb_t)(const uint8_t *buf, uint32_t len);
|
typedef void (* esp_a2d_sink_audio_data_cb_t)(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A2DP source data read callback function
|
* @brief Allocate a audio buffer to store and send audio data, can be used in both sink and source.
|
||||||
*
|
*
|
||||||
* @param[in] buf : buffer to be filled with PCM data stream from higher layer
|
* @param[in] size: buffer size to allocate
|
||||||
*
|
*
|
||||||
* @param[in] len : size(in bytes) of data block to be copied to buf. -1 is an indication to user
|
* @return allocated audio buffer, if Bluedroid is not enabled, no memory, or size is
|
||||||
* that data buffer shall be flushed
|
* zeros, will return NULL
|
||||||
*
|
|
||||||
* @return size of bytes read successfully, if the argument len is -1, this value is ignored.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len);
|
esp_a2d_audio_buff_t *esp_a2d_audio_buff_alloc(uint16_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a audio buffer allocated by esp_a2d_audio_buff_alloc.
|
||||||
|
*
|
||||||
|
* @param[in] audio_buf: audio buffer to free
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void esp_a2d_audio_buff_free(esp_a2d_audio_buff_t *audio_buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Register application callback function to A2DP module. This function should be called
|
* @brief Register application callback function to A2DP module. This function should be called
|
||||||
@@ -248,23 +394,20 @@ typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback);
|
esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Register A2DP sink data output function; For now the output is PCM data stream decoded
|
* @brief Register A2DP sink audio data output function, the output format is undecoded audio data
|
||||||
* from SBC format. This function should be called only after esp_bluedroid_enable()
|
* frame in esp_a2d_audio_buff_t, user shall call esp_a2d_audio_buff_free to free the buff
|
||||||
* completes successfully, used only by A2DP sink. The callback is invoked in the context
|
* when the data is consumed.
|
||||||
* of A2DP sink task whose stack size is configurable through menuconfig.
|
|
||||||
*
|
*
|
||||||
* @param[in] callback: A2DP sink data callback function
|
* @param[in] callback: A2DP sink audio data callback function
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK: success
|
* - ESP_OK: success
|
||||||
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
|
* - 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_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback);
|
esp_err_t esp_a2d_sink_register_audio_data_callback(esp_a2d_sink_audio_data_cb_t callback);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -282,6 +425,23 @@ esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_sink_init(void);
|
esp_err_t esp_a2d_sink_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a a2dp sink Stream Endpoint (SEP) with specific codec capability, shall register
|
||||||
|
* SEP after a2dp sink initializing and before a2dp connection establishing. Register the same
|
||||||
|
* SEP index repeatedly will overwrite the old one.
|
||||||
|
*
|
||||||
|
* @param[in] seid: local SEP identifier, start from 0, less than ESP_A2D_MAX_SEPS
|
||||||
|
*
|
||||||
|
* @param[in] mcc: codec capability, currently only supports SBC
|
||||||
|
*
|
||||||
|
* @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_a2d_sink_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -297,7 +457,6 @@ esp_err_t esp_a2d_sink_init(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_sink_deinit(void);
|
esp_err_t esp_a2d_sink_deinit(void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Connect to remote bluetooth A2DP source device. This API must be called after
|
* @brief Connect to remote bluetooth A2DP source device. This API must be called after
|
||||||
@@ -313,7 +472,6 @@ esp_err_t esp_a2d_sink_deinit(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda);
|
esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Disconnect from the remote A2DP source device. This API must be called after
|
* @brief Disconnect from the remote A2DP source device. This API must be called after
|
||||||
@@ -359,7 +517,6 @@ esp_err_t esp_a2d_sink_set_delay_value(uint16_t delay_value);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_sink_get_delay_value(void);
|
esp_err_t esp_a2d_sink_get_delay_value(void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Media control commands. This API can be used for both A2DP sink and source
|
* @brief Media control commands. This API can be used for both A2DP sink and source
|
||||||
@@ -375,7 +532,6 @@ esp_err_t esp_a2d_sink_get_delay_value(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl);
|
esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Initialize the bluetooth A2DP source module. A2DP can work independently.
|
* @brief Initialize the bluetooth A2DP source module. A2DP can work independently.
|
||||||
@@ -392,6 +548,23 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_source_init(void);
|
esp_err_t esp_a2d_source_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a a2dp source Stream Endpoint (SEP) with specific codec capability, shall register
|
||||||
|
* SEP after a2dp source initializing and before a2dp connection establishing. Register the same
|
||||||
|
* SEP index repeatedly will overwrite the old one.
|
||||||
|
*
|
||||||
|
* @param[in] seid: local SEP identifier, start from 0, less than ESP_A2D_MAX_SEPS
|
||||||
|
*
|
||||||
|
* @param[in] mcc: codec capability, currently, only SBC supported
|
||||||
|
*
|
||||||
|
* @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_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -407,23 +580,24 @@ esp_err_t esp_a2d_source_init(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_source_deinit(void);
|
esp_err_t esp_a2d_source_deinit(void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Register A2DP source data input function. For now, the input shoule be PCM data stream.
|
* @brief Send a audio buff with encoded audio data to sink, the audio data len shall not bigger than
|
||||||
* This function should be called only after esp_bluedroid_enable() completes
|
* audio connection mtu (retrieved from ESP_A2D_CONNECTION_STATE_EVT). if the return value is
|
||||||
* successfully. The callback is invoked in the context of A2DP source task whose
|
* ESP_OK, then the audio buff is consumed, otherwise, audio buff can be reused by user.
|
||||||
* stack size is configurable through menuconfig.
|
|
||||||
*
|
*
|
||||||
* @param[in] callback: A2DP source data callback function
|
* @param[in] conn_hdl: connection handle
|
||||||
|
*
|
||||||
|
* @param[in] audio_buf: encoded audio data
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK: success
|
* - ESP_OK: success
|
||||||
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
|
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
|
||||||
* - ESP_FAIL: if callback is a NULL function pointer
|
* - ESP_ERR_INVALID_ARG: invalid parameter
|
||||||
|
* - ESP_ERR_INVALID_SIZE: data len bigger than mtu
|
||||||
|
* - ESP_FAIL: buffer queue is full, try again later
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callback);
|
esp_err_t esp_a2d_source_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -440,7 +614,6 @@ esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callbac
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_a2d_source_connect(esp_bd_addr_t remote_bda);
|
esp_err_t esp_a2d_source_connect(esp_bd_addr_t remote_bda);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Disconnect from the remote A2DP sink device. This API must be called
|
* @brief Disconnect from the remote A2DP sink device. This API must be called
|
||||||
|
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some legacy APIs of A2DP, will be removed in the future
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_bt_defs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief [Deprecated] A2DP sink data callback function
|
||||||
|
*
|
||||||
|
* @param[in] buf : pointer to the data received from A2DP source device and is PCM format decoded from SBC decoder;
|
||||||
|
* buf references to a static memory block and can be overwritten by upcoming data
|
||||||
|
*
|
||||||
|
* @param[in] len : size(in bytes) in buf
|
||||||
|
*/
|
||||||
|
typedef void (* esp_a2d_sink_data_cb_t)(const uint8_t *buf, uint32_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief [Deprecated] A2DP source data read callback function
|
||||||
|
*
|
||||||
|
* @param[in] buf : buffer to be filled with PCM data stream from higher layer
|
||||||
|
*
|
||||||
|
* @param[in] len : size(in bytes) of data block to be copied to buf. -1 is an indication to user
|
||||||
|
* that data buffer shall be flushed
|
||||||
|
*
|
||||||
|
* @return size of bytes read successfully, if the argument len is -1, this value is ignored.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief [Deprecated] Register A2DP sink data output function; For now the output is PCM data stream decoded
|
||||||
|
* from SBC format. This function should be called only after esp_bluedroid_enable()
|
||||||
|
* completes successfully, used only by A2DP sink. The callback is invoked in the context
|
||||||
|
* of A2DP sink task whose stack size is configurable through menuconfig.
|
||||||
|
*
|
||||||
|
* @param[in] callback: A2DP sink 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_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief [Deprecated] Register A2DP source data input function. For now, the input should be PCM data stream.
|
||||||
|
* This function should be called only after esp_bluedroid_enable() completes
|
||||||
|
* successfully. The callback is invoked in the context of A2DP source task whose
|
||||||
|
* stack size is configurable through menuconfig.
|
||||||
|
*
|
||||||
|
* @param[in] callback: A2DP source 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_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callback);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -57,7 +57,7 @@
|
|||||||
#define BTA_AV_CLOSE_REQ_TIME_VAL 4000
|
#define BTA_AV_CLOSE_REQ_TIME_VAL 4000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* number to retry on reconfigure failure - some headsets requirs this number to be more than 1 */
|
/* number to retry on reconfigure failure - some headsets requires this number to be more than 1 */
|
||||||
#ifndef BTA_AV_RECONFIG_RETRY
|
#ifndef BTA_AV_RECONFIG_RETRY
|
||||||
#define BTA_AV_RECONFIG_RETRY 6
|
#define BTA_AV_RECONFIG_RETRY 6
|
||||||
#endif
|
#endif
|
||||||
@@ -239,7 +239,7 @@ static UINT8 bta_av_get_scb_handle(tBTA_AV_SCB *p_scb, UINT8 local_sep)
|
|||||||
return (p_scb->seps[xx].av_handle);
|
return (p_scb->seps[xx].av_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
APPL_TRACE_DEBUG(" bta_av_get_scb_handle appropiate sep_type not found")
|
APPL_TRACE_DEBUG(" bta_av_get_scb_handle appropriate sep_type not found")
|
||||||
return 0; /* return invalid handle */
|
return 0; /* return invalid handle */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ static UINT8 bta_av_get_scb_sep_type(tBTA_AV_SCB *p_scb, UINT8 tavdt_handle)
|
|||||||
return (p_scb->seps[xx].tsep);
|
return (p_scb->seps[xx].tsep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
APPL_TRACE_DEBUG(" bta_av_get_scb_sep_type appropiate handle not found")
|
APPL_TRACE_DEBUG(" bta_av_get_scb_sep_type appropriate handle not found")
|
||||||
return 3; /* return invalid sep type */
|
return 3; /* return invalid sep type */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,9 +586,18 @@ void bta_av_stream_data_cback(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UI
|
|||||||
osi_free(p_pkt);
|
osi_free(p_pkt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_pkt->offset >= 4) {
|
||||||
|
/* The offset of avdt packet will always greater than 4, it is safe to add timestamp here */
|
||||||
|
*((UINT32 *) (p_pkt + 1)) = time_stamp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
APPL_TRACE_WARNING("bta_av_stream_data_cback avdt packet offset small than 4");
|
||||||
|
}
|
||||||
|
|
||||||
p_pkt->event = BTA_AV_MEDIA_DATA_EVT;
|
p_pkt->event = BTA_AV_MEDIA_DATA_EVT;
|
||||||
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_DATA_EVT, (tBTA_AV_MEDIA *)p_pkt);
|
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_DATA_EVT, (tBTA_AV_MEDIA *)p_pkt);
|
||||||
osi_free(p_pkt); /* a copy of packet had been delivered, we free this buffer */
|
/* packet will be free by upper */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@@ -843,7 +852,7 @@ void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
bdcpy(av_open.bd_addr, p_scb->peer_addr);
|
bdcpy(av_open.bd_addr, p_scb->peer_addr);
|
||||||
av_open.chnl = p_scb->chnl;
|
av_open.chnl = p_scb->chnl;
|
||||||
av_open.hndl = p_scb->hndl;
|
av_open.hndl = p_scb->hndl;
|
||||||
start.status = BTA_AV_FAIL_ROLE;
|
av_open.status = BTA_AV_FAIL_ROLE;
|
||||||
if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC ) {
|
if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC ) {
|
||||||
av_open.sep = AVDT_TSEP_SNK;
|
av_open.sep = AVDT_TSEP_SNK;
|
||||||
} else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK ) {
|
} else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK ) {
|
||||||
@@ -1271,7 +1280,7 @@ void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
if (AVDT_TSEP_SNK == local_sep) {
|
if (AVDT_TSEP_SNK == local_sep) {
|
||||||
if ((p_data->ci_setconfig.err_code == AVDT_SUCCESS) &&
|
if ((p_data->ci_setconfig.err_code == AVDT_SUCCESS) &&
|
||||||
(p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL)) {
|
(p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL)) {
|
||||||
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_SINK_CFG_EVT,
|
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT,
|
||||||
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
|
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
|
||||||
}
|
}
|
||||||
if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) {
|
if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) {
|
||||||
@@ -1384,7 +1393,7 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
{
|
{
|
||||||
/* TODO check if other audio channel is open.
|
/* TODO check if other audio channel is open.
|
||||||
* If yes, check if reconfig is needed
|
* If yes, check if reconfig is needed
|
||||||
* Rigt now we do not do this kind of checking.
|
* Right now we do not do this kind of checking.
|
||||||
* BTA-AV is INT for 2nd audio connection.
|
* BTA-AV is INT for 2nd audio connection.
|
||||||
* The application needs to make sure the current codec_info is proper.
|
* The application needs to make sure the current codec_info is proper.
|
||||||
* If one audio connection is open and another SNK attempts to connect to AV,
|
* If one audio connection is open and another SNK attempts to connect to AV,
|
||||||
@@ -1397,6 +1406,7 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
open.status = BTA_AV_SUCCESS;
|
open.status = BTA_AV_SUCCESS;
|
||||||
open.starting = bta_av_chk_start(p_scb);
|
open.starting = bta_av_chk_start(p_scb);
|
||||||
open.edr = 0;
|
open.edr = 0;
|
||||||
|
open.mtu = mtu;
|
||||||
if ( NULL != (p = BTM_ReadRemoteFeatures(p_scb->peer_addr))) {
|
if ( NULL != (p = BTM_ReadRemoteFeatures(p_scb->peer_addr))) {
|
||||||
if (HCI_EDR_ACL_2MPS_SUPPORTED(p)) {
|
if (HCI_EDR_ACL_2MPS_SUPPORTED(p)) {
|
||||||
open.edr |= BTA_AV_EDR_2MBPS;
|
open.edr |= BTA_AV_EDR_2MBPS;
|
||||||
@@ -1533,7 +1543,7 @@ void bta_av_do_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
|
L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
|
||||||
|
|
||||||
AVDT_CloseReq(p_scb->avdt_handle);
|
AVDT_CloseReq(p_scb->avdt_handle);
|
||||||
/* just in case that the link is congested, link is flow controled by peer or
|
/* just in case that the link is congested, link is flow controlled by peer or
|
||||||
* for whatever reason the the close request can not be sent in time.
|
* for whatever reason the the close request can not be sent in time.
|
||||||
* when this timer expires, AVDT_DisconnectReq will be called to disconnect the link
|
* when this timer expires, AVDT_DisconnectReq will be called to disconnect the link
|
||||||
*/
|
*/
|
||||||
@@ -1814,7 +1824,7 @@ void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if there is already an active AV connnection with the same bd_addr,
|
/* if there is already an active AV connection with the same bd_addr,
|
||||||
don't send disconnect req, just report the open event with BTA_AV_FAIL_GET_CAP status */
|
don't send disconnect req, just report the open event with BTA_AV_FAIL_GET_CAP status */
|
||||||
if (is_av_opened == TRUE) {
|
if (is_av_opened == TRUE) {
|
||||||
bdcpy(open.bd_addr, p_scb->peer_addr);
|
bdcpy(open.bd_addr, p_scb->peer_addr);
|
||||||
@@ -1856,7 +1866,7 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
tAVDT_CFG cfg;
|
tAVDT_CFG cfg;
|
||||||
UINT8 media_type;
|
UINT8 media_type;
|
||||||
tAVDT_SEP_INFO *p_info = &p_scb->sep_info[p_scb->sep_info_idx];
|
tAVDT_SEP_INFO *p_info = &p_scb->sep_info[p_scb->sep_info_idx];
|
||||||
UINT16 uuid_int; /* UUID for which connection was initiatied */
|
UINT16 uuid_int; /* UUID for which connection was initiated */
|
||||||
tBTA_AV_SNK_PSC_CFG psc_cfg = {0};
|
tBTA_AV_SNK_PSC_CFG psc_cfg = {0};
|
||||||
|
|
||||||
memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
|
memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
|
||||||
@@ -1899,9 +1909,9 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
p_scb->cur_psc_mask = cfg.psc_mask;
|
p_scb->cur_psc_mask = cfg.psc_mask;
|
||||||
|
|
||||||
if (uuid_int == UUID_SERVCLASS_AUDIO_SINK) {
|
if (uuid_int == UUID_SERVCLASS_AUDIO_SINK) {
|
||||||
if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) {
|
if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) {
|
||||||
APPL_TRACE_DEBUG(" Configure Deoder for Sink Connection ");
|
APPL_TRACE_DEBUG(" Configure Deoder for Sink Connection ");
|
||||||
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_SINK_CFG_EVT,
|
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT,
|
||||||
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
|
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
|
||||||
}
|
}
|
||||||
if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) {
|
if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) {
|
||||||
@@ -1909,6 +1919,13 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
}
|
}
|
||||||
(*bta_av_cb.p_cback)(BTA_AV_SNK_PSC_CFG_EVT, (tBTA_AV *)&psc_cfg);
|
(*bta_av_cb.p_cback)(BTA_AV_SNK_PSC_CFG_EVT, (tBTA_AV *)&psc_cfg);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* UUID_SERVCLASS_AUDIO_SOURCE */
|
||||||
|
if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) {
|
||||||
|
p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT,
|
||||||
|
(tBTA_AV_MEDIA *)p_scb->cfg.codec_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* open the stream */
|
/* open the stream */
|
||||||
AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
|
AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
|
||||||
@@ -2387,7 +2404,7 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
{
|
{
|
||||||
/* If sink starts stream, disable sniff mode here */
|
/* If sink starts stream, disable sniff mode here */
|
||||||
if (!initiator) {
|
if (!initiator) {
|
||||||
/* If souce is the master role, disable role switch during streaming.
|
/* If source is the master role, disable role switch during streaming.
|
||||||
* Otherwise allow role switch, if source is slave.
|
* Otherwise allow role switch, if source is slave.
|
||||||
* Because it would not hurt source, if the peer device wants source to be master */
|
* Because it would not hurt source, if the peer device wants source to be master */
|
||||||
if ((BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
|
if ((BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
|
||||||
@@ -2502,7 +2519,7 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
|
|||||||
bta_av_str_stopped(p_scb, NULL);
|
bta_av_str_stopped(p_scb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update common mtu shared by remaining connectons */
|
/* Update common mtu shared by remaining connections */
|
||||||
mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
|
mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@@ -129,6 +129,23 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BTA_AvRegSEP(tBTA_AV_CHNL chnl, UINT8 seid, UINT8 tsep, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, tBTA_AV_DATA_CBACK *p_data_cback)
|
||||||
|
{
|
||||||
|
tBTA_AV_API_REG_SEP *p_buf;
|
||||||
|
|
||||||
|
if ((p_buf = (tBTA_AV_API_REG_SEP *) osi_malloc(sizeof(tBTA_AV_API_REG_SEP))) != NULL) {
|
||||||
|
p_buf->hdr.layer_specific = chnl;
|
||||||
|
p_buf->hdr.event = BTA_AV_API_REG_SEP_EVT;
|
||||||
|
|
||||||
|
p_buf->seid = seid;
|
||||||
|
p_buf->tsep = tsep;
|
||||||
|
p_buf->codec_type = codec_type;
|
||||||
|
memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE);
|
||||||
|
p_buf->p_data_cback = p_data_cback;
|
||||||
|
bta_sys_sendmsg(p_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function BTA_AvDeregister
|
** Function BTA_AvDeregister
|
||||||
|
@@ -151,6 +151,7 @@ static const tBTA_AV_ST_TBL bta_av_st_tbl[] = {
|
|||||||
typedef void (*tBTA_AV_NSM_ACT)(tBTA_AV_DATA *p_data);
|
typedef void (*tBTA_AV_NSM_ACT)(tBTA_AV_DATA *p_data);
|
||||||
static void bta_av_api_enable(tBTA_AV_DATA *p_data);
|
static void bta_av_api_enable(tBTA_AV_DATA *p_data);
|
||||||
static void bta_av_api_register(tBTA_AV_DATA *p_data);
|
static void bta_av_api_register(tBTA_AV_DATA *p_data);
|
||||||
|
static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data);
|
||||||
#if (BTA_AV_SINK_INCLUDED == TRUE)
|
#if (BTA_AV_SINK_INCLUDED == TRUE)
|
||||||
static void bta_av_api_sink_enable(tBTA_AV_DATA *p_data);
|
static void bta_av_api_sink_enable(tBTA_AV_DATA *p_data);
|
||||||
static void bta_av_api_get_delay_value(tBTA_AV_DATA *p_data);
|
static void bta_av_api_get_delay_value(tBTA_AV_DATA *p_data);
|
||||||
@@ -170,6 +171,7 @@ static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 ap
|
|||||||
const tBTA_AV_NSM_ACT bta_av_nsm_act[] = {
|
const tBTA_AV_NSM_ACT bta_av_nsm_act[] = {
|
||||||
bta_av_api_enable, /* BTA_AV_API_ENABLE_EVT */
|
bta_av_api_enable, /* BTA_AV_API_ENABLE_EVT */
|
||||||
bta_av_api_register, /* BTA_AV_API_REGISTER_EVT */
|
bta_av_api_register, /* BTA_AV_API_REGISTER_EVT */
|
||||||
|
bta_av_api_reg_sep, /* BTA_AV_API_REG_SEP_EVT */
|
||||||
bta_av_api_deregister, /* BTA_AV_API_DEREGISTER_EVT */
|
bta_av_api_deregister, /* BTA_AV_API_DEREGISTER_EVT */
|
||||||
bta_av_api_disconnect, /* BTA_AV_API_DISCONNECT_EVT */
|
bta_av_api_disconnect, /* BTA_AV_API_DISCONNECT_EVT */
|
||||||
bta_av_ci_data, /* BTA_AV_CI_SRC_DATA_READY_EVT */
|
bta_av_ci_data, /* BTA_AV_CI_SRC_DATA_READY_EVT */
|
||||||
@@ -533,9 +535,11 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
|
|||||||
tAVDT_REG reg;
|
tAVDT_REG reg;
|
||||||
tAVDT_CS cs;
|
tAVDT_CS cs;
|
||||||
char *p_service_name;
|
char *p_service_name;
|
||||||
tBTA_AV_CODEC codec_type;
|
|
||||||
tBTA_UTL_COD cod;
|
tBTA_UTL_COD cod;
|
||||||
|
#if (BTA_AV_EXT_CODEC == FALSE)
|
||||||
|
tBTA_AV_CODEC codec_type;
|
||||||
UINT8 index = 0;
|
UINT8 index = 0;
|
||||||
|
#endif
|
||||||
char p_avk_service_name[BTA_SERVICE_NAME_LEN + 1];
|
char p_avk_service_name[BTA_SERVICE_NAME_LEN + 1];
|
||||||
BCM_STRNCPY_S(p_avk_service_name, BTIF_AVK_SERVICE_NAME, BTA_SERVICE_NAME_LEN);
|
BCM_STRNCPY_S(p_avk_service_name, BTIF_AVK_SERVICE_NAME, BTA_SERVICE_NAME_LEN);
|
||||||
p_avk_service_name[BTA_SERVICE_NAME_LEN] = '\0';
|
p_avk_service_name[BTA_SERVICE_NAME_LEN] = '\0';
|
||||||
@@ -658,6 +662,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
|
|||||||
|
|
||||||
/* keep the configuration in the stream control block */
|
/* keep the configuration in the stream control block */
|
||||||
memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
|
memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
|
||||||
|
#if (BTA_AV_EXT_CODEC == FALSE)
|
||||||
while (index < BTA_AV_MAX_SEPS &&
|
while (index < BTA_AV_MAX_SEPS &&
|
||||||
(p_scb->p_cos->init)(&codec_type, cs.cfg.codec_info,
|
(p_scb->p_cos->init)(&codec_type, cs.cfg.codec_info,
|
||||||
&cs.cfg.num_protect, cs.cfg.protect_info, p_data->api_reg.tsep) == TRUE) {
|
&cs.cfg.num_protect, cs.cfg.protect_info, p_data->api_reg.tsep) == TRUE) {
|
||||||
@@ -673,12 +678,13 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
|
|||||||
|
|
||||||
#if (BTA_AV_SINK_INCLUDED == TRUE)
|
#if (BTA_AV_SINK_INCLUDED == TRUE)
|
||||||
p_scb->seps[index].tsep = cs.tsep;
|
p_scb->seps[index].tsep = cs.tsep;
|
||||||
if (cs.tsep == AVDT_TSEP_SNK) {
|
// if (cs.tsep == AVDT_TSEP_SNK) {
|
||||||
p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback;
|
// p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback;
|
||||||
} else {
|
// } else {
|
||||||
p_scb->seps[index].p_app_data_cback = NULL; /* In case of A2DP SOURCE we don't need a callback to handle media packets */
|
// p_scb->seps[index].p_app_data_cback = NULL; /* In case of A2DP SOURCE we don't need a callback to handle media packets */
|
||||||
}
|
// }
|
||||||
#endif
|
#endif
|
||||||
|
p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback;
|
||||||
|
|
||||||
APPL_TRACE_DEBUG("audio[%d] av_handle: %d codec_type: %d\n",
|
APPL_TRACE_DEBUG("audio[%d] av_handle: %d codec_type: %d\n",
|
||||||
index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type);
|
index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type);
|
||||||
@@ -687,6 +693,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!bta_av_cb.reg_audio) {
|
if (!bta_av_cb.reg_audio) {
|
||||||
if (p_data->api_reg.tsep == AVDT_TSEP_SRC) {
|
if (p_data->api_reg.tsep == AVDT_TSEP_SRC) {
|
||||||
@@ -744,6 +751,86 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
|
|||||||
(*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)®istr);
|
(*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)®istr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(p_data);
|
||||||
|
#if (BTA_AV_EXT_CODEC == TRUE)
|
||||||
|
tAVDT_CS cs;
|
||||||
|
tBTA_AV_CODEC codec_type;
|
||||||
|
UINT8 index = p_data->api_reg_sep.seid;
|
||||||
|
tBTA_AV_SEP_REG sep_reg;
|
||||||
|
|
||||||
|
sep_reg.seid = p_data->api_reg_sep.seid;
|
||||||
|
sep_reg.reg_state = BTA_AV_FAIL;
|
||||||
|
|
||||||
|
if (index > BTA_AV_MAX_SEPS || p_data->hdr.layer_specific != BTA_AV_CHNL_AUDIO) {
|
||||||
|
(*bta_av_cb.p_cback)(BTA_AV_SEP_REG_EVT, (tBTA_AV *)&sep_reg);
|
||||||
|
APPL_TRACE_WARNING("%s invalid parameter: seid %d, ch %d", __FUNCTION__, index, p_data->hdr.layer_specific);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&cs, 0, sizeof(tAVDT_CS));
|
||||||
|
cs.cfg.num_codec = 1;
|
||||||
|
cs.tsep = p_data->api_reg_sep.tsep;
|
||||||
|
cs.nsc_mask = AVDT_NSC_RECONFIG | ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY);
|
||||||
|
|
||||||
|
for (int xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
|
||||||
|
if (bta_av_cb.p_scb[xx] != NULL && bta_av_cb.p_scb[xx]->chnl == BTA_AV_CHNL_AUDIO) {
|
||||||
|
tBTA_AV_SCB *p_scb = bta_av_cb.p_scb[xx];
|
||||||
|
cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi];
|
||||||
|
cs.cfg.psc_mask = AVDT_PSC_TRANS;
|
||||||
|
cs.media_type = AVDT_MEDIA_AUDIO;
|
||||||
|
cs.mtu = p_bta_av_cfg->audio_mtu;
|
||||||
|
cs.flush_to = L2CAP_DEFAULT_FLUSH_TO;
|
||||||
|
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
if (bta_av_cb.features & BTA_AV_FEAT_REPORT) {
|
||||||
|
cs.cfg.psc_mask |= AVDT_PSC_REPORT;
|
||||||
|
cs.p_report_cback = bta_av_a2dp_report_cback;
|
||||||
|
#if AVDT_MULTIPLEXING == TRUE
|
||||||
|
cs.cfg.mux_tsid_report = 2;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT) {
|
||||||
|
cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT;
|
||||||
|
}
|
||||||
|
/* todo: check whether this memcpy is necessary */
|
||||||
|
memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
|
||||||
|
|
||||||
|
codec_type = p_data->api_reg_sep.codec_type;
|
||||||
|
memcpy(cs.cfg.codec_info, p_data->api_reg_sep.codec_info, AVDT_CODEC_SIZE);
|
||||||
|
if ((p_scb->p_cos->init)(&codec_type, cs.cfg.codec_info,
|
||||||
|
&cs.cfg.num_protect, cs.cfg.protect_info, p_data->api_reg_sep.tsep) == TRUE) {
|
||||||
|
|
||||||
|
#if (BTA_AV_SINK_INCLUDED == TRUE)
|
||||||
|
if (p_data->api_reg_sep.tsep == AVDT_TSEP_SNK) {
|
||||||
|
cs.p_data_cback = bta_av_stream_data_cback;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((p_scb->seps[index].av_handle != 0) && (AVDT_RemoveStream(p_scb->seps[index].av_handle) != AVDT_SUCCESS)) {
|
||||||
|
APPL_TRACE_WARNING("%s fail to remove exist sep", __FUNCTION__);
|
||||||
|
}
|
||||||
|
if (AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS) {
|
||||||
|
p_scb->seps[index].codec_type = codec_type;
|
||||||
|
p_scb->seps[index].tsep = cs.tsep;
|
||||||
|
p_scb->seps[index].p_app_data_cback = p_data->api_reg_sep.p_data_cback;
|
||||||
|
} else {
|
||||||
|
APPL_TRACE_WARNING("%s fail to create sep", __FUNCTION__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
APPL_TRACE_WARNING("%s invalid codec capability", __FUNCTION__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sep_reg.reg_state = BTA_AV_SUCCESS;
|
||||||
|
(*bta_av_cb.p_cback)(BTA_AV_SEP_REG_EVT, (tBTA_AV *)&sep_reg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function bta_av_api_deregister
|
** Function bta_av_api_deregister
|
||||||
@@ -1415,7 +1502,8 @@ char *bta_av_action_code(UINT16 action_code)
|
|||||||
case 46: return "BTA_AV_DELAY_CO";
|
case 46: return "BTA_AV_DELAY_CO";
|
||||||
case 47: return "BTA_AV_OPEN_AT_INC";
|
case 47: return "BTA_AV_OPEN_AT_INC";
|
||||||
case 48: return "BTA_AV_OPEN_FAIL_SDP";
|
case 48: return "BTA_AV_OPEN_FAIL_SDP";
|
||||||
case 49: return "NULL";
|
case 49: return "BTA_AV_SET_DELAY_VALUE";
|
||||||
|
case 50: return "NULL";
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -581,6 +581,64 @@ UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function bta_av_sbc_cfg_in_external_codec_cap
|
||||||
|
**
|
||||||
|
** Description This function checks whether an SBC codec configuration
|
||||||
|
** is allowable for the given external codec capabilities.
|
||||||
|
**
|
||||||
|
** Returns 0 if ok, nonzero if error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 bta_av_sbc_cfg_in_external_codec_cap(UINT8 *p_cfg, UINT8 *p_cap)
|
||||||
|
{
|
||||||
|
UINT8 status = 0;
|
||||||
|
tA2D_SBC_CIE cfg_cie;
|
||||||
|
tA2D_SBC_CIE cap_cie;
|
||||||
|
|
||||||
|
/* parse configuration */
|
||||||
|
if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, FALSE)) != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/* parse capability */
|
||||||
|
if ((status = A2D_ParsSbcInfo(&cap_cie, p_cap, TRUE)) != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verify that each parameter is in range */
|
||||||
|
|
||||||
|
/* sampling frequency */
|
||||||
|
if ((cfg_cie.samp_freq & cap_cie.samp_freq) == 0) {
|
||||||
|
status = A2D_NS_SAMP_FREQ;
|
||||||
|
}
|
||||||
|
/* channel mode */
|
||||||
|
else if ((cfg_cie.ch_mode & cap_cie.ch_mode) == 0) {
|
||||||
|
status = A2D_NS_CH_MODE;
|
||||||
|
}
|
||||||
|
/* block length */
|
||||||
|
else if ((cfg_cie.block_len & cap_cie.block_len) == 0) {
|
||||||
|
status = A2D_BAD_BLOCK_LEN;
|
||||||
|
}
|
||||||
|
/* subbands */
|
||||||
|
else if ((cfg_cie.num_subbands & cap_cie.num_subbands) == 0) {
|
||||||
|
status = A2D_NS_SUBBANDS;
|
||||||
|
}
|
||||||
|
/* allocation method */
|
||||||
|
else if ((cfg_cie.alloc_mthd & cap_cie.alloc_mthd) == 0) {
|
||||||
|
status = A2D_NS_ALLOC_MTHD;
|
||||||
|
}
|
||||||
|
/* max bitpool */
|
||||||
|
else if (cfg_cie.max_bitpool > cap_cie.max_bitpool) {
|
||||||
|
status = A2D_NS_MAX_BITPOOL;
|
||||||
|
}
|
||||||
|
/* min bitpool */
|
||||||
|
else if (cfg_cie.min_bitpool < cap_cie.min_bitpool) {
|
||||||
|
status = A2D_NS_MIN_BITPOOL;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function bta_av_sbc_bld_hdr
|
** Function bta_av_sbc_bld_hdr
|
||||||
|
@@ -98,6 +98,7 @@ enum {
|
|||||||
/* these events are handled outside of the state machine */
|
/* these events are handled outside of the state machine */
|
||||||
BTA_AV_API_ENABLE_EVT,
|
BTA_AV_API_ENABLE_EVT,
|
||||||
BTA_AV_API_REGISTER_EVT,
|
BTA_AV_API_REGISTER_EVT,
|
||||||
|
BTA_AV_API_REG_SEP_EVT,
|
||||||
BTA_AV_API_DEREGISTER_EVT,
|
BTA_AV_API_DEREGISTER_EVT,
|
||||||
BTA_AV_API_DISCONNECT_EVT,
|
BTA_AV_API_DISCONNECT_EVT,
|
||||||
BTA_AV_CI_SRC_DATA_READY_EVT,
|
BTA_AV_CI_SRC_DATA_READY_EVT,
|
||||||
@@ -195,6 +196,15 @@ typedef struct {
|
|||||||
tBTA_AVRC_CO_FUNCTS *bta_avrc_cos;
|
tBTA_AVRC_CO_FUNCTS *bta_avrc_cos;
|
||||||
} tBTA_AV_API_REG;
|
} tBTA_AV_API_REG;
|
||||||
|
|
||||||
|
/* data type for BTA_AV_API_REG_SEP_EVT */
|
||||||
|
typedef struct {
|
||||||
|
BT_HDR hdr;
|
||||||
|
UINT8 seid;
|
||||||
|
UINT8 tsep;
|
||||||
|
tBTA_AV_CODEC codec_type;
|
||||||
|
UINT8 codec_info[AVDT_CODEC_SIZE];
|
||||||
|
tBTA_AV_DATA_CBACK *p_data_cback;
|
||||||
|
} tBTA_AV_API_REG_SEP;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BTA_AV_RS_NONE, /* straight API call */
|
BTA_AV_RS_NONE, /* straight API call */
|
||||||
@@ -425,6 +435,7 @@ typedef union {
|
|||||||
BT_HDR hdr;
|
BT_HDR hdr;
|
||||||
tBTA_AV_API_ENABLE api_enable;
|
tBTA_AV_API_ENABLE api_enable;
|
||||||
tBTA_AV_API_REG api_reg;
|
tBTA_AV_API_REG api_reg;
|
||||||
|
tBTA_AV_API_REG_SEP api_reg_sep;
|
||||||
tBTA_AV_API_OPEN api_open;
|
tBTA_AV_API_OPEN api_open;
|
||||||
tBTA_AV_API_STOP api_stop;
|
tBTA_AV_API_STOP api_stop;
|
||||||
tBTA_AV_API_DISCNT api_discnt;
|
tBTA_AV_API_DISCNT api_discnt;
|
||||||
|
@@ -256,18 +256,19 @@ typedef UINT8 tBTA_AV_GET_TYPE;
|
|||||||
#define BTA_AV_META_MSG_EVT 17 /* metadata messages */
|
#define BTA_AV_META_MSG_EVT 17 /* metadata messages */
|
||||||
#define BTA_AV_REJECT_EVT 18 /* incoming connection rejected */
|
#define BTA_AV_REJECT_EVT 18 /* incoming connection rejected */
|
||||||
#define BTA_AV_RC_FEAT_EVT 19 /* remote control channel peer supported features update */
|
#define BTA_AV_RC_FEAT_EVT 19 /* remote control channel peer supported features update */
|
||||||
#define BTA_AV_MEDIA_SINK_CFG_EVT 20 /* command to configure codec */
|
#define BTA_AV_MEDIA_CFG_EVT 20 /* command to configure codec */
|
||||||
#define BTA_AV_MEDIA_DATA_EVT 21 /* sending data to Media Task */
|
#define BTA_AV_MEDIA_DATA_EVT 21 /* sending data to Media Task */
|
||||||
#define BTA_AV_SET_DELAY_VALUE_EVT 22 /* set delay reporting value */
|
#define BTA_AV_SET_DELAY_VALUE_EVT 22 /* set delay reporting value */
|
||||||
#define BTA_AV_GET_DELAY_VALUE_EVT 23 /* get delay reporting value */
|
#define BTA_AV_GET_DELAY_VALUE_EVT 23 /* get delay reporting value */
|
||||||
#define BTA_AV_SNK_PSC_CFG_EVT 24 /* Protocol service capabilities. */
|
#define BTA_AV_SNK_PSC_CFG_EVT 24 /* Protocol service capabilities. */
|
||||||
|
#define BTA_AV_SEP_REG_EVT 25 /* stream endpoint registered */
|
||||||
|
|
||||||
/* still keep Cover Art event here if Cover Art feature not enabled */
|
/* still keep Cover Art event here if Cover Art feature not enabled */
|
||||||
#define BTA_AV_CA_STATUS_EVT 25 /* Cover Art Client status event */
|
#define BTA_AV_CA_STATUS_EVT 26 /* Cover Art Client status event */
|
||||||
#define BTA_AV_CA_DATA_EVT 26 /* Cover Art response body data */
|
#define BTA_AV_CA_DATA_EVT 27 /* Cover Art response body data */
|
||||||
|
|
||||||
/* Max BTA event */
|
/* Max BTA event */
|
||||||
#define BTA_AV_MAX_EVT 27
|
#define BTA_AV_MAX_EVT 28
|
||||||
|
|
||||||
|
|
||||||
/* function types for call-out functions */
|
/* function types for call-out functions */
|
||||||
@@ -341,6 +342,12 @@ typedef struct {
|
|||||||
tBTA_AVRC_CO_FUNCTS *p_bta_avrc_cos;
|
tBTA_AVRC_CO_FUNCTS *p_bta_avrc_cos;
|
||||||
} tBTA_AV_REGISTER;
|
} tBTA_AV_REGISTER;
|
||||||
|
|
||||||
|
/* Event associated with BTA_AV_SEP_REG_EVT */
|
||||||
|
typedef struct {
|
||||||
|
UINT8 seid;
|
||||||
|
tBTA_AV_STATUS reg_state;
|
||||||
|
} tBTA_AV_SEP_REG;
|
||||||
|
|
||||||
/* data associated with BTA_AV_OPEN_EVT */
|
/* data associated with BTA_AV_OPEN_EVT */
|
||||||
#define BTA_AV_EDR_2MBPS 0x01
|
#define BTA_AV_EDR_2MBPS 0x01
|
||||||
#define BTA_AV_EDR_3MBPS 0x02
|
#define BTA_AV_EDR_3MBPS 0x02
|
||||||
@@ -354,6 +361,7 @@ typedef struct {
|
|||||||
BOOLEAN starting;
|
BOOLEAN starting;
|
||||||
tBTA_AV_EDR edr; /* 0, if peer device does not support EDR */
|
tBTA_AV_EDR edr; /* 0, if peer device does not support EDR */
|
||||||
UINT8 sep; /* sep type of peer device */
|
UINT8 sep; /* sep type of peer device */
|
||||||
|
UINT16 mtu;
|
||||||
} tBTA_AV_OPEN;
|
} tBTA_AV_OPEN;
|
||||||
|
|
||||||
/* data associated with BTA_AV_CLOSE_EVT */
|
/* data associated with BTA_AV_CLOSE_EVT */
|
||||||
@@ -519,6 +527,7 @@ typedef union {
|
|||||||
tBTA_AV_CHNL chnl;
|
tBTA_AV_CHNL chnl;
|
||||||
tBTA_AV_ENABLE enable;
|
tBTA_AV_ENABLE enable;
|
||||||
tBTA_AV_REGISTER registr;
|
tBTA_AV_REGISTER registr;
|
||||||
|
tBTA_AV_SEP_REG sep_reg;
|
||||||
tBTA_AV_OPEN open;
|
tBTA_AV_OPEN open;
|
||||||
tBTA_AV_CLOSE close;
|
tBTA_AV_CLOSE close;
|
||||||
tBTA_AV_START start;
|
tBTA_AV_START start;
|
||||||
@@ -657,6 +666,8 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name,
|
|||||||
tBTA_AV_CO_FUNCTS *bta_av_cos, tBTA_AVRC_CO_FUNCTS *bta_avrc_cos,
|
tBTA_AV_CO_FUNCTS *bta_av_cos, tBTA_AVRC_CO_FUNCTS *bta_avrc_cos,
|
||||||
UINT8 tsep);
|
UINT8 tsep);
|
||||||
|
|
||||||
|
void BTA_AvRegSEP(tBTA_AV_CHNL chnl, UINT8 idx, UINT8 tsep, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, tBTA_AV_DATA_CBACK *p_data_cback);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function BTA_AvDeregister
|
** Function BTA_AvDeregister
|
||||||
|
@@ -194,6 +194,18 @@ extern UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
extern UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap);
|
extern UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function bta_av_sbc_cfg_in_external_codec_cap
|
||||||
|
**
|
||||||
|
** Description This function checks whether an SBC codec configuration
|
||||||
|
** is allowable for the given external codec capabilities.
|
||||||
|
**
|
||||||
|
** Returns 0 if ok, nonzero if error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
extern UINT8 bta_av_sbc_cfg_in_external_codec_cap(UINT8 *p_cfg, UINT8 *p_cap);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function bta_av_sbc_cfg_matches_cap
|
** Function bta_av_sbc_cfg_matches_cap
|
||||||
|
@@ -122,7 +122,6 @@ static UINT8 bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8
|
|||||||
static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index);
|
static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function bta_av_co_cp_is_active
|
** Function bta_av_co_cp_is_active
|
||||||
@@ -245,18 +244,29 @@ BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_
|
|||||||
UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
|
UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
|
||||||
} while (0);
|
} while (0);
|
||||||
#endif
|
#endif
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
/* for external codec, we get codec capability from BTA_AV */
|
||||||
|
bta_av_co_cb.codec_caps.id = *p_codec_type;
|
||||||
|
memcpy(bta_av_co_cb.codec_caps.info, p_codec_info, AVDT_CODEC_SIZE);
|
||||||
|
bta_av_co_audio_codec_reset();
|
||||||
|
#else
|
||||||
/* Set up for SBC codec for SRC*/
|
/* Set up for SBC codec for SRC*/
|
||||||
*p_codec_type = BTA_AV_CODEC_SBC;
|
*p_codec_type = BTA_AV_CODEC_SBC;
|
||||||
|
|
||||||
/* This should not fail because we are using constants for parameters */
|
/* This should not fail because we are using constants for parameters */
|
||||||
A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info);
|
A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info);
|
||||||
|
#endif
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else if (tsep == AVDT_TSEP_SNK) {
|
} else if (tsep == AVDT_TSEP_SNK) {
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
/* for external codec, we get codec capability from BTA_AV */
|
||||||
|
bta_av_co_cb.codec_caps.id = *p_codec_type;
|
||||||
|
memcpy(bta_av_co_cb.codec_caps.info, p_codec_info, AVDT_CODEC_SIZE);
|
||||||
|
bta_av_co_audio_codec_reset();
|
||||||
|
#else
|
||||||
*p_codec_type = BTA_AV_CODEC_SBC;
|
*p_codec_type = BTA_AV_CODEC_SBC;
|
||||||
|
|
||||||
/* This should not fail because we are using constants for parameters */
|
/* This should not fail because we are using constants for parameters */
|
||||||
A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_sink_caps, p_codec_info);
|
A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_sink_caps, p_codec_info);
|
||||||
|
#endif
|
||||||
/* Codec is valid */
|
/* Codec is valid */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else {
|
} else {
|
||||||
@@ -387,7 +397,7 @@ void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap)
|
|||||||
/* now try to build a preferred one */
|
/* now try to build a preferred one */
|
||||||
/* parse configuration */
|
/* parse configuration */
|
||||||
if ((status = A2D_ParsSbcInfo(&src_cap, p_src_cap, TRUE)) != 0) {
|
if ((status = A2D_ParsSbcInfo(&src_cap, p_src_cap, TRUE)) != 0) {
|
||||||
APPL_TRACE_DEBUG(" Cant parse src cap ret = %d", status);
|
APPL_TRACE_DEBUG(" Can't parse src cap ret = %d", status);
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,12 +1072,12 @@ static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UIN
|
|||||||
memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF + 1);
|
memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF + 1);
|
||||||
|
|
||||||
/* Update the bit pool boundaries with the codec capabilities */
|
/* Update the bit pool boundaries with the codec capabilities */
|
||||||
p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
|
p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = BTA_AV_CO_MAX(p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF]);
|
||||||
p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
|
p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = BTA_AV_CO_MIN(p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
|
||||||
|
|
||||||
APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config : bitpool min %d, max %d",
|
APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config : bitpool min %d, max %d",
|
||||||
p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
|
p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
|
||||||
p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
|
p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
APPL_TRACE_ERROR("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
|
APPL_TRACE_ERROR("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
|
||||||
@@ -1301,10 +1311,20 @@ static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer,
|
|||||||
if (p_src_index) {
|
if (p_src_index) {
|
||||||
*p_src_index = index;
|
*p_src_index = index;
|
||||||
}
|
}
|
||||||
if (0 == bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps,
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
(tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps)) {
|
tA2D_SBC_CIE cap_cie;
|
||||||
|
if (A2D_ParsSbcInfo(&cap_cie, bta_av_co_cb.codec_caps.info, TRUE) != A2D_SUCCESS) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (0 == bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps, &cap_cie)) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (0 == bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps,
|
||||||
|
(tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1334,7 +1354,11 @@ static UINT8 bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8
|
|||||||
|
|
||||||
switch (codec_type) {
|
switch (codec_type) {
|
||||||
case BTA_AV_CODEC_SBC:
|
case BTA_AV_CODEC_SBC:
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
status = bta_av_sbc_cfg_in_external_codec_cap((UINT8 *)p_codec_cfg, (UINT8 *)bta_av_co_cb.codec_caps.info);
|
||||||
|
#else
|
||||||
status = bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps);
|
status = bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case BTA_AV_CODEC_M12:
|
case BTA_AV_CODEC_M12:
|
||||||
case BTA_AV_CODEC_M24:
|
case BTA_AV_CODEC_M24:
|
||||||
@@ -1365,7 +1389,11 @@ static UINT8 bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8
|
|||||||
|
|
||||||
switch (codec_type) {
|
switch (codec_type) {
|
||||||
case BTA_AV_CODEC_SBC:
|
case BTA_AV_CODEC_SBC:
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
status = bta_av_sbc_cfg_in_external_codec_cap((UINT8 *)p_codec_cfg, (UINT8 *)bta_av_co_cb.codec_caps.info);
|
||||||
|
#else
|
||||||
status = bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps);
|
status = bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case BTA_AV_CODEC_M12:
|
case BTA_AV_CODEC_M12:
|
||||||
case BTA_AV_CODEC_M24:
|
case BTA_AV_CODEC_M24:
|
||||||
@@ -1478,12 +1506,16 @@ void bta_av_co_audio_codec_reset(void)
|
|||||||
osi_mutex_global_lock();
|
osi_mutex_global_lock();
|
||||||
FUNC_TRACE();
|
FUNC_TRACE();
|
||||||
|
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
bta_av_co_cb.codec_cfg.id = bta_av_co_cb.codec_caps.id;
|
||||||
|
bta_av_build_src_cfg(bta_av_co_cb.codec_cfg.info, bta_av_co_cb.codec_caps.info);
|
||||||
|
#else
|
||||||
/* Reset the current configuration to SBC */
|
/* Reset the current configuration to SBC */
|
||||||
bta_av_co_cb.codec_cfg.id = BTC_AV_CODEC_SBC;
|
bta_av_co_cb.codec_cfg.id = BTC_AV_CODEC_SBC;
|
||||||
|
|
||||||
if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btc_av_sbc_default_config, bta_av_co_cb.codec_cfg.info) != A2D_SUCCESS) {
|
if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btc_av_sbc_default_config, bta_av_co_cb.codec_cfg.info) != A2D_SUCCESS) {
|
||||||
APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed");
|
APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
osi_mutex_global_unlock();
|
osi_mutex_global_unlock();
|
||||||
}
|
}
|
||||||
@@ -1564,7 +1596,6 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTC_AV_MEDIA_FEEDINGS *p_feeding, tBTC_
|
|||||||
/* The new config was correctly built */
|
/* The new config was correctly built */
|
||||||
bta_av_co_cb.codec_cfg = new_cfg;
|
bta_av_co_cb.codec_cfg = new_cfg;
|
||||||
|
|
||||||
|
|
||||||
/* Check all devices support it */
|
/* Check all devices support it */
|
||||||
*p_status = BTC_AV_SUCCESS;
|
*p_status = BTC_AV_SUCCESS;
|
||||||
return bta_av_co_audio_codec_supported(p_status);
|
return bta_av_co_audio_codec_supported(p_status);
|
||||||
@@ -1666,13 +1697,16 @@ void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl)
|
|||||||
** Returns Nothing
|
** Returns Nothing
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void bta_av_co_init(void)
|
void bta_av_co_init(tBTC_AV_CODEC_INFO *codec_caps)
|
||||||
{
|
{
|
||||||
FUNC_TRACE();
|
FUNC_TRACE();
|
||||||
|
|
||||||
/* Reset the control block */
|
/* Reset the control block */
|
||||||
memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));
|
memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));
|
||||||
|
|
||||||
|
if (codec_caps) {
|
||||||
|
memcpy(&bta_av_co_cb.codec_caps, codec_caps, sizeof(tBTC_AV_CODEC_INFO));
|
||||||
|
}
|
||||||
bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_NONE;
|
bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_NONE;
|
||||||
|
|
||||||
#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
|
#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
|
||||||
@@ -1685,7 +1719,6 @@ void bta_av_co_init(void)
|
|||||||
bta_av_co_audio_codec_reset();
|
bta_av_co_audio_codec_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function bta_av_co_peer_cp_supported
|
** Function bta_av_co_peer_cp_supported
|
||||||
@@ -1729,7 +1762,7 @@ BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl)
|
|||||||
** of our exported bitpool range. If set we will set the
|
** of our exported bitpool range. If set we will set the
|
||||||
** remote preference.
|
** remote preference.
|
||||||
**
|
**
|
||||||
** Returns TRUE if config set, FALSE otherwize
|
** Returns TRUE if config set, FALSE otherwise
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
@@ -49,7 +49,12 @@ void btc_a2dp_on_idle(void)
|
|||||||
}
|
}
|
||||||
#endif // BTC_AV_SRC_INCLUDED
|
#endif // BTC_AV_SRC_INCLUDED
|
||||||
|
|
||||||
bta_av_co_init();
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
tBTC_AV_CODEC_INFO *codec_caps = btc_av_codec_cap_get();
|
||||||
|
#else
|
||||||
|
tBTC_AV_CODEC_INFO *codec_caps = NULL;
|
||||||
|
#endif
|
||||||
|
bta_av_co_init(codec_caps);
|
||||||
|
|
||||||
#if BTC_AV_SINK_INCLUDED
|
#if BTC_AV_SINK_INCLUDED
|
||||||
if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) {
|
if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) {
|
||||||
@@ -88,9 +93,11 @@ BOOLEAN btc_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start)
|
|||||||
ack = TRUE;
|
ack = TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#if (BTC_AV_EXT_CODEC == FALSE)
|
||||||
/* we were remotely started, make sure codec
|
/* we were remotely started, make sure codec
|
||||||
is setup before datapath is started */
|
is setup before datapath is started */
|
||||||
btc_a2dp_source_setup_codec();
|
btc_a2dp_source_setup_codec();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* media task is autostarted upon a2dp audiopath connection */
|
/* media task is autostarted upon a2dp audiopath connection */
|
||||||
|
@@ -71,8 +71,10 @@ static void btc_a2dp_datapath_open(void)
|
|||||||
/* Start the media task to encode SBC */
|
/* Start the media task to encode SBC */
|
||||||
btc_a2dp_source_start_audio_req();
|
btc_a2dp_source_start_audio_req();
|
||||||
|
|
||||||
|
#if (BTC_AV_EXT_CODEC == FALSE)
|
||||||
/* make sure we update any changed sbc encoder params */
|
/* make sure we update any changed sbc encoder params */
|
||||||
btc_a2dp_source_encoder_update();
|
btc_a2dp_source_encoder_update();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if (BTC_AV_SINK_INCLUDED == TRUE)
|
#if (BTC_AV_SINK_INCLUDED == TRUE)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -30,12 +30,13 @@
|
|||||||
#include "btc_av.h"
|
#include "btc_av.h"
|
||||||
#include "btc/btc_util.h"
|
#include "btc/btc_util.h"
|
||||||
#include "esp_a2dp_api.h"
|
#include "esp_a2dp_api.h"
|
||||||
#include "oi_codec_sbc.h"
|
|
||||||
#include "oi_status.h"
|
|
||||||
#include "osi/future.h"
|
#include "osi/future.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#if (BTC_AV_SINK_INCLUDED == TRUE)
|
#if (BTC_AV_SINK_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE)
|
||||||
|
|
||||||
|
#include "oi_codec_sbc.h"
|
||||||
|
#include "oi_status.h"
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Constants
|
** Constants
|
||||||
@@ -85,13 +86,6 @@ typedef struct {
|
|||||||
void *param;
|
void *param;
|
||||||
} a2dp_sink_task_evt_t;
|
} a2dp_sink_task_evt_t;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
UINT16 num_frames_to_be_processed;
|
|
||||||
UINT16 len;
|
|
||||||
UINT16 offset;
|
|
||||||
UINT16 layer_specific;
|
|
||||||
} tBT_SBC_HDR;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BOOLEAN rx_flush; /* discards any incoming data when true */
|
BOOLEAN rx_flush; /* discards any incoming data when true */
|
||||||
UINT8 channel_count;
|
UINT8 channel_count;
|
||||||
@@ -121,7 +115,7 @@ static void btc_a2dp_sink_rx_flush(void);
|
|||||||
static int btc_a2dp_sink_get_track_frequency(UINT8 frequency);
|
static int btc_a2dp_sink_get_track_frequency(UINT8 frequency);
|
||||||
static int btc_a2dp_sink_get_track_channel_count(UINT8 channeltype);
|
static int btc_a2dp_sink_get_track_channel_count(UINT8 channeltype);
|
||||||
/* Handle incoming media packets A2DP SINK streaming*/
|
/* Handle incoming media packets A2DP SINK streaming*/
|
||||||
static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg);
|
static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg);
|
||||||
static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg);
|
static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg);
|
||||||
static void btc_a2dp_sink_handle_clear_track(void);
|
static void btc_a2dp_sink_handle_clear_track(void);
|
||||||
static BOOLEAN btc_a2dp_sink_clear_track(void);
|
static BOOLEAN btc_a2dp_sink_clear_track(void);
|
||||||
@@ -346,7 +340,7 @@ void btc_a2dp_sink_reset_decoder(UINT8 *p_av)
|
|||||||
|
|
||||||
static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
|
static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
|
||||||
{
|
{
|
||||||
tBT_SBC_HDR *p_msg;
|
BT_HDR *p_msg;
|
||||||
int nb_of_msgs_to_process = 0;
|
int nb_of_msgs_to_process = 0;
|
||||||
|
|
||||||
if (fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) {
|
if (fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) {
|
||||||
@@ -362,13 +356,12 @@ static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
|
|||||||
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
|
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p_msg = (tBT_SBC_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, 0);
|
p_msg = (BT_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, 0);
|
||||||
if ( p_msg == NULL ) {
|
if ( p_msg == NULL ) {
|
||||||
APPL_TRACE_ERROR("Insufficient data in que ");
|
APPL_TRACE_ERROR("Insufficient data in que ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
btc_a2dp_sink_handle_inc_media(p_msg);
|
btc_a2dp_sink_handle_inc_media(p_msg);
|
||||||
osi_free(p_msg);
|
|
||||||
nb_of_msgs_to_process--;
|
nb_of_msgs_to_process--;
|
||||||
}
|
}
|
||||||
APPL_TRACE_DEBUG(" Process Frames - ");
|
APPL_TRACE_DEBUG(" Process Frames - ");
|
||||||
@@ -526,25 +519,27 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg
|
|||||||
** Returns void
|
** Returns void
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg)
|
static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg)
|
||||||
{
|
{
|
||||||
UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
|
UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
|
||||||
int count;
|
int count;
|
||||||
UINT32 pcmBytes, availPcmBytes;
|
UINT32 pcmBytes, availPcmBytes;
|
||||||
OI_INT16 *pcmDataPointer = a2dp_sink_local_param.pcmData; /*Will be overwritten on next packet receipt*/
|
OI_INT16 *pcmDataPointer = a2dp_sink_local_param.pcmData; /*Will be overwritten on next packet receipt*/
|
||||||
OI_STATUS status;
|
OI_STATUS status;
|
||||||
int num_sbc_frames = p_msg->num_frames_to_be_processed;
|
int num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
|
||||||
UINT32 sbc_frame_len = p_msg->len - 1;
|
UINT32 sbc_frame_len = p_msg->len - 1;
|
||||||
availPcmBytes = sizeof(a2dp_sink_local_param.pcmData);
|
availPcmBytes = sizeof(a2dp_sink_local_param.pcmData);
|
||||||
|
|
||||||
/* XXX: Check if the below check is correct, we are checking for peer to be sink when we are sink */
|
/* XXX: Check if the below check is correct, we are checking for peer to be sink when we are sink */
|
||||||
if (btc_av_get_peer_sep() == AVDT_TSEP_SNK || (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush)) {
|
if (btc_av_get_peer_sep() == AVDT_TSEP_SNK || (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush)) {
|
||||||
APPL_TRACE_DEBUG(" State Changed happened in this tick ");
|
APPL_TRACE_DEBUG(" State Changed happened in this tick ");
|
||||||
|
osi_free(p_msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore data if no one is listening
|
// ignore data if no one is listening
|
||||||
if (!btc_a2dp_control_get_datachnl_stat()) {
|
if (!btc_a2dp_control_get_datachnl_stat()) {
|
||||||
|
osi_free(p_msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,9 +560,9 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg)
|
|||||||
for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) {
|
for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) {
|
||||||
pcmBytes = availPcmBytes;
|
pcmBytes = availPcmBytes;
|
||||||
status = OI_CODEC_SBC_DecodeFrame(&a2dp_sink_local_param.context, (const OI_BYTE **)&sbc_start_frame,
|
status = OI_CODEC_SBC_DecodeFrame(&a2dp_sink_local_param.context, (const OI_BYTE **)&sbc_start_frame,
|
||||||
(OI_UINT32 *)&sbc_frame_len,
|
(OI_UINT32 *)&sbc_frame_len,
|
||||||
(OI_INT16 *)pcmDataPointer,
|
(OI_INT16 *)pcmDataPointer,
|
||||||
(OI_UINT32 *)&pcmBytes);
|
(OI_UINT32 *)&pcmBytes);
|
||||||
if (!OI_SUCCESS(status)) {
|
if (!OI_SUCCESS(status)) {
|
||||||
APPL_TRACE_ERROR("Decoding failure: %d\n", status);
|
APPL_TRACE_ERROR("Decoding failure: %d\n", status);
|
||||||
break;
|
break;
|
||||||
@@ -577,6 +572,7 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg)
|
|||||||
p_msg->offset += (p_msg->len - 1) - sbc_frame_len;
|
p_msg->offset += (p_msg->len - 1) - sbc_frame_len;
|
||||||
p_msg->len = sbc_frame_len + 1;
|
p_msg->len = sbc_frame_len + 1;
|
||||||
}
|
}
|
||||||
|
osi_free(p_msg);
|
||||||
|
|
||||||
btc_a2d_data_cb_to_app((uint8_t *)a2dp_sink_local_param.pcmData, (sizeof(a2dp_sink_local_param.pcmData) - availPcmBytes));
|
btc_a2d_data_cb_to_app((uint8_t *)a2dp_sink_local_param.pcmData, (sizeof(a2dp_sink_local_param.pcmData) - availPcmBytes));
|
||||||
}
|
}
|
||||||
@@ -663,35 +659,28 @@ static int btc_a2dp_sink_get_track_channel_count(UINT8 channeltype)
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt)
|
UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt)
|
||||||
{
|
{
|
||||||
tBT_SBC_HDR *p_msg;
|
|
||||||
|
|
||||||
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
|
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
|
||||||
|
osi_free(p_pkt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) { /* Flush enabled, do not enque*/
|
if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) { /* Flush enabled, do not enqueue */
|
||||||
|
osi_free(p_pkt);
|
||||||
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
|
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) >= MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ) {
|
if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) >= MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ) {
|
||||||
|
osi_free(p_pkt);
|
||||||
APPL_TRACE_WARNING("Pkt dropped\n");
|
APPL_TRACE_WARNING("Pkt dropped\n");
|
||||||
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
|
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
APPL_TRACE_DEBUG("btc_a2dp_sink_enque_buf + ");
|
APPL_TRACE_DEBUG("btc_a2dp_sink_enque_buf + ");
|
||||||
|
|
||||||
/* allocate and Queue this buffer */
|
// p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
|
||||||
if ((p_msg = (tBT_SBC_HDR *) osi_malloc(sizeof(tBT_SBC_HDR) +
|
fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, p_pkt, FIXED_QUEUE_MAX_TIMEOUT);
|
||||||
p_pkt->offset + p_pkt->len)) != NULL) {
|
osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
|
||||||
memcpy(p_msg, p_pkt, (sizeof(BT_HDR) + p_pkt->offset + p_pkt->len));
|
|
||||||
p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
|
|
||||||
APPL_TRACE_VERBOSE("btc_a2dp_sink_enque_buf %d + \n", p_msg->num_frames_to_be_processed);
|
|
||||||
fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, p_msg, FIXED_QUEUE_MAX_TIMEOUT);
|
|
||||||
osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
|
|
||||||
} else {
|
|
||||||
/* let caller deal with a failed allocation */
|
|
||||||
APPL_TRACE_WARNING("btc_a2dp_sink_enque_buf No Buffer left - ");
|
|
||||||
}
|
|
||||||
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
|
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,4 +738,4 @@ static void btc_a2dp_sink_thread_cleanup(UNUSED_ATTR void *context)
|
|||||||
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL;
|
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* BTC_AV_SINK_INCLUDED */
|
#endif /* (BTC_AV_SINK_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE) */
|
||||||
|
@@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/bt_target.h"
|
||||||
|
#include "common/bt_trace.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "common/bt_defs.h"
|
||||||
|
#include "osi/allocator.h"
|
||||||
|
#include "osi/mutex.h"
|
||||||
|
#include "osi/thread.h"
|
||||||
|
#include "osi/fixed_queue.h"
|
||||||
|
#include "stack/a2d_api.h"
|
||||||
|
#include "bta/bta_av_api.h"
|
||||||
|
#include "bta/bta_av_ci.h"
|
||||||
|
#include "btc_av_co.h"
|
||||||
|
#include "btc_a2dp.h"
|
||||||
|
#include "btc_a2dp_control.h"
|
||||||
|
#include "btc_a2dp_sink.h"
|
||||||
|
#include "btc/btc_manage.h"
|
||||||
|
#include "btc_av.h"
|
||||||
|
#include "btc/btc_util.h"
|
||||||
|
#include "esp_a2dp_api.h"
|
||||||
|
#include "osi/future.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if (BTC_AV_SINK_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
|
||||||
|
#define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ (25)
|
||||||
|
#define BTC_A2DP_SNK_DATA_QUEUE_IDX (1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BTC_A2DP_SINK_STATE_OFF = 0,
|
||||||
|
BTC_A2DP_SINK_STATE_ON = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BOOLEAN rx_flush; /* discards any incoming data when true */
|
||||||
|
struct osi_event *data_ready_event;
|
||||||
|
fixed_queue_t *audio_rx_q;
|
||||||
|
} tBTC_A2DP_SINK_CB;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t expected_seq_num;
|
||||||
|
bool seq_num_recount;
|
||||||
|
} a2dp_sink_media_pkt_seq_num_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tBTC_A2DP_SINK_CB btc_aa_snk_cb;
|
||||||
|
osi_thread_t *btc_aa_snk_task_hdl;
|
||||||
|
a2dp_sink_media_pkt_seq_num_t media_pkt_seq_num;
|
||||||
|
} a2dp_sink_local_param_t;
|
||||||
|
|
||||||
|
static int btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_OFF;
|
||||||
|
static esp_a2d_sink_audio_data_cb_t bt_aa_snk_audio_data_cb = NULL;
|
||||||
|
|
||||||
|
#if A2D_DYNAMIC_MEMORY == FALSE
|
||||||
|
static a2dp_sink_local_param_t a2dp_sink_local_param;
|
||||||
|
#else
|
||||||
|
static a2dp_sink_local_param_t *a2dp_sink_local_param_ptr;
|
||||||
|
#define a2dp_sink_local_param (*a2dp_sink_local_param_ptr)
|
||||||
|
#endif ///A2D_DYNAMIC_MEMORY == FALSE
|
||||||
|
|
||||||
|
static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context);
|
||||||
|
static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg);
|
||||||
|
|
||||||
|
void btc_a2dp_sink_reg_audio_data_cb(esp_a2d_sink_audio_data_cb_t callback)
|
||||||
|
{
|
||||||
|
bt_aa_snk_audio_data_cb = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void btc_a2d_audio_data_cb_to_app(uint16_t conn_hdl, uint8_t *buf, uint8_t *data, uint16_t len, uint16_t number_frame, uint32_t timestamp)
|
||||||
|
{
|
||||||
|
if (bt_aa_snk_audio_data_cb) {
|
||||||
|
/* AVDT media packet offset is larger than sizeof(esp_a2d_audio_buff_t), it safe to do this */
|
||||||
|
esp_a2d_audio_buff_t *audio_buff = (esp_a2d_audio_buff_t *)buf;
|
||||||
|
audio_buff->buff_size = len;
|
||||||
|
audio_buff->number_frame = number_frame;
|
||||||
|
audio_buff->data_len = len;
|
||||||
|
audio_buff->data = data;
|
||||||
|
audio_buff->timestamp = timestamp;
|
||||||
|
bt_aa_snk_audio_data_cb(conn_hdl, audio_buff);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
osi_free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btc_a2dp_sink_rx_flush(void)
|
||||||
|
{
|
||||||
|
while (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q)) {
|
||||||
|
osi_free(fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btc_a2dp_sink_startup(void)
|
||||||
|
{
|
||||||
|
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_OFF) {
|
||||||
|
APPL_TRACE_ERROR("a2dp sink already start up");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if A2D_DYNAMIC_MEMORY == TRUE
|
||||||
|
if ((a2dp_sink_local_param_ptr = (a2dp_sink_local_param_t *)osi_malloc(sizeof(a2dp_sink_local_param_t))) == NULL) {
|
||||||
|
APPL_TRACE_ERROR("%s malloc failed!", __func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset((void *)a2dp_sink_local_param_ptr, 0, sizeof(a2dp_sink_local_param_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_task_hdl = btc_get_current_thread();
|
||||||
|
|
||||||
|
struct osi_event *data_event = osi_event_create(btc_a2dp_sink_data_ready, NULL);
|
||||||
|
assert (data_event != NULL);
|
||||||
|
osi_event_bind(data_event, a2dp_sink_local_param.btc_aa_snk_task_hdl, BTC_A2DP_SNK_DATA_QUEUE_IDX);
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = data_event;
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||||
|
btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON;
|
||||||
|
|
||||||
|
btc_a2dp_control_init();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_sink_shutdown(void)
|
||||||
|
{
|
||||||
|
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON) {
|
||||||
|
APPL_TRACE_ERROR("a2dp sink already shutdown");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btc_a2dp_control_set_datachnl_stat(FALSE);
|
||||||
|
|
||||||
|
btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_OFF;
|
||||||
|
|
||||||
|
btc_a2dp_control_cleanup();
|
||||||
|
|
||||||
|
fixed_queue_free(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, osi_free_func);
|
||||||
|
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q = NULL;
|
||||||
|
|
||||||
|
osi_event_delete(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event);
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL;
|
||||||
|
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_task_hdl = NULL;
|
||||||
|
|
||||||
|
#if A2D_DYNAMIC_MEMORY == TRUE
|
||||||
|
osi_free(a2dp_sink_local_param_ptr);
|
||||||
|
a2dp_sink_local_param_ptr = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_sink_on_idle(void)
|
||||||
|
{
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE;
|
||||||
|
btc_a2dp_sink_rx_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_sink_on_stopped(tBTA_AV_SUSPEND *p_av)
|
||||||
|
{
|
||||||
|
UNUSED(p_av);
|
||||||
|
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE;
|
||||||
|
btc_a2dp_control_set_datachnl_stat(FALSE);
|
||||||
|
btc_a2dp_sink_rx_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_sink_on_suspended(tBTA_AV_SUSPEND *p_av)
|
||||||
|
{
|
||||||
|
UNUSED(p_av);
|
||||||
|
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE;
|
||||||
|
btc_a2dp_sink_rx_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_sink_set_rx_flush(BOOLEAN enable)
|
||||||
|
{
|
||||||
|
if (enable == FALSE) {
|
||||||
|
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = 0x1;
|
||||||
|
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = true;
|
||||||
|
}
|
||||||
|
a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = enable;
|
||||||
|
btc_a2dp_sink_rx_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
|
||||||
|
{
|
||||||
|
BT_HDR *p_msg;
|
||||||
|
int nb_of_msgs_to_process = 0;
|
||||||
|
|
||||||
|
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q)) {
|
||||||
|
if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) {
|
||||||
|
btc_a2dp_sink_rx_flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nb_of_msgs_to_process = fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q);
|
||||||
|
APPL_TRACE_DEBUG("%s nb msgs:%d", __func__, nb_of_msgs_to_process);
|
||||||
|
while (nb_of_msgs_to_process > 0) {
|
||||||
|
p_msg = (BT_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, 0);
|
||||||
|
if ( p_msg == NULL ) {
|
||||||
|
APPL_TRACE_ERROR("%s insufficient data in queue", __func__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
btc_a2dp_sink_handle_inc_media(p_msg);
|
||||||
|
nb_of_msgs_to_process--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q)) {
|
||||||
|
osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg)
|
||||||
|
{
|
||||||
|
UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
|
||||||
|
int num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
|
||||||
|
UINT32 sbc_frame_len = p_msg->len - 1;
|
||||||
|
|
||||||
|
if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush) {
|
||||||
|
osi_free(p_msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ignore data if no one is listening */
|
||||||
|
if (!btc_a2dp_control_get_datachnl_stat()) {
|
||||||
|
osi_free(p_msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_msg->layer_specific != a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num) {
|
||||||
|
/* Because the sequence number of some devices is not recounted */
|
||||||
|
if (!a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount ||
|
||||||
|
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num != 0x1) {
|
||||||
|
APPL_TRACE_WARNING("Sequence numbers error, recv:0x%x, expect:0x%x, recount:0x%x",
|
||||||
|
p_msg->layer_specific, a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num,
|
||||||
|
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = p_msg->layer_specific + 1;
|
||||||
|
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = false;
|
||||||
|
|
||||||
|
APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len);
|
||||||
|
|
||||||
|
UINT32 timestamp = *((UINT32 *) (p_msg + 1));
|
||||||
|
UINT16 conn_hdl = btc_a2d_conn_handle_get();
|
||||||
|
btc_a2d_audio_data_cb_to_app(conn_hdl, (uint8_t *)p_msg, sbc_start_frame, sbc_frame_len, num_sbc_frames, timestamp);
|
||||||
|
/* dont free p_msg here */
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt)
|
||||||
|
{
|
||||||
|
if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
|
||||||
|
osi_free(p_pkt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) {
|
||||||
|
/* Flush enabled, do not enqueue */
|
||||||
|
osi_free(p_pkt);
|
||||||
|
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q) >= MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ) {
|
||||||
|
osi_free(p_pkt);
|
||||||
|
APPL_TRACE_WARNING("Pkt dropped\n");
|
||||||
|
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q);
|
||||||
|
}
|
||||||
|
|
||||||
|
APPL_TRACE_DEBUG("btc_a2dp_sink_enque_buf + ");
|
||||||
|
|
||||||
|
// p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
|
||||||
|
fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, p_pkt, FIXED_QUEUE_MAX_TIMEOUT);
|
||||||
|
osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
|
||||||
|
|
||||||
|
return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -36,11 +36,12 @@
|
|||||||
#include "btc_av.h"
|
#include "btc_av.h"
|
||||||
#include "btc/btc_util.h"
|
#include "btc/btc_util.h"
|
||||||
#include "esp_a2dp_api.h"
|
#include "esp_a2dp_api.h"
|
||||||
#include "sbc_encoder.h"
|
|
||||||
#include "osi/future.h"
|
#include "osi/future.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#if BTC_AV_SRC_INCLUDED
|
#if (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE)
|
||||||
|
|
||||||
|
#include "sbc_encoder.h"
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** BQB global variables
|
** BQB global variables
|
||||||
@@ -83,12 +84,6 @@ enum {
|
|||||||
|
|
||||||
#define BTC_MEDIA_AA_BUF_SIZE (4096+16)
|
#define BTC_MEDIA_AA_BUF_SIZE (4096+16)
|
||||||
|
|
||||||
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
|
|
||||||
#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE + 1)
|
|
||||||
#else
|
|
||||||
#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BTC_MEDIA_BITRATE_STEP
|
#ifndef BTC_MEDIA_BITRATE_STEP
|
||||||
#define BTC_MEDIA_BITRATE_STEP 5
|
#define BTC_MEDIA_BITRATE_STEP 5
|
||||||
#endif
|
#endif
|
||||||
@@ -170,6 +165,10 @@ typedef struct {
|
|||||||
UINT64 last_frame_us;
|
UINT64 last_frame_us;
|
||||||
} a2dp_source_local_param_t;
|
} a2dp_source_local_param_t;
|
||||||
|
|
||||||
|
static BOOLEAN btc_a2dp_source_stop_audio_req(void);
|
||||||
|
static BOOLEAN btc_a2dp_source_tx_flush_req(void);
|
||||||
|
static BOOLEAN btc_a2dp_source_audio_feeding_init_req(tBTC_MEDIA_INIT_AUDIO_FEEDING *p_msg);
|
||||||
|
|
||||||
static void btc_a2dp_source_thread_init(UNUSED_ATTR void *context);
|
static void btc_a2dp_source_thread_init(UNUSED_ATTR void *context);
|
||||||
static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context);
|
static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context);
|
||||||
static void btc_a2dp_source_flush_q(fixed_queue_t *p_q);
|
static void btc_a2dp_source_flush_q(fixed_queue_t *p_q);
|
||||||
@@ -226,11 +225,6 @@ static inline void btc_aa_cb_to_app(esp_a2d_cb_event_t event, esp_a2d_cb_param_t
|
|||||||
** BTC ADAPTATION
|
** BTC ADAPTATION
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
bool btc_a2dp_source_is_streaming(void)
|
|
||||||
{
|
|
||||||
return a2dp_source_local_param.btc_aa_src_cb.is_tx_timer == TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool btc_a2dp_source_is_task_shutting_down(void)
|
bool btc_a2dp_source_is_task_shutting_down(void)
|
||||||
{
|
{
|
||||||
return btc_a2dp_source_state == BTC_A2DP_SOURCE_STATE_SHUTTING_DOWN;
|
return btc_a2dp_source_state == BTC_A2DP_SOURCE_STATE_SHUTTING_DOWN;
|
||||||
@@ -505,7 +499,7 @@ BOOLEAN btc_a2dp_source_start_audio_req(void)
|
|||||||
** Returns TRUE is success
|
** Returns TRUE is success
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BOOLEAN btc_a2dp_source_stop_audio_req(void)
|
static BOOLEAN btc_a2dp_source_stop_audio_req(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Explicitly check whether the btc_aa_src_ctrl_queue is not NULL to
|
* Explicitly check whether the btc_aa_src_ctrl_queue is not NULL to
|
||||||
@@ -536,7 +530,7 @@ BOOLEAN btc_a2dp_source_stop_audio_req(void)
|
|||||||
** Returns TRUE is success
|
** Returns TRUE is success
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg)
|
static BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg)
|
||||||
{
|
{
|
||||||
tBTC_MEDIA_INIT_AUDIO *p_buf;
|
tBTC_MEDIA_INIT_AUDIO *p_buf;
|
||||||
if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_INIT_AUDIO)))) {
|
if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_INIT_AUDIO)))) {
|
||||||
@@ -559,7 +553,7 @@ BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg)
|
|||||||
** Returns TRUE is success
|
** Returns TRUE is success
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg)
|
static BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg)
|
||||||
{
|
{
|
||||||
tBTC_MEDIA_UPDATE_AUDIO *p_buf;
|
tBTC_MEDIA_UPDATE_AUDIO *p_buf;
|
||||||
if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_UPDATE_AUDIO)))) {
|
if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_UPDATE_AUDIO)))) {
|
||||||
@@ -1451,6 +1445,7 @@ static void btc_a2dp_source_prep_2_send(UINT8 nb_frame)
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
static void btc_a2dp_source_send_aa_frame(void)
|
static void btc_a2dp_source_send_aa_frame(void)
|
||||||
{
|
{
|
||||||
|
/* if external codec is used, skip generate audio frame */
|
||||||
UINT8 nb_frame_2_send;
|
UINT8 nb_frame_2_send;
|
||||||
|
|
||||||
/* get the number of frame to send */
|
/* get the number of frame to send */
|
||||||
@@ -1461,8 +1456,8 @@ static void btc_a2dp_source_send_aa_frame(void)
|
|||||||
btc_a2dp_source_prep_2_send(nb_frame_2_send);
|
btc_a2dp_source_prep_2_send(nb_frame_2_send);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send it */
|
BTC_TRACE_VERBOSE("%s: send %d new frames", __FUNCTION__, nb_frame_2_send);
|
||||||
BTC_TRACE_VERBOSE("%s: send %d frames", __FUNCTION__, nb_frame_2_send);
|
|
||||||
bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
|
bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1539,8 +1534,8 @@ static void btc_a2dp_source_aa_stop_tx(void)
|
|||||||
when the DUT and the remote device issue SUSPEND simultaneously
|
when the DUT and the remote device issue SUSPEND simultaneously
|
||||||
and due to the processing of the SUSPEND request from the remote,
|
and due to the processing of the SUSPEND request from the remote,
|
||||||
the media path is torn down. If the A2DP HAL happens to wait
|
the media path is torn down. If the A2DP HAL happens to wait
|
||||||
for ACK for the initiated SUSPEND, it would never receive it casuing
|
for ACK for the initiated SUSPEND, it would never receive it causing
|
||||||
a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed
|
a block/wait. Due to this acknowledgement, the A2DP HAL is guaranteed
|
||||||
to get the ACK for any pending command in such cases. */
|
to get the ACK for any pending command in such cases. */
|
||||||
|
|
||||||
if (send_ack) {
|
if (send_ack) {
|
||||||
@@ -1647,4 +1642,4 @@ static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context)
|
|||||||
a2dp_source_local_param.btc_aa_src_cb.poll_data = NULL;
|
a2dp_source_local_param.btc_aa_src_cb.poll_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* BTC_AV_INCLUDED */
|
#endif /* (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE) */
|
||||||
|
@@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/bt_target.h"
|
||||||
|
#include "common/bt_trace.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "osi/allocator.h"
|
||||||
|
#include "osi/fixed_queue.h"
|
||||||
|
#include "stack/a2d_api.h"
|
||||||
|
#include "bta/bta_av_api.h"
|
||||||
|
#include "bta/bta_av_ci.h"
|
||||||
|
#include "btc/btc_manage.h"
|
||||||
|
#include "btc/btc_common.h"
|
||||||
|
#include "btc_av_co.h"
|
||||||
|
#include "btc_a2dp.h"
|
||||||
|
#include "btc_a2dp_control.h"
|
||||||
|
#include "btc_a2dp_source.h"
|
||||||
|
#include "btc_av.h"
|
||||||
|
#include "esp_a2dp_api.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
|
||||||
|
#define MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ (27)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BTC_A2DP_SOURCE_STATE_OFF = 0,
|
||||||
|
BTC_A2DP_SOURCE_STATE_ON = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BOOLEAN stream_started;
|
||||||
|
BOOLEAN tx_flush;
|
||||||
|
fixed_queue_t *audio_tx_q;
|
||||||
|
} a2dp_source_local_param_t;
|
||||||
|
|
||||||
|
static int btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_OFF;
|
||||||
|
#if A2D_DYNAMIC_MEMORY == FALSE
|
||||||
|
static a2dp_source_local_param_t a2dp_source_local_param;
|
||||||
|
#else
|
||||||
|
static a2dp_source_local_param_t *a2dp_source_local_param_ptr;
|
||||||
|
#define a2dp_source_local_param (*a2dp_source_local_param_ptr)
|
||||||
|
#endif ///A2D_DYNAMIC_MEMORY == FALSE
|
||||||
|
|
||||||
|
static inline void btc_aa_cb_to_app(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
||||||
|
{
|
||||||
|
esp_a2d_cb_t btc_aa_cb = (esp_a2d_cb_t)btc_profile_cb_get(BTC_PID_A2DP);
|
||||||
|
if (btc_aa_cb) {
|
||||||
|
btc_aa_cb(event, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btc_a2dp_source_tx_flush(void)
|
||||||
|
{
|
||||||
|
while (!fixed_queue_is_empty(a2dp_source_local_param.audio_tx_q)) {
|
||||||
|
osi_free(fixed_queue_dequeue(a2dp_source_local_param.audio_tx_q, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btc_a2dp_source_tx_stop(void)
|
||||||
|
{
|
||||||
|
if (a2dp_source_local_param.stream_started == TRUE) {
|
||||||
|
a2dp_source_local_param.stream_started = FALSE;
|
||||||
|
/* ack to command */
|
||||||
|
btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* flush tx queue */
|
||||||
|
btc_a2dp_source_tx_flush();
|
||||||
|
a2dp_source_local_param.tx_flush = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN btc_a2dp_source_enqueue_audio_frame(BT_HDR *p_buf)
|
||||||
|
{
|
||||||
|
if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON) {
|
||||||
|
APPL_TRACE_WARNING("%s source not start up", __func__);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a2dp_source_local_param.tx_flush) {
|
||||||
|
APPL_TRACE_WARNING("%s try to send data when tx flush enable", __func__);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixed_queue_length(a2dp_source_local_param.audio_tx_q) > MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ) {
|
||||||
|
APPL_TRACE_WARNING("%s audio tx queue overflow: %d", __func__, fixed_queue_length(a2dp_source_local_param.audio_tx_q));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed_queue_enqueue(a2dp_source_local_param.audio_tx_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
|
||||||
|
bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_source_report_delay_value(UINT16 delay_value)
|
||||||
|
{
|
||||||
|
esp_a2d_cb_param_t param;
|
||||||
|
|
||||||
|
if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
param.a2d_report_delay_value_stat.delay_value = delay_value;
|
||||||
|
|
||||||
|
btc_aa_cb_to_app(ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT, ¶m);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN btc_a2dp_source_start_audio_req(void)
|
||||||
|
{
|
||||||
|
a2dp_source_local_param.stream_started = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_HDR *btc_a2dp_source_audio_readbuf(void)
|
||||||
|
{
|
||||||
|
if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON || a2dp_source_local_param.tx_flush){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return fixed_queue_dequeue(a2dp_source_local_param.audio_tx_q, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_source_set_tx_flush(BOOLEAN enable)
|
||||||
|
{
|
||||||
|
a2dp_source_local_param.tx_flush = enable;
|
||||||
|
if (enable) {
|
||||||
|
btc_a2dp_source_tx_flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av)
|
||||||
|
{
|
||||||
|
/* check for status failures */
|
||||||
|
if (p_av->status != BTA_AV_SUCCESS) {
|
||||||
|
if (p_av->initiator == TRUE) {
|
||||||
|
btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stop tx, ack to cmd, flush tx queue */
|
||||||
|
btc_a2dp_source_tx_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_source_on_stopped(tBTA_AV_SUSPEND *p_av)
|
||||||
|
{
|
||||||
|
/* allow using this api for other than suspend */
|
||||||
|
if (p_av != NULL) {
|
||||||
|
if (p_av->status != BTA_AV_SUCCESS) {
|
||||||
|
if (p_av->initiator) {
|
||||||
|
btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stop tx, ack to cmd, flush tx queue */
|
||||||
|
btc_a2dp_source_tx_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_source_on_idle(void)
|
||||||
|
{
|
||||||
|
/* stop tx, ack to cmd, flush tx queue */
|
||||||
|
btc_a2dp_source_tx_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btc_a2dp_source_is_task_shutting_down(void)
|
||||||
|
{
|
||||||
|
/* always return false, remove this api when internal codec is remove */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool btc_a2dp_source_startup(void)
|
||||||
|
{
|
||||||
|
if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_OFF) {
|
||||||
|
APPL_TRACE_ERROR("%s A2DP source already start up", __func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if A2D_DYNAMIC_MEMORY == TRUE
|
||||||
|
if ((a2dp_source_local_param_ptr = (a2dp_source_local_param_t *)osi_malloc(sizeof(a2dp_source_local_param_t))) == NULL) {
|
||||||
|
APPL_TRACE_ERROR("%s malloc failed!", __func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset((void *)a2dp_source_local_param_ptr, 0, sizeof(a2dp_source_local_param_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_ON;
|
||||||
|
|
||||||
|
a2dp_source_local_param.audio_tx_q = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||||
|
if(a2dp_source_local_param.audio_tx_q == NULL) {
|
||||||
|
goto error_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
btc_a2dp_control_init();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error_exit:;
|
||||||
|
APPL_TRACE_ERROR("%s A2DP source start up failed", __func__);
|
||||||
|
|
||||||
|
#if A2D_DYNAMIC_MEMORY == TRUE
|
||||||
|
osi_free(a2dp_source_local_param_ptr);
|
||||||
|
a2dp_source_local_param_ptr = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_a2dp_source_shutdown(void)
|
||||||
|
{
|
||||||
|
if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON) {
|
||||||
|
APPL_TRACE_ERROR("%s A2DP source already shutdown", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_OFF;
|
||||||
|
|
||||||
|
btc_a2dp_control_cleanup();
|
||||||
|
|
||||||
|
fixed_queue_free(a2dp_source_local_param.audio_tx_q, osi_free_func);
|
||||||
|
|
||||||
|
a2dp_source_local_param.audio_tx_q = NULL;
|
||||||
|
a2dp_source_local_param.tx_flush = FALSE;
|
||||||
|
a2dp_source_local_param.stream_started = FALSE;
|
||||||
|
|
||||||
|
#if A2D_DYNAMIC_MEMORY == TRUE
|
||||||
|
osi_free(a2dp_source_local_param_ptr);
|
||||||
|
a2dp_source_local_param_ptr = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == TRUE) */
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "btc/btc_common.h"
|
#include "btc/btc_common.h"
|
||||||
#include "btc/btc_manage.h"
|
#include "btc/btc_manage.h"
|
||||||
#include "btc_av.h"
|
#include "btc_av.h"
|
||||||
|
#include "btc_av_co.h"
|
||||||
#include "btc_avrc.h"
|
#include "btc_avrc.h"
|
||||||
#include "btc/btc_util.h"
|
#include "btc/btc_util.h"
|
||||||
#include "btc/btc_profile_queue.h"
|
#include "btc/btc_profile_queue.h"
|
||||||
@@ -46,6 +47,9 @@ bool g_a2dp_source_ongoing_deinit;
|
|||||||
bool g_a2dp_sink_ongoing_deinit;
|
bool g_a2dp_sink_ongoing_deinit;
|
||||||
|
|
||||||
|
|
||||||
|
/* reserve some bytes for media payload header (currently, only SBC, 1 byte) */
|
||||||
|
#define BTC_AV_AUDIO_MTU_RESERVE 1
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Constants & Macros
|
** Constants & Macros
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -74,6 +78,9 @@ typedef enum {
|
|||||||
#define BTC_AV_FLAG_PENDING_START 0x4
|
#define BTC_AV_FLAG_PENDING_START 0x4
|
||||||
#define BTC_AV_FLAG_PENDING_STOP 0x8
|
#define BTC_AV_FLAG_PENDING_STOP 0x8
|
||||||
|
|
||||||
|
#define BTC_AV_SBC_CIE_OFFSET 3
|
||||||
|
#define BTC_AV_SBC_CIE_LEN 4
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Local type definitions
|
** Local type definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -81,11 +88,13 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int service_id;
|
int service_id;
|
||||||
tBTA_AV_HNDL bta_handle;
|
tBTA_AV_HNDL bta_handle;
|
||||||
|
UINT16 mtu;
|
||||||
bt_bdaddr_t peer_bda;
|
bt_bdaddr_t peer_bda;
|
||||||
btc_sm_handle_t sm_handle;
|
btc_sm_handle_t sm_handle;
|
||||||
UINT8 flags;
|
UINT8 flags;
|
||||||
tBTA_AV_EDR edr;
|
tBTA_AV_EDR edr;
|
||||||
UINT8 peer_sep; /* sep type of peer device */
|
UINT8 peer_sep; /* sep type of peer device */
|
||||||
|
tBTC_AV_CODEC_INFO codec_caps;
|
||||||
#if BTC_AV_SRC_INCLUDED
|
#if BTC_AV_SRC_INCLUDED
|
||||||
osi_alarm_t *tle_av_open_on_rc;
|
osi_alarm_t *tle_av_open_on_rc;
|
||||||
#endif /* BTC_AV_SRC_INCLUDED */
|
#endif /* BTC_AV_SRC_INCLUDED */
|
||||||
@@ -170,6 +179,7 @@ static void btc_av_event_free_data(btc_msg_t *msg);
|
|||||||
|
|
||||||
extern tBTA_AV_CO_FUNCTS bta_av_a2d_cos;
|
extern tBTA_AV_CO_FUNCTS bta_av_a2d_cos;
|
||||||
extern tBTA_AVRC_CO_FUNCTS bta_avrc_cos;
|
extern tBTA_AVRC_CO_FUNCTS bta_avrc_cos;
|
||||||
|
extern tA2D_SBC_CIE btc_av_sbc_default_config;
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Local helper functions
|
** Local helper functions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -222,7 +232,7 @@ UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event)
|
|||||||
CASE_RETURN_STR(BTC_AV_DISCONNECT_REQ_EVT)
|
CASE_RETURN_STR(BTC_AV_DISCONNECT_REQ_EVT)
|
||||||
CASE_RETURN_STR(BTC_AV_START_STREAM_REQ_EVT)
|
CASE_RETURN_STR(BTC_AV_START_STREAM_REQ_EVT)
|
||||||
CASE_RETURN_STR(BTC_AV_SUSPEND_STREAM_REQ_EVT)
|
CASE_RETURN_STR(BTC_AV_SUSPEND_STREAM_REQ_EVT)
|
||||||
CASE_RETURN_STR(BTC_AV_SINK_CONFIG_REQ_EVT)
|
CASE_RETURN_STR(BTC_AV_CONFIG_EVT)
|
||||||
default: return "UNKNOWN_EVENT";
|
default: return "UNKNOWN_EVENT";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,7 +273,7 @@ static void btc_initiate_av_open_tmr_hdlr(void *arg)
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Static functions
|
** Static functions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static void btc_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr, int disc_rsn)
|
static void btc_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr, uint16_t mtu, int disc_rsn)
|
||||||
{
|
{
|
||||||
// todo: add callback for SRC
|
// todo: add callback for SRC
|
||||||
esp_a2d_cb_param_t param;
|
esp_a2d_cb_param_t param;
|
||||||
@@ -272,8 +282,15 @@ static void btc_report_connection_state(esp_a2d_connection_state_t state, bt_bda
|
|||||||
param.conn_stat.state = state;
|
param.conn_stat.state = state;
|
||||||
if (bd_addr) {
|
if (bd_addr) {
|
||||||
memcpy(param.conn_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
|
memcpy(param.conn_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
|
||||||
|
if (memcmp(bd_addr, &(btc_av_cb.peer_bda), sizeof(bt_bdaddr_t)) == 0) {
|
||||||
|
param.conn_stat.conn_hdl = btc_av_cb.bta_handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
|
if (state == ESP_A2D_CONNECTION_STATE_CONNECTED) {
|
||||||
|
param.conn_stat.audio_mtu = mtu;
|
||||||
|
btc_av_cb.mtu = mtu;
|
||||||
|
}
|
||||||
|
else if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
|
||||||
param.conn_stat.disc_rsn = (disc_rsn == 0) ? ESP_A2D_DISC_RSN_NORMAL :
|
param.conn_stat.disc_rsn = (disc_rsn == 0) ? ESP_A2D_DISC_RSN_NORMAL :
|
||||||
ESP_A2D_DISC_RSN_ABNORMAL;
|
ESP_A2D_DISC_RSN_ABNORMAL;
|
||||||
}
|
}
|
||||||
@@ -289,6 +306,9 @@ static void btc_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_
|
|||||||
param.audio_stat.state = state;
|
param.audio_stat.state = state;
|
||||||
if (bd_addr) {
|
if (bd_addr) {
|
||||||
memcpy(param.audio_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
|
memcpy(param.audio_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
|
||||||
|
if (memcmp(bd_addr, &(btc_av_cb.peer_bda), sizeof(bt_bdaddr_t)) == 0) {
|
||||||
|
param.audio_stat.conn_hdl = btc_av_cb.bta_handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
btc_a2d_cb_to_app(ESP_A2D_AUDIO_STATE_EVT, ¶m);
|
btc_a2d_cb_to_app(ESP_A2D_AUDIO_STATE_EVT, ¶m);
|
||||||
}
|
}
|
||||||
@@ -328,6 +348,12 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
|
|||||||
case BTA_AV_REGISTER_EVT:
|
case BTA_AV_REGISTER_EVT:
|
||||||
btc_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl;
|
btc_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl;
|
||||||
break;
|
break;
|
||||||
|
case BTA_AV_SEP_REG_EVT:
|
||||||
|
param.a2d_sep_reg_stat.seid = ((tBTA_AV *)p_data)->sep_reg.seid;
|
||||||
|
param.a2d_sep_reg_stat.reg_state = (((tBTA_AV *)p_data)->sep_reg.reg_state == BTA_AV_SUCCESS) ? ESP_A2D_SEP_REG_SUCCESS :
|
||||||
|
ESP_A2D_SEP_REG_FAIL;
|
||||||
|
btc_a2d_cb_to_app(ESP_A2D_SEP_REG_STATE_EVT, ¶m);
|
||||||
|
break;
|
||||||
|
|
||||||
case BTA_AV_PENDING_EVT:
|
case BTA_AV_PENDING_EVT:
|
||||||
case BTC_AV_CONNECT_REQ_EVT: {
|
case BTC_AV_CONNECT_REQ_EVT: {
|
||||||
@@ -358,7 +384,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
|
|||||||
|
|
||||||
case BTC_AV_DISCONNECT_REQ_EVT:
|
case BTC_AV_DISCONNECT_REQ_EVT:
|
||||||
BTC_TRACE_WARNING("No Link At All.");
|
BTC_TRACE_WARNING("No Link At All.");
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0);
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTA_AV_RC_OPEN_EVT:
|
case BTA_AV_RC_OPEN_EVT:
|
||||||
@@ -448,7 +474,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
|
|||||||
switch (event) {
|
switch (event) {
|
||||||
case BTC_SM_ENTER_EVT:
|
case BTC_SM_ENTER_EVT:
|
||||||
/* inform the application that we are entering connecting state */
|
/* inform the application that we are entering connecting state */
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btc_av_cb.peer_bda), 0);
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btc_av_cb.peer_bda), 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTC_SM_EXIT_EVT:
|
case BTC_SM_EXIT_EVT:
|
||||||
@@ -456,7 +482,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
|
|||||||
|
|
||||||
case BTA_AV_REJECT_EVT:
|
case BTA_AV_REJECT_EVT:
|
||||||
BTC_TRACE_WARNING(" Received BTA_AV_REJECT_EVT \n");
|
BTC_TRACE_WARNING(" Received BTA_AV_REJECT_EVT \n");
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0);
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0, 0);
|
||||||
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
|
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -464,13 +490,14 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
|
|||||||
tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
|
tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
|
||||||
esp_a2d_connection_state_t conn_stat;
|
esp_a2d_connection_state_t conn_stat;
|
||||||
btc_sm_state_t av_state;
|
btc_sm_state_t av_state;
|
||||||
|
uint16_t mtu = 0;
|
||||||
BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status,
|
BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status,
|
||||||
p_bta_data->open.edr, p_bta_data->open.sep);
|
p_bta_data->open.edr, p_bta_data->open.sep);
|
||||||
|
|
||||||
if (p_bta_data->open.status == BTA_AV_SUCCESS) {
|
if (p_bta_data->open.status == BTA_AV_SUCCESS) {
|
||||||
btc_av_cb.edr = p_bta_data->open.edr;
|
btc_av_cb.edr = p_bta_data->open.edr;
|
||||||
btc_av_cb.peer_sep = p_bta_data->open.sep;
|
btc_av_cb.peer_sep = p_bta_data->open.sep;
|
||||||
|
mtu = p_bta_data->open.mtu - BTC_AV_AUDIO_MTU_RESERVE;
|
||||||
conn_stat = ESP_A2D_CONNECTION_STATE_CONNECTED;
|
conn_stat = ESP_A2D_CONNECTION_STATE_CONNECTED;
|
||||||
av_state = BTC_AV_STATE_OPENED;
|
av_state = BTC_AV_STATE_OPENED;
|
||||||
} else {
|
} else {
|
||||||
@@ -480,7 +507,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
|
|||||||
av_state = BTC_AV_STATE_IDLE;
|
av_state = BTC_AV_STATE_IDLE;
|
||||||
}
|
}
|
||||||
/* inform the application of the event */
|
/* inform the application of the event */
|
||||||
btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), 0);
|
btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), mtu, 0);
|
||||||
/* change state to open/idle based on the status */
|
/* change state to open/idle based on the status */
|
||||||
btc_sm_change_state(btc_av_cb.sm_handle, av_state);
|
btc_sm_change_state(btc_av_cb.sm_handle, av_state);
|
||||||
|
|
||||||
@@ -502,13 +529,12 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
|
|||||||
btc_queue_advance();
|
btc_queue_advance();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BTC_AV_SINK_CONFIG_REQ_EVT: {
|
case BTC_AV_CONFIG_EVT: {
|
||||||
if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
|
esp_a2d_cb_param_t param;
|
||||||
esp_a2d_cb_param_t param;
|
param.audio_cfg.conn_hdl = btc_av_cb.bta_handle;
|
||||||
memcpy(param.audio_cfg.remote_bda, &btc_av_cb.peer_bda, sizeof(esp_bd_addr_t));
|
memcpy(param.audio_cfg.remote_bda, &btc_av_cb.peer_bda, sizeof(esp_bd_addr_t));
|
||||||
memcpy(¶m.audio_cfg.mcc, p_data, sizeof(esp_a2d_mcc_t));
|
memcpy(¶m.audio_cfg.mcc, p_data, sizeof(esp_a2d_mcc_t));
|
||||||
btc_a2d_cb_to_app(ESP_A2D_AUDIO_CFG_EVT, ¶m);
|
btc_a2d_cb_to_app(ESP_A2D_AUDIO_CFG_EVT, ¶m);
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BTC_AV_CONNECT_REQ_EVT:
|
case BTC_AV_CONNECT_REQ_EVT:
|
||||||
@@ -520,7 +546,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
BTC_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__);
|
BTC_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__);
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0);
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0, 0);
|
||||||
btc_queue_advance();
|
btc_queue_advance();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -623,7 +649,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
|
|||||||
case BTA_AV_CLOSE_EVT: {
|
case BTA_AV_CLOSE_EVT: {
|
||||||
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
|
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
|
||||||
/* inform the application that we are disconnecting */
|
/* inform the application that we are disconnecting */
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn);
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0, close->disc_rsn);
|
||||||
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
|
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -693,7 +719,9 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
|
|||||||
case BTC_AV_START_STREAM_REQ_EVT:
|
case BTC_AV_START_STREAM_REQ_EVT:
|
||||||
#if BTC_AV_SRC_INCLUDED
|
#if BTC_AV_SRC_INCLUDED
|
||||||
if (btc_av_cb.peer_sep != AVDT_TSEP_SRC) {
|
if (btc_av_cb.peer_sep != AVDT_TSEP_SRC) {
|
||||||
|
#if (BTC_AV_EXT_CODEC == FALSE)
|
||||||
btc_a2dp_source_setup_codec();
|
btc_a2dp_source_setup_codec();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* BTC_AV_SRC_INCLUDED */
|
#endif /* BTC_AV_SRC_INCLUDED */
|
||||||
BTA_AvStart();
|
BTA_AvStart();
|
||||||
@@ -759,7 +787,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* inform the application that we are disconnecting */
|
/* inform the application that we are disconnecting */
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTA_AV_CLOSE_EVT: {
|
case BTA_AV_CLOSE_EVT: {
|
||||||
@@ -767,7 +795,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
|
|||||||
btc_a2dp_on_stopped(NULL);
|
btc_a2dp_on_stopped(NULL);
|
||||||
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
|
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
|
||||||
/* inform the application that we are disconnected */
|
/* inform the application that we are disconnected */
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0,
|
||||||
close->disc_rsn);
|
close->disc_rsn);
|
||||||
|
|
||||||
if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
|
if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
|
||||||
@@ -804,7 +832,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
|
|||||||
} else {
|
} else {
|
||||||
BTC_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__);
|
BTC_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__);
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED,
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED,
|
||||||
(bt_bdaddr_t *)p_data, ESP_A2D_DISC_RSN_NORMAL);
|
(bt_bdaddr_t *)p_data, 0, ESP_A2D_DISC_RSN_NORMAL);
|
||||||
}
|
}
|
||||||
btc_queue_advance();
|
btc_queue_advance();
|
||||||
break;
|
break;
|
||||||
@@ -917,7 +945,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* inform the application that we are disconnecting */
|
/* inform the application that we are disconnecting */
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0, 0);
|
||||||
|
|
||||||
/* wait in closing state until fully closed */
|
/* wait in closing state until fully closed */
|
||||||
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
|
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
|
||||||
@@ -982,7 +1010,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
|
|||||||
btc_a2dp_on_stopped(NULL);
|
btc_a2dp_on_stopped(NULL);
|
||||||
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
|
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
|
||||||
/* inform the application that we are disconnected */
|
/* inform the application that we are disconnected */
|
||||||
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
|
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0,
|
||||||
close->disc_rsn);
|
close->disc_rsn);
|
||||||
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
|
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
|
||||||
|
|
||||||
@@ -1337,7 +1365,7 @@ static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BTC_AV_SINK_INCLUDED
|
#if BTC_AV_SINK_INCLUDED
|
||||||
static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
static void bte_av_media_sink_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
||||||
{
|
{
|
||||||
btc_sm_state_t state;
|
btc_sm_state_t state;
|
||||||
UINT8 que_len;
|
UINT8 que_len;
|
||||||
@@ -1351,13 +1379,16 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
|||||||
que_len = btc_a2dp_sink_enque_buf((BT_HDR *)p_data);
|
que_len = btc_a2dp_sink_enque_buf((BT_HDR *)p_data);
|
||||||
BTC_TRACE_DEBUG(" Packets in Que %d\n", que_len);
|
BTC_TRACE_DEBUG(" Packets in Que %d\n", que_len);
|
||||||
} else {
|
} else {
|
||||||
|
osi_free(p_data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == BTA_AV_MEDIA_SINK_CFG_EVT) {
|
if (event == BTA_AV_MEDIA_CFG_EVT) {
|
||||||
|
#if (BTC_AV_EXT_CODEC == FALSE)
|
||||||
/* send a command to BT Media Task */
|
/* send a command to BT Media Task */
|
||||||
btc_a2dp_sink_reset_decoder((UINT8 *)p_data);
|
btc_a2dp_sink_reset_decoder((UINT8 *)p_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* currently only supports SBC */
|
/* currently only supports SBC */
|
||||||
a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE);
|
a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE);
|
||||||
@@ -1367,11 +1398,11 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
|||||||
|
|
||||||
msg.sig = BTC_SIG_API_CB;
|
msg.sig = BTC_SIG_API_CB;
|
||||||
msg.pid = BTC_PID_A2DP;
|
msg.pid = BTC_PID_A2DP;
|
||||||
msg.act = BTC_AV_SINK_CONFIG_REQ_EVT;
|
msg.act = BTC_AV_CONFIG_EVT;
|
||||||
|
|
||||||
memset(&arg, 0, sizeof(btc_av_args_t));
|
memset(&arg, 0, sizeof(btc_av_args_t));
|
||||||
arg.mcc.type = ESP_A2D_MCT_SBC;
|
arg.mcc.type = ESP_A2D_MCT_SBC;
|
||||||
memcpy(arg.mcc.cie.sbc, (uint8_t *)p_data + 3, ESP_A2D_CIE_LEN_SBC);
|
memcpy(&arg.mcc.cie.sbc_info, (uint8_t *)p_data + BTC_AV_SBC_CIE_OFFSET, BTC_AV_SBC_CIE_LEN);
|
||||||
btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
|
btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
BTC_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
|
BTC_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
|
||||||
@@ -1380,7 +1411,7 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
|||||||
UNUSED(que_len);
|
UNUSED(que_len);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
static void bte_av_media_sink_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
||||||
{
|
{
|
||||||
UNUSED(event);
|
UNUSED(event);
|
||||||
UNUSED(p_data);
|
UNUSED(p_data);
|
||||||
@@ -1388,6 +1419,82 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BTC_AV_SRC_INCLUDED
|
||||||
|
static void bte_av_media_source_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
||||||
|
{
|
||||||
|
tA2D_STATUS a2d_status;
|
||||||
|
tA2D_SBC_CIE sbc_cie;
|
||||||
|
|
||||||
|
if (event == BTA_AV_MEDIA_CFG_EVT) {
|
||||||
|
/* currently only supports SBC */
|
||||||
|
a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE);
|
||||||
|
if (a2d_status == A2D_SUCCESS) {
|
||||||
|
btc_msg_t msg;
|
||||||
|
btc_av_args_t arg;
|
||||||
|
|
||||||
|
msg.sig = BTC_SIG_API_CB;
|
||||||
|
msg.pid = BTC_PID_A2DP;
|
||||||
|
msg.act = BTC_AV_CONFIG_EVT;
|
||||||
|
|
||||||
|
memset(&arg, 0, sizeof(btc_av_args_t));
|
||||||
|
arg.mcc.type = ESP_A2D_MCT_SBC;
|
||||||
|
memcpy(&arg.mcc.cie.sbc_info, (uint8_t *)p_data + BTC_AV_SBC_CIE_OFFSET, BTC_AV_SBC_CIE_LEN);
|
||||||
|
btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
|
||||||
|
} else {
|
||||||
|
BTC_TRACE_ERROR("A2D_ParsSbcInfo fail:%d\n", a2d_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void bte_av_media_source_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(event);
|
||||||
|
UNUSED(p_data);
|
||||||
|
BTC_TRACE_WARNING("%s : event %u\n", __func__, event);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
|
||||||
|
tBTC_AV_CODEC_INFO *btc_av_codec_cap_get(void)
|
||||||
|
{
|
||||||
|
return &btc_av_cb.codec_caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btc_av_reg_sep(uint8_t tsep, uint8_t seid, esp_a2d_mcc_t *mcc)
|
||||||
|
{
|
||||||
|
tBTA_AV_DATA_CBACK *p_data_cback = NULL;
|
||||||
|
esp_a2d_cb_param_t param;
|
||||||
|
|
||||||
|
param.a2d_sep_reg_stat.seid = seid;
|
||||||
|
if (btc_av_cb.sm_handle == NULL || btc_sm_get_state(btc_av_cb.sm_handle) != BTC_AV_STATE_IDLE) {
|
||||||
|
param.a2d_sep_reg_stat.reg_state = ESP_A2D_SEP_REG_INVALID_STATE;
|
||||||
|
btc_a2d_cb_to_app(ESP_A2D_SEP_REG_STATE_EVT, ¶m);
|
||||||
|
BTC_TRACE_WARNING("%s: try to reg sep when a2dp not init or connected", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcc->type == ESP_A2D_MCT_SBC) {
|
||||||
|
A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btc_av_sbc_default_config, btc_av_cb.codec_caps.info);
|
||||||
|
/* overwrite sbc cie */
|
||||||
|
memcpy(btc_av_cb.codec_caps.info + A2D_SBC_CIE_OFF, &mcc->cie, A2D_SBC_CIE_LEN);
|
||||||
|
|
||||||
|
if (tsep == AVDT_TSEP_SNK) {
|
||||||
|
p_data_cback = bte_av_media_sink_callback;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p_data_cback = bte_av_media_source_callback;
|
||||||
|
}
|
||||||
|
BTA_AvRegSEP(BTA_AV_CHNL_AUDIO, seid, tsep, BTA_AV_CODEC_SBC, btc_av_cb.codec_caps.info, p_data_cback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
param.a2d_sep_reg_stat.reg_state = ESP_A2D_SEP_REG_UNSUPPORTED;
|
||||||
|
btc_a2d_cb_to_app(ESP_A2D_SEP_REG_STATE_EVT, ¶m);
|
||||||
|
BTC_TRACE_WARNING("%s: unsupported codec type %d", __func__, mcc->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function btc_av_execute_service
|
** Function btc_av_execute_service
|
||||||
@@ -1399,7 +1506,15 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
|
bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
|
||||||
{
|
{
|
||||||
|
tBTA_AV_DATA_CBACK *p_data_cback = NULL;
|
||||||
|
|
||||||
if (b_enable) {
|
if (b_enable) {
|
||||||
|
if (tsep == AVDT_TSEP_SNK) {
|
||||||
|
p_data_cback = bte_av_media_sink_callback;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p_data_cback = bte_av_media_source_callback;
|
||||||
|
}
|
||||||
/* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
|
/* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
|
||||||
* handle this request in order to allow incoming connections to succeed.
|
* handle this request in order to allow incoming connections to succeed.
|
||||||
* We need to put this back once support for this is added */
|
* We need to put this back once support for this is added */
|
||||||
@@ -1413,11 +1528,11 @@ bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
|
|||||||
BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
|
BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
|
||||||
BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_DELAY_RPT,
|
BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_DELAY_RPT,
|
||||||
bte_av_callback);
|
bte_av_callback);
|
||||||
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, &bta_avrc_cos, tsep);
|
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, p_data_cback, &bta_av_a2d_cos, &bta_avrc_cos, tsep);
|
||||||
} else {
|
} else {
|
||||||
BTC_TRACE_WARNING("A2DP Enable without AVRC")
|
BTC_TRACE_WARNING("A2DP Enable without AVRC")
|
||||||
BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_DELAY_RPT, bte_av_callback);
|
BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_DELAY_RPT, bte_av_callback);
|
||||||
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, NULL, tsep);
|
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, p_data_cback, &bta_av_a2d_cos, NULL, tsep);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BTA_AvDeregister(btc_av_cb.bta_handle);
|
BTA_AvDeregister(btc_av_cb.bta_handle);
|
||||||
@@ -1476,6 +1591,11 @@ BOOLEAN btc_av_is_connected(void)
|
|||||||
return ((state == BTC_AV_STATE_OPENED) || (state == BTC_AV_STATE_STARTED));
|
return ((state == BTC_AV_STATE_OPENED) || (state == BTC_AV_STATE_STARTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN btc_av_is_started(void)
|
||||||
|
{
|
||||||
|
return ((btc_sm_get_state(btc_av_cb.sm_handle) == BTC_AV_STATE_STARTED));
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* Function btc_av_get_service_id
|
* Function btc_av_get_service_id
|
||||||
@@ -1548,15 +1668,17 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
|
|||||||
btc_av_args_t *arg = (btc_av_args_t *)(msg->arg);
|
btc_av_args_t *arg = (btc_av_args_t *)(msg->arg);
|
||||||
switch (msg->act) {
|
switch (msg->act) {
|
||||||
#if BTC_AV_SINK_INCLUDED
|
#if BTC_AV_SINK_INCLUDED
|
||||||
case BTC_AV_SINK_CONFIG_REQ_EVT: {
|
|
||||||
btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (void *)(msg->arg));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BTC_AV_SINK_API_INIT_EVT: {
|
case BTC_AV_SINK_API_INIT_EVT: {
|
||||||
btc_a2d_sink_init();
|
btc_a2d_sink_init();
|
||||||
// todo: callback to application
|
// todo: callback to application
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
case BTC_AV_SINK_API_REG_SEP_EVT: {
|
||||||
|
btc_av_reg_sep(AVDT_TSEP_SNK, arg->reg_sep.seid, &arg->reg_sep.mcc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
case BTC_AV_SINK_API_DEINIT_EVT: {
|
case BTC_AV_SINK_API_DEINIT_EVT: {
|
||||||
btc_a2d_sink_deinit();
|
btc_a2d_sink_deinit();
|
||||||
// todo: callback to application
|
// todo: callback to application
|
||||||
@@ -1574,10 +1696,17 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
|
|||||||
btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
|
btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
case BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT: {
|
||||||
|
btc_a2dp_sink_reg_audio_data_cb(arg->audio_data_cb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
case BTC_AV_SINK_API_REG_DATA_CB_EVT: {
|
case BTC_AV_SINK_API_REG_DATA_CB_EVT: {
|
||||||
btc_a2dp_sink_reg_data_cb(arg->data_cb);
|
btc_a2dp_sink_reg_data_cb(arg->data_cb);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
case BTC_AV_SINK_API_SET_DELAY_VALUE_EVT: {
|
case BTC_AV_SINK_API_SET_DELAY_VALUE_EVT: {
|
||||||
btc_a2d_sink_set_delay_value(arg->delay_value);
|
btc_a2d_sink_set_delay_value(arg->delay_value);
|
||||||
break;
|
break;
|
||||||
@@ -1592,6 +1721,12 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
|
|||||||
btc_a2d_src_init();
|
btc_a2d_src_init();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
case BTC_AV_SRC_API_REG_SEP_EVT: {
|
||||||
|
btc_av_reg_sep(AVDT_TSEP_SRC, arg->reg_sep.seid, &arg->reg_sep.mcc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
case BTC_AV_SRC_API_DEINIT_EVT: {
|
case BTC_AV_SRC_API_DEINIT_EVT: {
|
||||||
btc_a2d_src_deinit();
|
btc_a2d_src_deinit();
|
||||||
break;
|
break;
|
||||||
@@ -1607,10 +1742,12 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
|
|||||||
btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
|
btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if (BTC_AV_EXT_CODEC == FALSE)
|
||||||
case BTC_AV_SRC_API_REG_DATA_CB_EVT: {
|
case BTC_AV_SRC_API_REG_DATA_CB_EVT: {
|
||||||
btc_a2dp_src_reg_data_cb(arg->src_data_cb);
|
btc_a2dp_src_reg_data_cb(arg->src_data_cb);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif /* BTC_AV_SRC_INCLUDED */
|
#endif /* BTC_AV_SRC_INCLUDED */
|
||||||
case BTC_AV_API_MEDIA_CTRL_EVT: {
|
case BTC_AV_API_MEDIA_CTRL_EVT: {
|
||||||
btc_a2dp_control_media_ctrl(arg->ctrl);
|
btc_a2dp_control_media_ctrl(arg->ctrl);
|
||||||
@@ -1734,6 +1871,56 @@ static bt_status_t btc_a2d_src_connect(bt_bdaddr_t *remote_bda)
|
|||||||
return btc_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, remote_bda, connect_int);
|
return btc_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, remote_bda, connect_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN btc_a2d_src_audio_mtu_check(uint16_t data_len)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (data_len <= btc_av_cb.mtu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_status_t btc_a2d_src_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf)
|
||||||
|
{
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
if (conn_hdl != btc_av_cb.bta_handle) {
|
||||||
|
return BT_STATUS_FAIL;
|
||||||
|
}
|
||||||
|
BT_HDR *p_buf = (BT_HDR *)audio_buf;
|
||||||
|
assert(audio_buf->data - (UINT8 *)(p_buf + 1) >= BTC_AUDIO_BUFF_OFFSET);
|
||||||
|
/* since p_buf and audio_buf point to the same memory, backup those value before modify p_buf */
|
||||||
|
uint16_t number_frame = audio_buf->number_frame;
|
||||||
|
uint16_t data_len = audio_buf->data_len;
|
||||||
|
uint32_t timestamp = audio_buf->timestamp;
|
||||||
|
p_buf->offset = audio_buf->data - (UINT8 *)(p_buf + 1);
|
||||||
|
p_buf->layer_specific = number_frame;
|
||||||
|
p_buf->len = data_len;
|
||||||
|
*((UINT32 *) (p_buf + 1)) = timestamp;
|
||||||
|
|
||||||
|
if (btc_a2dp_source_enqueue_audio_frame(p_buf)) {
|
||||||
|
return BT_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return BT_STATUS_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* BTC_AV_SRC_INCLUDED */
|
#endif /* BTC_AV_SRC_INCLUDED */
|
||||||
|
|
||||||
|
uint16_t btc_a2d_conn_handle_get(void)
|
||||||
|
{
|
||||||
|
return btc_av_cb.bta_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_av_audio_buff_alloc(uint16_t size, uint8_t **pp_buff, uint8_t **pp_data)
|
||||||
|
{
|
||||||
|
/* todo */
|
||||||
|
BT_HDR *p_buf= (BT_HDR *)osi_calloc(sizeof(BT_HDR) + BTC_AUDIO_BUFF_OFFSET + size);
|
||||||
|
if (p_buf != NULL) {
|
||||||
|
*pp_buff = (uint8_t *)p_buf;
|
||||||
|
*pp_data = (uint8_t *)(p_buf + 1) + BTC_AUDIO_BUFF_OFFSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void btc_av_audio_buff_free(uint8_t *p_buf)
|
||||||
|
{
|
||||||
|
osi_free(p_buf);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* #if BTC_AV_INCLUDED */
|
#endif /* #if BTC_AV_INCLUDED */
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -64,6 +64,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
/* Connected peer information */
|
/* Connected peer information */
|
||||||
tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
|
tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
|
||||||
|
tBTC_AV_CODEC_INFO codec_caps;
|
||||||
/* Current codec configuration - access to this variable must be protected */
|
/* Current codec configuration - access to this variable must be protected */
|
||||||
tBTC_AV_CODEC_INFO codec_cfg;
|
tBTC_AV_CODEC_INFO codec_cfg;
|
||||||
tBTC_AV_CODEC_INFO codec_cfg_setconfig; /* remote peer setconfig preference */
|
tBTC_AV_CODEC_INFO codec_cfg_setconfig; /* remote peer setconfig preference */
|
||||||
@@ -189,8 +190,7 @@ void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl);
|
|||||||
** Returns Nothing
|
** Returns Nothing
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void bta_av_co_init(void);
|
void bta_av_co_init(tBTC_AV_CODEC_INFO *codec_caps);
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
@@ -211,7 +211,7 @@ BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl);
|
|||||||
** of our exported bitpool range. If set we will set the
|
** of our exported bitpool range. If set we will set the
|
||||||
** remote preference.
|
** remote preference.
|
||||||
**
|
**
|
||||||
** Returns TRUE if config set, FALSE otherwize
|
** Returns TRUE if config set, FALSE otherwise
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max);
|
BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Data types
|
** Data types
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
#if (BTC_AV_EXT_CODEC == FALSE)
|
||||||
|
|
||||||
/* tBTC_MEDIA_INIT_AUDIO msg structure */
|
/* tBTC_MEDIA_INIT_AUDIO msg structure */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -50,6 +51,8 @@ typedef struct {
|
|||||||
tBTC_AV_MEDIA_FEEDINGS feeding;
|
tBTC_AV_MEDIA_FEEDINGS feeding;
|
||||||
} tBTC_MEDIA_INIT_AUDIO_FEEDING;
|
} tBTC_MEDIA_INIT_AUDIO_FEEDING;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Public functions
|
** Public functions
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@@ -76,29 +79,6 @@ bool btc_a2dp_source_startup(void);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void btc_a2dp_source_shutdown(void);
|
void btc_a2dp_source_shutdown(void);
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
** Function btc_a2dp_source_enc_init_req
|
|
||||||
**
|
|
||||||
** Description Request to initialize the media task encoder
|
|
||||||
**
|
|
||||||
** Returns TRUE is success
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
** Function btc_a2dp_source_enc_udpate_req
|
|
||||||
**
|
|
||||||
** Description Request to update the media task encoder
|
|
||||||
**
|
|
||||||
** Returns TRUE is success
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg);
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function btc_a2dp_source_start_audio_req
|
** Function btc_a2dp_source_start_audio_req
|
||||||
@@ -110,28 +90,6 @@ BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BOOLEAN btc_a2dp_source_start_audio_req(void);
|
BOOLEAN btc_a2dp_source_start_audio_req(void);
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
** Function btc_a2dp_source_stop_audio_req
|
|
||||||
**
|
|
||||||
** Description Request to stop audio encoding task
|
|
||||||
**
|
|
||||||
** Returns TRUE is success
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
BOOLEAN btc_a2dp_source_stop_audio_req(void);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
** Function btc_a2dp_source_tx_flush_req
|
|
||||||
**
|
|
||||||
** Description Request to flush audio encoding pipe
|
|
||||||
**
|
|
||||||
** Returns TRUE is success
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
BOOLEAN btc_a2dp_source_tx_flush_req(void);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function btc_a2dp_source_audio_readbuf
|
** Function btc_a2dp_source_audio_readbuf
|
||||||
@@ -143,27 +101,6 @@ BOOLEAN btc_a2dp_source_tx_flush_req(void);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BT_HDR *btc_a2dp_source_audio_readbuf(void);
|
BT_HDR *btc_a2dp_source_audio_readbuf(void);
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
** Function btc_a2dp_source_audio_feeding_init_req
|
|
||||||
**
|
|
||||||
** Description Request to initialize audio feeding
|
|
||||||
**
|
|
||||||
** Returns TRUE if success
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
BOOLEAN btc_a2dp_source_audio_feeding_init_req(tBTC_MEDIA_INIT_AUDIO_FEEDING *p_msg);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
** Function btc_a2dp_source_is_streaming
|
|
||||||
**
|
|
||||||
** Description Check whether A2DP source is in streaming state
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
bool btc_a2dp_source_is_streaming(void);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function btc_a2dp_source_is_task_shutting_down
|
** Function btc_a2dp_source_is_task_shutting_down
|
||||||
@@ -204,15 +141,6 @@ void btc_a2dp_source_on_stopped(tBTA_AV_SUSPEND *p_av);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av);
|
void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av);
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
** Function btc_a2dp_source_setup_codec
|
|
||||||
**
|
|
||||||
** Description initialize the encoder parameters
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
void btc_a2dp_source_setup_codec(void);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function btc_a2dp_source_set_tx_flush
|
** Function btc_a2dp_source_set_tx_flush
|
||||||
@@ -222,6 +150,17 @@ void btc_a2dp_source_setup_codec(void);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void btc_a2dp_source_set_tx_flush(BOOLEAN enable);
|
void btc_a2dp_source_set_tx_flush(BOOLEAN enable);
|
||||||
|
|
||||||
|
#if (BTC_AV_EXT_CODEC == FALSE)
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_a2dp_source_setup_codec
|
||||||
|
**
|
||||||
|
** Description initialize the encoder parameters
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void btc_a2dp_source_setup_codec(void);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function btc_a2dp_source_encoder_update
|
** Function btc_a2dp_source_encoder_update
|
||||||
@@ -231,6 +170,8 @@ void btc_a2dp_source_set_tx_flush(BOOLEAN enable);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void btc_a2dp_source_encoder_update(void);
|
void btc_a2dp_source_encoder_update(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
**
|
**
|
||||||
** Function btc_source_report_delay_value
|
** Function btc_source_report_delay_value
|
||||||
@@ -240,6 +181,19 @@ void btc_a2dp_source_encoder_update(void);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void btc_source_report_delay_value(UINT16 delay_value);
|
void btc_source_report_delay_value(UINT16 delay_value);
|
||||||
|
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_a2dp_source_enqueue_audio_frame
|
||||||
|
**
|
||||||
|
** Description Enqueue source audio frame to tx queue
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
BOOLEAN btc_a2dp_source_enqueue_audio_frame(BT_HDR *p_buf);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* #if BTC_AV_SRC_INCLUDED */
|
#endif /* #if BTC_AV_SRC_INCLUDED */
|
||||||
|
|
||||||
#endif /* __BTC_A2DP_SOURCE_H__ */
|
#endif /* __BTC_A2DP_SOURCE_H__ */
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -22,11 +22,21 @@
|
|||||||
#include "btc/btc_task.h"
|
#include "btc/btc_task.h"
|
||||||
#include "btc/btc_common.h"
|
#include "btc/btc_common.h"
|
||||||
#include "btc/btc_sm.h"
|
#include "btc/btc_sm.h"
|
||||||
|
#include "btc_av_api.h"
|
||||||
#include "bta/bta_av_api.h"
|
#include "bta/bta_av_api.h"
|
||||||
|
#include "bta/bta_av_sbc.h"
|
||||||
|
|
||||||
#if (BTC_AV_INCLUDED == TRUE)
|
#if (BTC_AV_INCLUDED == TRUE)
|
||||||
|
|
||||||
// global variable to inidcate avrc is initialized with a2dp
|
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
|
||||||
|
#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE + 1)
|
||||||
|
#else
|
||||||
|
#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BTC_AUDIO_BUFF_OFFSET BTC_MEDIA_AA_SBC_OFFSET
|
||||||
|
|
||||||
|
// global variable to indicate avrc is initialized with a2dp
|
||||||
extern bool g_av_with_rc;
|
extern bool g_av_with_rc;
|
||||||
// global variable to indicate a2dp is initialized
|
// global variable to indicate a2dp is initialized
|
||||||
extern bool g_a2dp_on_init;
|
extern bool g_a2dp_on_init;
|
||||||
@@ -51,21 +61,24 @@ typedef enum {
|
|||||||
BTC_AV_DISCONNECT_REQ_EVT,
|
BTC_AV_DISCONNECT_REQ_EVT,
|
||||||
BTC_AV_START_STREAM_REQ_EVT,
|
BTC_AV_START_STREAM_REQ_EVT,
|
||||||
BTC_AV_SUSPEND_STREAM_REQ_EVT,
|
BTC_AV_SUSPEND_STREAM_REQ_EVT,
|
||||||
BTC_AV_SINK_CONFIG_REQ_EVT,
|
BTC_AV_CONFIG_EVT,
|
||||||
} btc_av_sm_event_t;
|
} btc_av_sm_event_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#if BTC_AV_SINK_INCLUDED
|
#if BTC_AV_SINK_INCLUDED
|
||||||
BTC_AV_SINK_API_INIT_EVT = 0,
|
BTC_AV_SINK_API_INIT_EVT = 0,
|
||||||
|
BTC_AV_SINK_API_REG_SEP_EVT,
|
||||||
BTC_AV_SINK_API_DEINIT_EVT,
|
BTC_AV_SINK_API_DEINIT_EVT,
|
||||||
BTC_AV_SINK_API_CONNECT_EVT,
|
BTC_AV_SINK_API_CONNECT_EVT,
|
||||||
BTC_AV_SINK_API_DISCONNECT_EVT,
|
BTC_AV_SINK_API_DISCONNECT_EVT,
|
||||||
BTC_AV_SINK_API_REG_DATA_CB_EVT,
|
BTC_AV_SINK_API_REG_DATA_CB_EVT,
|
||||||
|
BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT,
|
||||||
BTC_AV_SINK_API_SET_DELAY_VALUE_EVT,
|
BTC_AV_SINK_API_SET_DELAY_VALUE_EVT,
|
||||||
BTC_AV_SINK_API_GET_DELAY_VALUE_EVT,
|
BTC_AV_SINK_API_GET_DELAY_VALUE_EVT,
|
||||||
#endif /* BTC_AV_SINK_INCLUDED */
|
#endif /* BTC_AV_SINK_INCLUDED */
|
||||||
#if BTC_AV_SRC_INCLUDED
|
#if BTC_AV_SRC_INCLUDED
|
||||||
BTC_AV_SRC_API_INIT_EVT,
|
BTC_AV_SRC_API_INIT_EVT,
|
||||||
|
BTC_AV_SRC_API_REG_SEP_EVT,
|
||||||
BTC_AV_SRC_API_DEINIT_EVT,
|
BTC_AV_SRC_API_DEINIT_EVT,
|
||||||
BTC_AV_SRC_API_CONNECT_EVT,
|
BTC_AV_SRC_API_CONNECT_EVT,
|
||||||
BTC_AV_SRC_API_DISCONNECT_EVT,
|
BTC_AV_SRC_API_DISCONNECT_EVT,
|
||||||
@@ -77,14 +90,14 @@ typedef enum {
|
|||||||
/* btc_av_args_t */
|
/* btc_av_args_t */
|
||||||
typedef union {
|
typedef union {
|
||||||
#if BTC_AV_SINK_INCLUDED
|
#if BTC_AV_SINK_INCLUDED
|
||||||
// BTC_AV_SINK_CONFIG_REQ_EVT -- internal event
|
|
||||||
esp_a2d_mcc_t mcc;
|
|
||||||
// BTC_AV_SINK_API_CONNECT_EVT
|
// BTC_AV_SINK_API_CONNECT_EVT
|
||||||
bt_bdaddr_t connect;
|
bt_bdaddr_t connect;
|
||||||
// BTC_AV_SINK_API_DISCONNECT_EVT
|
// BTC_AV_SINK_API_DISCONNECT_EVT
|
||||||
bt_bdaddr_t disconn;
|
bt_bdaddr_t disconn;
|
||||||
// BTC_AV_SINK_API_REG_DATA_CB_EVT
|
// BTC_AV_SINK_API_REG_DATA_CB_EVT
|
||||||
esp_a2d_sink_data_cb_t data_cb;
|
esp_a2d_sink_data_cb_t data_cb;
|
||||||
|
// BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT
|
||||||
|
esp_a2d_sink_audio_data_cb_t audio_data_cb;
|
||||||
// BTC_AV_SINK_API_SET_DELAY_VALUE_EVT
|
// BTC_AV_SINK_API_SET_DELAY_VALUE_EVT
|
||||||
uint16_t delay_value;
|
uint16_t delay_value;
|
||||||
#endif /* BTC_AV_SINK_INCLUDED */
|
#endif /* BTC_AV_SINK_INCLUDED */
|
||||||
@@ -96,6 +109,13 @@ typedef union {
|
|||||||
// BTC_AV_SRC_API_DISCONNECT_EVT
|
// BTC_AV_SRC_API_DISCONNECT_EVT
|
||||||
bt_bdaddr_t src_disconn;
|
bt_bdaddr_t src_disconn;
|
||||||
#endif /* BTC_AV_SRC_INCLUDED */
|
#endif /* BTC_AV_SRC_INCLUDED */
|
||||||
|
// BTC_AV_CONFIG_EVT
|
||||||
|
esp_a2d_mcc_t mcc;
|
||||||
|
// BTC_AV_SINK_API_REG_SEP_EVT or BTC_AV_SRC_API_REG_SEP_EVT
|
||||||
|
struct {
|
||||||
|
uint8_t seid;
|
||||||
|
esp_a2d_mcc_t mcc;
|
||||||
|
} reg_sep;
|
||||||
// BTC_AV_API_MEDIA_CTRL_EVT
|
// BTC_AV_API_MEDIA_CTRL_EVT
|
||||||
esp_a2d_media_ctrl_t ctrl;
|
esp_a2d_media_ctrl_t ctrl;
|
||||||
} btc_av_args_t;
|
} btc_av_args_t;
|
||||||
@@ -110,6 +130,32 @@ void btc_a2dp_cb_handler(btc_msg_t *msg);
|
|||||||
|
|
||||||
void btc_a2dp_sink_reg_data_cb(esp_a2d_sink_data_cb_t callback);
|
void btc_a2dp_sink_reg_data_cb(esp_a2d_sink_data_cb_t callback);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_a2dp_sink_reg_audio_data_cb
|
||||||
|
**
|
||||||
|
** Description Register a2dp sink audio data callback
|
||||||
|
**
|
||||||
|
** Returns None
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void btc_a2dp_sink_reg_audio_data_cb(esp_a2d_sink_audio_data_cb_t callback);
|
||||||
|
|
||||||
|
#if (BTC_AV_EXT_CODEC == TRUE)
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_av_codec_cap_get
|
||||||
|
**
|
||||||
|
** Description Get external codec capability
|
||||||
|
**
|
||||||
|
** Returns Pointer to codec capability
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tBTC_AV_CODEC_INFO *btc_av_codec_cap_get(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void btc_a2dp_src_reg_data_cb(esp_a2d_source_data_cb_t callback);
|
void btc_a2dp_src_reg_data_cb(esp_a2d_source_data_cb_t callback);
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
@@ -172,6 +218,16 @@ void btc_dispatch_sm_event(btc_av_sm_event_t event, void *p_data, int len);
|
|||||||
|
|
||||||
BOOLEAN btc_av_is_connected(void);
|
BOOLEAN btc_av_is_connected(void);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_av_is_started
|
||||||
|
**
|
||||||
|
** Description Checks if av is started
|
||||||
|
**
|
||||||
|
** Returns BOOLEAN
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
BOOLEAN btc_av_is_started(void);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -225,4 +281,60 @@ uint8_t btc_av_get_service_id(void);
|
|||||||
|
|
||||||
#endif ///BTC_AV_INCLUDED == TRUE
|
#endif ///BTC_AV_INCLUDED == TRUE
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_a2d_conn_handle_get
|
||||||
|
**
|
||||||
|
** Description Get connection handle from btc_av_cb
|
||||||
|
**
|
||||||
|
** Returns Void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
uint16_t btc_a2d_conn_handle_get(void);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_av_audio_buff_alloc
|
||||||
|
**
|
||||||
|
** Description Allocate audio buffer with specific size
|
||||||
|
**
|
||||||
|
** Returns Void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void btc_av_audio_buff_alloc(uint16_t size, uint8_t **pp_buff, uint8_t **pp_data);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_av_audio_buff_free
|
||||||
|
**
|
||||||
|
** Description Free audio buffer
|
||||||
|
**
|
||||||
|
** Returns Void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void btc_av_audio_buff_free(uint8_t *p_buf);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_a2d_src_audio_mtu_check
|
||||||
|
**
|
||||||
|
** Description Checks if data length is valid, not bigger than mtu
|
||||||
|
**
|
||||||
|
** Returns BOOLEAN
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
BOOLEAN btc_a2d_src_audio_mtu_check(uint16_t data_len);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function btc_a2d_src_audio_data_send
|
||||||
|
**
|
||||||
|
** Description Send audio data to lower layer, audio buffer is consumed
|
||||||
|
** only when operation is success
|
||||||
|
**
|
||||||
|
** Returns BT_STATUS_SUCCESS if success, otherwise, BT_STATUS_FAIL
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
bt_status_t btc_a2d_src_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf);
|
||||||
|
|
||||||
#endif /* __BTC_AV_H__ */
|
#endif /* __BTC_AV_H__ */
|
||||||
|
@@ -91,6 +91,7 @@
|
|||||||
#define BTC_AV_SRC_INCLUDED TRUE
|
#define BTC_AV_SRC_INCLUDED TRUE
|
||||||
#if (UC_BT_A2DP_USE_EXTERNAL_CODEC == TRUE)
|
#if (UC_BT_A2DP_USE_EXTERNAL_CODEC == TRUE)
|
||||||
#define BTC_AV_EXT_CODEC TRUE
|
#define BTC_AV_EXT_CODEC TRUE
|
||||||
|
#define BTA_AV_EXT_CODEC TRUE
|
||||||
#else
|
#else
|
||||||
#define SBC_DEC_INCLUDED TRUE
|
#define SBC_DEC_INCLUDED TRUE
|
||||||
#define SBC_ENC_INCLUDED TRUE
|
#define SBC_ENC_INCLUDED TRUE
|
||||||
@@ -581,6 +582,10 @@
|
|||||||
#define BTC_AV_SRC_INCLUDED FALSE
|
#define BTC_AV_SRC_INCLUDED FALSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BTC_AV_EXT_CODEC
|
||||||
|
#define BTC_AV_EXT_CODEC FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef BTC_SPP_INCLUDED
|
#ifndef BTC_SPP_INCLUDED
|
||||||
#define BTC_SPP_INCLUDED FALSE
|
#define BTC_SPP_INCLUDED FALSE
|
||||||
#endif
|
#endif
|
||||||
@@ -658,8 +663,8 @@
|
|||||||
#define BTA_AV_CA_INCLUDED FALSE
|
#define BTA_AV_CA_INCLUDED FALSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BTC_AV_EXT_CODEC
|
#ifndef BTA_AV_EXT_CODEC
|
||||||
#define BTC_AV_EXT_CODEC FALSE
|
#define BTA_AV_EXT_CODEC FALSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BTA_AV_SINK_INCLUDED
|
#ifndef BTA_AV_SINK_INCLUDED
|
||||||
|
@@ -264,6 +264,37 @@ UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVDT_UpdateCodecInfo
|
||||||
|
**
|
||||||
|
** Description Update codec capability for a stream endpoint.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns AVDT_SUCCESS if successful, otherwise error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVDT_UpdateCodecInfo(UINT8 handle, UINT8 num_codec, UINT8 *codec_info, UINT16 codec_info_len)
|
||||||
|
{
|
||||||
|
UINT16 result = AVDT_SUCCESS;
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
|
||||||
|
/* look up scb */
|
||||||
|
if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) {
|
||||||
|
result = AVDT_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
else if (num_codec != 1 || codec_info == NULL || codec_info_len != AVDT_CODEC_SIZE) {
|
||||||
|
/* currently, only allow one codec info */
|
||||||
|
result = AVDT_BAD_PARAMS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* update codec info */
|
||||||
|
p_scb->cs.cfg.num_codec = num_codec;
|
||||||
|
memcpy(p_scb->cs.cfg.codec_info, codec_info, codec_info_len);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function AVDT_RemoveStream
|
** Function AVDT_RemoveStream
|
||||||
|
@@ -30,7 +30,12 @@
|
|||||||
/* the length of the SBC Media Payload header. */
|
/* the length of the SBC Media Payload header. */
|
||||||
#define A2D_SBC_MPL_HDR_LEN 1
|
#define A2D_SBC_MPL_HDR_LEN 1
|
||||||
|
|
||||||
/* the LOSC of SBC media codec capabilitiy */
|
/* CIE offset in the info byte sequence */
|
||||||
|
#define A2D_SBC_CIE_OFF 3
|
||||||
|
/* CIE length in the info byte sequence */
|
||||||
|
#define A2D_SBC_CIE_LEN 4
|
||||||
|
|
||||||
|
/* the LOSC of SBC media codec capability */
|
||||||
#define A2D_SBC_INFO_LEN 6
|
#define A2D_SBC_INFO_LEN 6
|
||||||
|
|
||||||
/* for Codec Specific Information Element */
|
/* for Codec Specific Information Element */
|
||||||
|
@@ -517,6 +517,18 @@ extern void AVDT_AbortReq(UINT8 handle);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
extern UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs);
|
extern UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVDT_UpdateCodecInfo
|
||||||
|
**
|
||||||
|
** Description Update codec capability for a stream endpoint.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns AVDT_SUCCESS if successful, otherwise error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
extern UINT16 AVDT_UpdateCodecInfo(UINT8 handle, UINT8 num_codec, UINT8 *codec_info, UINT16 codec_info_len);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function AVDT_RemoveStream
|
** Function AVDT_RemoveStream
|
||||||
|
Reference in New Issue
Block a user