diff --git a/components/bt/host/bluedroid/api/esp_a2dp_api.c b/components/bt/host/bluedroid/api/esp_a2dp_api.c index 7bcea0b526b..d1733fa0df5 100644 --- a/components/bt/host/bluedroid/api/esp_a2dp_api.c +++ b/components/bt/host/bluedroid/api/esp_a2dp_api.c @@ -14,6 +14,13 @@ #if BTC_AV_INCLUDED +// indicate the first time to call the register SEP function (for sink) +static bool s_a2dp_sink_first_call_reg_sep[ESP_A2D_MAX_SEPS] = { [0 ... (ESP_A2D_MAX_SEPS - 1)] = true }; +// indicate the first time to call the register SEP function (for source) +static bool s_a2dp_src_first_call_reg_sep[ESP_A2D_MAX_SEPS] = { [0 ... (ESP_A2D_MAX_SEPS - 1)] = true }; +// indicate the first time to call the get delay value function +static bool s_a2dp_first_call_get_delay = true; + esp_a2d_audio_buff_t *esp_a2d_audio_buff_alloc(uint16_t size) { if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { @@ -73,14 +80,21 @@ esp_err_t esp_a2d_sink_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_ return ESP_ERR_INVALID_STATE; } - if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) { - return ESP_ERR_INVALID_STATE; - } - if (mcc == NULL || seid >= ESP_A2D_MAX_SEPS) { return ESP_ERR_INVALID_ARG; } + /* To be compatible with the legacy usage methods, + use a flag indicating whether this is the first time the function has been called. */ + if (s_a2dp_sink_first_call_reg_sep[seid]) { + s_a2dp_sink_first_call_reg_sep[seid] = false; + if (g_a2dp_sink_ongoing_deinit) { + return ESP_ERR_INVALID_STATE; + } + } else if (g_a2dp_on_deinit || 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; @@ -114,7 +128,15 @@ esp_err_t esp_a2d_sink_deinit(void) /* Switch to BTC context */ bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL); - return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; + if (stat == BT_STATUS_SUCCESS) { + for (int i = 0; i < ESP_A2D_MAX_SEPS; i++) { + s_a2dp_sink_first_call_reg_sep[i] = false; + } + s_a2dp_first_call_get_delay = false; + return ESP_OK; + } else { + return ESP_FAIL; + } } esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback) @@ -248,7 +270,14 @@ esp_err_t esp_a2d_sink_get_delay_value(void) return ESP_ERR_INVALID_STATE; } - if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) { + /* To be compatible with the legacy usage methods, + use a flag indicating whether this is the first time the function has been called. */ + if (s_a2dp_first_call_get_delay) { + s_a2dp_first_call_get_delay = false; + if (g_a2dp_sink_ongoing_deinit) { + return ESP_ERR_INVALID_STATE; + } + } else if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) { return ESP_ERR_INVALID_STATE; } @@ -361,14 +390,21 @@ esp_err_t esp_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mc return ESP_ERR_INVALID_STATE; } - if (g_a2dp_on_deinit || g_a2dp_source_ongoing_deinit) { - return ESP_ERR_INVALID_STATE; - } - if (mcc == NULL || seid >= ESP_A2D_MAX_SEPS) { return ESP_ERR_INVALID_ARG; } + /* To be compatible with the legacy usage methods, + use a flag indicating whether this is the first time the function has been called. */ + if (s_a2dp_src_first_call_reg_sep[seid]) { + s_a2dp_src_first_call_reg_sep[seid] = false; + if (g_a2dp_source_ongoing_deinit) { + return ESP_ERR_INVALID_STATE; + } + } else if (g_a2dp_on_deinit || g_a2dp_source_ongoing_deinit) { + return ESP_ERR_INVALID_STATE; + } + btc_msg_t msg; msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_A2DP; @@ -402,7 +438,14 @@ esp_err_t esp_a2d_source_deinit(void) /* Switch to BTC context */ bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL); - return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; + if (stat == BT_STATUS_SUCCESS) { + for (int i = 0; i < ESP_A2D_MAX_SEPS; i++) { + s_a2dp_src_first_call_reg_sep[i] = false; + } + return ESP_OK; + } else { + return ESP_FAIL; + } } esp_err_t esp_a2d_source_connect(esp_bd_addr_t remote_bda) @@ -483,7 +526,11 @@ esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callbac 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()) { + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (g_a2dp_on_deinit || g_a2dp_source_ongoing_deinit || !btc_av_is_started()) { return ESP_ERR_INVALID_STATE; } diff --git a/components/bt/host/bluedroid/bta/av/bta_av_act.c b/components/bt/host/bluedroid/bta/av/bta_av_act.c index 13d0901e989..2d8df0599ee 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_act.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_act.c @@ -262,8 +262,8 @@ static void bta_av_rc_msg_cback(UINT8 handle, UINT8 label, UINT8 opcode, tAVRC_M } /* Create a copy of the message */ - tBTA_AV_RC_MSG *p_buf = - (tBTA_AV_RC_MSG *)osi_malloc((UINT16)(sizeof(tBTA_AV_RC_MSG) + data_len)); + size_t buf_size = sizeof(tBTA_AV_RC_MSG) + data_len; + tBTA_AV_RC_MSG *p_buf = (tBTA_AV_RC_MSG *)osi_malloc(buf_size); if (p_buf != NULL) { p_buf->hdr.event = BTA_AV_AVRC_MSG_EVT; p_buf->handle = handle; diff --git a/components/bt/host/bluedroid/bta/av/bta_av_api.c b/components/bt/host/bluedroid/bta/av/bta_av_api.c index b95f7d16c66..f65966e5479 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_api.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_api.c @@ -60,16 +60,18 @@ void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features, tBTA_AV_CBACK *p_cba { tBTA_AV_API_ENABLE *p_buf; + if ((p_buf = (tBTA_AV_API_ENABLE *) osi_malloc(sizeof(tBTA_AV_API_ENABLE))) == NULL) { + return; + } + /* register with BTA system manager */ bta_sys_register(BTA_ID_AV, &bta_av_reg); - if ((p_buf = (tBTA_AV_API_ENABLE *) osi_malloc(sizeof(tBTA_AV_API_ENABLE))) != NULL) { - p_buf->hdr.event = BTA_AV_API_ENABLE_EVT; - p_buf->p_cback = p_cback; - p_buf->features = features; - p_buf->sec_mask = sec_mask; - bta_sys_sendmsg(p_buf); - } + p_buf->hdr.event = BTA_AV_API_ENABLE_EVT; + p_buf->p_cback = p_cback; + p_buf->features = features; + p_buf->sec_mask = sec_mask; + bta_sys_sendmsg(p_buf); } /******************************************************************************* diff --git a/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c b/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c index 5e01bec3d97..86f1ff507ad 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c @@ -298,7 +298,6 @@ void bta_av_ca_api_get(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, COVER_ART_HEADER_ID_IMG_HANDLE, (UINT8 *)image_handle_utf16, BTA_AV_CA_IMG_HDL_UTF16_LEN); if (p_data->api_ca_get.type == BTA_AV_CA_GET_IMAGE) { GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, COVER_ART_HEADER_ID_IMG_DESCRIPTOR, (UINT8 *)p_data->api_ca_get.image_descriptor, p_data->api_ca_get.image_descriptor_len); - osi_free(p_data->api_ca_get.image_descriptor); } /* always request to enable srm */ GOEPC_RequestSetSRM(p_rcb->cover_art_goep_hdl, TRUE, FALSE); diff --git a/components/bt/host/bluedroid/bta/av/bta_av_main.c b/components/bt/host/bluedroid/bta/av/bta_av_main.c index 5e08ef5d947..589c02d2389 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_main.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_main.c @@ -755,7 +755,9 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) } while (0); /* call callback with register event */ - (*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)®istr); + if (bta_av_cb.p_cback != NULL) { + (*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)®istr); + } } static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data) diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index 46b343a542e..2d5b009f12e 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -230,6 +230,11 @@ error_exit:; void btc_a2dp_sink_shutdown(void) { + if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON) { + APPL_TRACE_ERROR("a2dp sink already shutdown"); + return; + } + APPL_TRACE_EVENT("## A2DP SINK STOP MEDIA THREAD ##\n"); // Exit thread diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c index 25d6941314b..699e530400c 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c @@ -406,6 +406,11 @@ static void log_tstamps_us(char *comment) { static UINT64 prev_us = 0; UINT64 now_us = time_now_us(); +#if A2D_DYNAMIC_MEMORY == TRUE + if (a2dp_source_local_param_ptr == NULL) { + return; + } +#endif APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment, now_us, now_us - prev_us, fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ)); prev_us = now_us; @@ -1487,6 +1492,11 @@ static void btc_a2dp_source_handle_timer(UNUSED_ATTR void *context) if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON || g_a2dp_source_ongoing_deinit){ return; } +#if A2D_DYNAMIC_MEMORY == TRUE + if (a2dp_source_local_param_ptr == NULL) { + return; + } +#endif if (a2dp_source_local_param.btc_aa_src_cb.is_tx_timer == TRUE) { btc_a2dp_source_send_aa_frame(); diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c index 605c06bcb36..745b5431f16 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -40,7 +40,7 @@ bool g_av_with_rc; // global variable to indicate a2dp is initialized bool g_a2dp_on_init; // global variable to indicate a2dp is deinitialized -bool g_a2dp_on_deinit; +bool g_a2dp_on_deinit = true; // global variable to indicate a2dp source deinitialization is ongoing bool g_a2dp_source_ongoing_deinit; // global variable to indicate a2dp sink deinitialization is ongoing diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_ad.c b/components/bt/host/bluedroid/stack/avdt/avdt_ad.c index d6911e1f7cf..fbdaf6dd6ba 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_ad.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_ad.c @@ -110,6 +110,11 @@ void avdt_ad_init(void) tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl; memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD)); + /* 0 is a valid tc_tbl index; use invalid marker for unassigned LCIDs */ + for (i = 0; i < MAX_L2CAP_CHANNELS; i++) { + avdt_cb.ad.lcid_tbl[i] = 0xFF; + } + /* make sure the peer_mtu is a valid value */ for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) { p_tbl->peer_mtu = L2CAP_DEFAULT_MTU; diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_api.c b/components/bt/host/bluedroid/stack/avdt/avdt_api.c index 50de972186a..375aeeb1bcc 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_api.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_api.c @@ -944,6 +944,7 @@ UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_ } /* map handle to scb */ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) { + osi_free(p_pkt); result = AVDT_BAD_HANDLE; } else { evt.apiwrite.p_buf = p_pkt; diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c b/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c index bf8943aa54c..a18535d2093 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c @@ -383,6 +383,12 @@ tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr) memcpy(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN); p_ccb->cmd_q = fixed_queue_new(QUEUE_SIZE_MAX); p_ccb->rsp_q = fixed_queue_new(QUEUE_SIZE_MAX); + if (p_ccb->cmd_q == NULL || p_ccb->rsp_q == NULL) { + AVDT_TRACE_ERROR("avdt_ccb_alloc: queue alloc failed"); + avdt_ccb_dealloc(p_ccb, NULL); + p_ccb = NULL; + break; + } p_ccb->timer_entry.param = (UINT32) p_ccb; AVDT_TRACE_DEBUG("avdt_ccb_alloc %d\n", i); break; diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c b/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c index dce084aa7c5..386b5fa40c6 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c @@ -712,6 +712,8 @@ void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) UINT8 evt; tAVDT_SCB *p_scb; + memset(&msg, 0, sizeof(msg)); + if (p_ccb->p_curr_cmd != NULL) { if (p_ccb->p_curr_cmd->event < 1 || p_ccb->p_curr_cmd->event > AVDT_SIG_MAX) { osi_free(p_ccb->p_curr_cmd); diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/main.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/main.c index 3241b5f5033..0dff2d171df 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink_stream/main/main.c @@ -68,10 +68,57 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa bredr_app_gap_evt_def_hdl(event, param); } +static void bt_app_a2d_evt_hdl(uint16_t event, void *param) +{ + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when a2dp init or deinit completed, this event comes */ + case ESP_A2D_PROF_STATE_EVT: { + if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == TRUE + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + ESP_ERROR_CHECK(esp_a2d_sink_register_stream_endpoint(0, &mcc)); +#endif + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) { switch (event) { - case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_app_a2d_evt_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); + break; + } case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { @@ -124,31 +171,9 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); #else - esp_a2d_mcc_t mcc = {0}; - mcc.type = ESP_A2D_MCT_SBC; - mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | - ESP_A2D_SBC_CIE_SF_32K | - ESP_A2D_SBC_CIE_SF_44K | - ESP_A2D_SBC_CIE_SF_48K; - mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | - ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | - ESP_A2D_SBC_CIE_CH_MODE_STEREO | - ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; - mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | - ESP_A2D_SBC_CIE_BLOCK_LEN_8 | - ESP_A2D_SBC_CIE_BLOCK_LEN_12 | - ESP_A2D_SBC_CIE_BLOCK_LEN_16; - mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; - mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; - mcc.cie.sbc_info.max_bitpool = 250; - mcc.cie.sbc_info.min_bitpool = 2; - /* register stream end point, only support SBC currently */ - esp_a2d_sink_register_stream_endpoint(0, &mcc); esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); #endif - /* Get the default value of the delay value */ - esp_a2d_sink_get_delay_value(); /* Get local device name */ esp_bt_gap_get_device_name(); diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/main.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/main.c index 7ef35189bf5..723104e4cf5 100644 --- a/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_absolute_volume/main/main.c @@ -47,6 +47,7 @@ static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *pa static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); /* callback function for A2DP sink */ +static void bt_app_a2d_evt_hdl(uint16_t event, void *param); static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); #if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE @@ -82,10 +83,59 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa bredr_app_gap_evt_def_hdl(event, param); } +static void bt_app_a2d_evt_hdl(uint16_t event, void *param) +{ + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when a2dp init or deinit completed, this event comes */ + case ESP_A2D_PROF_STATE_EVT: { + if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == TRUE + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + ESP_ERROR_CHECK(esp_a2d_sink_register_stream_endpoint(0, &mcc)); +#endif +#endif + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) { switch (event) { - case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_app_a2d_evt_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); + break; + } case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { @@ -194,32 +244,10 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); #else - esp_a2d_mcc_t mcc = {0}; - mcc.type = ESP_A2D_MCT_SBC; - mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | - ESP_A2D_SBC_CIE_SF_32K | - ESP_A2D_SBC_CIE_SF_44K | - ESP_A2D_SBC_CIE_SF_48K; - mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | - ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | - ESP_A2D_SBC_CIE_CH_MODE_STEREO | - ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; - mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | - ESP_A2D_SBC_CIE_BLOCK_LEN_8 | - ESP_A2D_SBC_CIE_BLOCK_LEN_12 | - ESP_A2D_SBC_CIE_BLOCK_LEN_16; - mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; - mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; - mcc.cie.sbc_info.max_bitpool = 250; - mcc.cie.sbc_info.min_bitpool = 2; - /* register stream end point, only support SBC currently */ - esp_a2d_sink_register_stream_endpoint(0, &mcc); esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); #endif #endif - /* Get the default value of the delay value */ - esp_a2d_sink_get_delay_value(); /* Get local device name */ esp_bt_gap_get_device_name(); diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.c index eff24138899..41f5f4ad479 100644 --- a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.c +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/bt_app_av.c @@ -13,6 +13,7 @@ #include "esp_log.h" #include "esp_bt_device.h" #include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" #include "esp_avrc_api.h" #include "freertos/FreeRTOS.h" @@ -108,10 +109,59 @@ static void bt_app_avrc_ct_evt_hdl(uint16_t event, void *param) * EXTERNAL FUNCTION DEFINITIONS *******************************/ +static void bt_app_a2d_evt_hdl(uint16_t event, void *param) +{ + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when a2dp init or deinit completed, this event comes */ + case ESP_A2D_PROF_STATE_EVT: { + if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == TRUE + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + ESP_ERROR_CHECK(esp_a2d_sink_register_stream_endpoint(0, &mcc)); +#endif +#endif + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) { switch (event) { - case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_app_a2d_evt_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); + break; + } case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/main.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/main.c index 87e32a7d887..756991daf7d 100644 --- a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_cover_art/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -79,32 +79,10 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); #else - esp_a2d_mcc_t mcc = {0}; - mcc.type = ESP_A2D_MCT_SBC; - mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | - ESP_A2D_SBC_CIE_SF_32K | - ESP_A2D_SBC_CIE_SF_44K | - ESP_A2D_SBC_CIE_SF_48K; - mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | - ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | - ESP_A2D_SBC_CIE_CH_MODE_STEREO | - ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; - mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | - ESP_A2D_SBC_CIE_BLOCK_LEN_8 | - ESP_A2D_SBC_CIE_BLOCK_LEN_12 | - ESP_A2D_SBC_CIE_BLOCK_LEN_16; - mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; - mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; - mcc.cie.sbc_info.max_bitpool = 250; - mcc.cie.sbc_info.min_bitpool = 2; - /* register stream end point, only support SBC currently */ - esp_a2d_sink_register_stream_endpoint(0, &mcc); esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); #endif #endif - /* Get the default value of the delay value */ - esp_a2d_sink_get_delay_value(); /* Get local device name */ esp_bt_gap_get_device_name(); diff --git a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/main.c b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/main.c index 4ff11d03e92..ad257cc88a9 100644 --- a/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/avrcp_ct_metadata/main/main.c @@ -47,6 +47,7 @@ static void bt_app_dev_cb(esp_bt_dev_cb_event_t event, esp_bt_dev_cb_param_t *pa static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); /* callback function for A2DP sink */ +static void bt_app_a2d_evt_hdl(uint16_t event, void *param); static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); #if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE @@ -85,10 +86,59 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa bredr_app_gap_evt_def_hdl(event, param); } +static void bt_app_a2d_evt_hdl(uint16_t event, void *param) +{ + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when a2dp init or deinit completed, this event comes */ + case ESP_A2D_PROF_STATE_EVT: { + if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); +#if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == TRUE + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | + ESP_A2D_SBC_CIE_SF_32K | + ESP_A2D_SBC_CIE_SF_44K | + ESP_A2D_SBC_CIE_SF_48K; + mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | + ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | + ESP_A2D_SBC_CIE_CH_MODE_STEREO | + ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; + mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | + ESP_A2D_SBC_CIE_BLOCK_LEN_8 | + ESP_A2D_SBC_CIE_BLOCK_LEN_12 | + ESP_A2D_SBC_CIE_BLOCK_LEN_16; + mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; + mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + ESP_ERROR_CHECK(esp_a2d_sink_register_stream_endpoint(0, &mcc)); +#endif +#endif + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) { switch (event) { - case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_app_a2d_evt_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); + break; + } case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { @@ -248,32 +298,10 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); #else - esp_a2d_mcc_t mcc = {0}; - mcc.type = ESP_A2D_MCT_SBC; - mcc.cie.sbc_info.samp_freq = ESP_A2D_SBC_CIE_SF_16K | - ESP_A2D_SBC_CIE_SF_32K | - ESP_A2D_SBC_CIE_SF_44K | - ESP_A2D_SBC_CIE_SF_48K; - mcc.cie.sbc_info.ch_mode = ESP_A2D_SBC_CIE_CH_MODE_MONO | - ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL | - ESP_A2D_SBC_CIE_CH_MODE_STEREO | - ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO; - mcc.cie.sbc_info.block_len = ESP_A2D_SBC_CIE_BLOCK_LEN_4 | - ESP_A2D_SBC_CIE_BLOCK_LEN_8 | - ESP_A2D_SBC_CIE_BLOCK_LEN_12 | - ESP_A2D_SBC_CIE_BLOCK_LEN_16; - mcc.cie.sbc_info.num_subbands = ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 | ESP_A2D_SBC_CIE_NUM_SUBBANDS_8; - mcc.cie.sbc_info.alloc_mthd = ESP_A2D_SBC_CIE_ALLOC_MTHD_SNR | ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS; - mcc.cie.sbc_info.max_bitpool = 250; - mcc.cie.sbc_info.min_bitpool = 2; - /* register stream end point, only support SBC currently */ - esp_a2d_sink_register_stream_endpoint(0, &mcc); esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); #endif #endif - /* Get the default value of the delay value */ - esp_a2d_sink_get_delay_value(); /* Get local device name */ esp_bt_gap_get_device_name(); diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c index 754ea42a82b..2a7085f729e 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c @@ -82,6 +82,30 @@ static void bt_app_avrc_ct_evt_hdl(uint16_t event, void *param) } } +/* handler for A2DP callback events */ +static void bt_app_a2d_evt_hdl(uint16_t event, void *param) +{ + esp_a2d_cb_param_t *a2d = (esp_a2d_cb_param_t *)(param); + + switch (event) { + /* when a2dp init or deinit completed, this event comes */ + case ESP_A2D_PROF_STATE_EVT: { + if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state) { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Complete"); + /* Get the default value of the delay value */ + esp_a2d_sink_get_delay_value(); + } else { + ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Complete"); + } + break; + } + /* others */ + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event); + break; + } +} + /******************************** * EXTERNAL FUNCTION DEFINITIONS *******************************/ @@ -89,13 +113,16 @@ static void bt_app_avrc_ct_evt_hdl(uint16_t event, void *param) void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) { switch (event) { + case ESP_A2D_PROF_STATE_EVT: { + bt_app_work_dispatch(bt_app_a2d_evt_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); + break; + } case ESP_A2D_CONNECTION_STATE_EVT: case ESP_A2D_AUDIO_STATE_EVT: case ESP_A2D_AUDIO_CFG_EVT: { bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); break; } - case ESP_A2D_PROF_STATE_EVT: case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c index 75cddcbcc29..0761e1c3594 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c @@ -644,9 +644,6 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) esp_a2d_register_callback(&bt_app_a2d_cb); esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); - /* Get the default value of the delay value */ - esp_a2d_sink_get_delay_value(); - /* set discoverable and connectable mode, wait to be connected */ esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); break;