From aa10a3a2d11264825005fa470ca79f34cdda514f Mon Sep 17 00:00:00 2001 From: yangfeng Date: Wed, 8 Apr 2026 14:29:03 +0800 Subject: [PATCH] fix(bt/example): fix critical issues of classic_bt examples reported by AI review --- .../classic_bt/a2dp_sink_stream/main/main.c | 10 +-- .../classic_bt/a2dp_source/main/bt_app_core.c | 29 +++++++-- .../classic_bt/a2dp_source/main/bt_app_core.h | 14 +++- .../classic_bt/a2dp_source/main/main.c | 15 ++--- .../avrcp_absolute_volume/main/main.c | 21 +++--- .../avrcp_ct_cover_art/main/bt_app_av.c | 19 +++--- .../classic_bt/avrcp_ct_cover_art/main/main.c | 2 +- .../classic_bt/avrcp_ct_metadata/main/main.c | 19 +++--- .../classic_bt/bt_discovery/main/main.c | 9 +-- .../bt_l2cap_client/main/bt_app_core.c | 29 +++++++-- .../bt_l2cap_client/main/bt_app_core.h | 16 ++++- .../classic_bt/bt_l2cap_client/main/main.c | 6 +- .../bt_l2cap_server/main/bt_app_core.c | 29 +++++++-- .../bt_l2cap_server/main/bt_app_core.h | 16 ++++- .../classic_bt/bt_l2cap_server/main/main.c | 4 +- .../bt_spp_initiator/main/console_uart.c | 16 +++-- .../bt_spp_vfs_acceptor/main/main.c | 2 +- .../bt_spp_vfs_acceptor/main/spp_task.c | 27 +++++++- .../bt_spp_vfs_acceptor/main/spp_task.h | 11 +++- .../bt_spp_vfs_initiator/main/main.c | 2 +- .../bt_spp_vfs_initiator/main/spp_task.c | 27 +++++++- .../bt_spp_vfs_initiator/main/spp_task.h | 11 +++- .../audio_sink_service_dac.c | 65 ++++++++++++++----- .../audio_sink_service_i2s.c | 55 ++++++++++++---- .../avrcp_abs_vol_service.c | 10 ++- .../avrcp_abs_vol_utils/avrcp_abs_vol_utils.c | 2 +- .../avrcp_common_utils/avrcp_common_utils.c | 24 +++++-- .../avrcp_common_utils/avrcp_common_utils.h | 9 ++- .../avrcp_cover_art_service.c | 12 +++- .../avrcp_cover_art_utils.c | 12 ++-- .../avrcp_metadata_service.c | 4 ++ .../avrcp_metadata_utils.c | 14 ++-- .../common/bt_app_core_utils/CMakeLists.txt | 1 + .../bt_app_core_utils/bt_app_core_utils.c | 29 +++++++-- .../bt_app_core_utils/bt_app_core_utils.h | 14 +++- .../classic_bt/hfp_ag/main/bt_app_core.c | 29 +++++++-- .../classic_bt/hfp_ag/main/bt_app_core.h | 11 +++- .../classic_bt/hfp_ag/main/bt_app_hf.c | 2 + .../bluedroid/classic_bt/hfp_ag/main/main.c | 2 +- .../classic_bt/hfp_hf/main/bt_app_core.c | 29 +++++++-- .../classic_bt/hfp_hf/main/bt_app_core.h | 11 +++- .../classic_bt/hfp_hf/main/bt_app_hf.c | 18 +++-- .../bluedroid/classic_bt/hfp_hf/main/main.c | 2 +- .../coex/a2dp_gatts_coex/main/bt_app_av.c | 15 +++-- .../coex/a2dp_gatts_coex/main/main.c | 2 +- 45 files changed, 532 insertions(+), 174 deletions(-) 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 680d13ad13d..3241b5f5033 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 @@ -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 */ @@ -75,7 +75,7 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); break; } case ESP_A2D_CONNECTION_STATE_EVT: @@ -83,9 +83,9 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_AUDIO_CFG_EVT: case ESP_A2D_SEP_REG_STATE_EVT: { #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE - bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #else - bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #endif break; } @@ -173,5 +173,5 @@ void app_main(void) bt_app_task_start_up(); /* bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL); } diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.c index 581104f2e48..6bdca650096 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.c +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -37,7 +37,7 @@ static TaskHandle_t s_bt_app_task_handle = NULL; static bool bt_app_send_msg(bt_app_msg_t *msg) { - if (msg == NULL) { + if (msg == NULL || s_bt_app_task_queue == NULL) { return false; } @@ -75,6 +75,9 @@ static void bt_app_task_handler(void *arg) } if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -85,7 +88,8 @@ static void bt_app_task_handler(void *arg) * EXTERN FUNCTION DEFINITIONS ********************************/ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback) { ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len); @@ -95,6 +99,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i msg.sig = BT_APP_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return bt_app_send_msg(&msg); @@ -105,7 +110,14 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i if (p_copy_cback) { p_copy_cback(msg.param, p_params, param_len); } - return bt_app_send_msg(&msg); + if (!bt_app_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } @@ -125,6 +137,15 @@ void bt_app_task_shut_down(void) s_bt_app_task_handle = NULL; } if (s_bt_app_task_queue) { + bt_app_msg_t msg; + while (xQueueReceive(s_bt_app_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(s_bt_app_task_queue); s_bt_app_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.h index 379eb289392..13219431c6e 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.h +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/bt_app_core.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -25,11 +25,19 @@ */ typedef void (* bt_app_cb_t) (uint16_t event, void *param); +/** + * @brief parameter deep-free function + * + * @param [in] p_param pointer to the parameter + */ + typedef void (* bt_app_free_cb_t) (void *p_param); + /* message to be sent */ typedef struct { uint16_t sig; /*!< signal to bt_app_task */ uint16_t event; /*!< message event id */ bt_app_cb_t cb; /*!< context switch callback */ + bt_app_free_cb_t free_cb; /*!< parameter deep-free function */ void *param; /*!< parameter area needs to be last */ } bt_app_msg_t; @@ -50,10 +58,12 @@ typedef void (* bt_app_copy_cb_t) (void *p_dest, void *p_src, int len); * @param [in] p_params pointer to the parameter * @param [in] param_len length of the parameter * @param [in] p_copy_cback parameter deep-copy function + * @param [in] p_free_cback parameter deep-free function * * @return true if work dispatch successfully, false otherwise */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback); /** * @brief start up the application task diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c index 54bba3d6804..77cbc2a6b3c 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_source/main/main.c @@ -360,7 +360,7 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) { - bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); } /* generate some random noise to simulate source audio */ @@ -380,7 +380,7 @@ static int32_t bt_app_a2d_data_cb(uint8_t *data, int32_t len) static void bt_app_a2d_heart_beat(TimerHandle_t arg) { - bt_app_work_dispatch(bt_app_av_sm_hdlr, BT_APP_HEART_BEAT_EVT, NULL, 0, NULL); + bt_app_work_dispatch(bt_app_av_sm_hdlr, BT_APP_HEART_BEAT_EVT, NULL, 0, NULL, NULL); } static void bt_app_av_sm_hdlr(uint16_t event, void *param) @@ -726,13 +726,12 @@ static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t switch (event) { case ESP_AVRC_CT_CONNECTION_STATE_EVT: case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: - case ESP_AVRC_CT_METADATA_RSP_EVT: case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: case ESP_AVRC_CT_REMOTE_FEATURES_EVT: case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: case ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT: case ESP_AVRC_CT_PROF_STATE_EVT: { - bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL, NULL); break; } default: { @@ -793,12 +792,6 @@ static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) rc->psth_rsp.key_state, rc->psth_rsp.rsp_code); break; } - /* when metadata responded, this event comes */ - case ESP_AVRC_CT_METADATA_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata response: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); - free(rc->meta_rsp.attr_text); - break; - } /* when notification changed, this event comes */ case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id); @@ -906,5 +899,5 @@ void app_main(void) ESP_LOGI(BT_AV_TAG, "Own address:[%s]", bda2str((uint8_t *)esp_bt_dev_get_address(), bda_str, sizeof(bda_str))); bt_app_task_start_up(); /* Bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_STACK_UP_EVT, NULL, 0, NULL); + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_STACK_UP_EVT, NULL, 0, NULL, NULL); } 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 a5c45d0e432..7ef35189bf5 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 @@ -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 */ @@ -89,7 +89,7 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); break; } case ESP_A2D_CONNECTION_STATE_EVT: @@ -98,12 +98,12 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_SEP_REG_STATE_EVT: { #if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE - bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #else - bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #endif #else - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #endif break; } @@ -130,16 +130,13 @@ static void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_ static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) { switch (event) { - case ESP_AVRC_CT_METADATA_RSP_EVT: case ESP_AVRC_CT_CONNECTION_STATE_EVT: case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: case ESP_AVRC_CT_REMOTE_FEATURES_EVT: case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: - case ESP_AVRC_CT_COVER_ART_STATE_EVT: - case ESP_AVRC_CT_COVER_ART_DATA_EVT: case ESP_AVRC_CT_PROF_STATE_EVT: { - bt_app_work_dispatch(bt_avrc_common_ct_evt_def_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + bt_app_work_dispatch(bt_avrc_common_ct_evt_def_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL, NULL); break; } default: @@ -155,13 +152,13 @@ static void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: case ESP_AVRC_TG_PROF_STATE_EVT: { - bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL, NULL); break; } case ESP_AVRC_TG_CONNECTION_STATE_EVT: case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { - bt_app_work_dispatch(bt_avrc_avc_tg_evt_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + bt_app_work_dispatch(bt_avrc_avc_tg_evt_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL, NULL); break; } default: @@ -247,5 +244,5 @@ void app_main(void) bt_app_task_start_up(); /* bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL); } 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 6683dc9306c..eff24138899 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 @@ -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 */ @@ -115,7 +115,7 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); break; } case ESP_A2D_CONNECTION_STATE_EVT: @@ -124,12 +124,12 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_SEP_REG_STATE_EVT: { #if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE - bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #else - bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #endif #else - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #endif break; } @@ -157,7 +157,8 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param { switch (event) { case ESP_AVRC_CT_METADATA_RSP_EVT: { - bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), bt_avrc_common_copy_metadata); + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), + bt_avrc_common_copy_metadata, bt_avrc_common_free_metadata); break; } case ESP_AVRC_CT_COVER_ART_DATA_EVT: { @@ -169,7 +170,7 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param ESP_LOGE(BT_RC_CT_TAG, "Cover Art Client get operation failed"); break; } - bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL, NULL); break; } case ESP_AVRC_CT_CONNECTION_STATE_EVT: @@ -179,7 +180,7 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: case ESP_AVRC_CT_COVER_ART_STATE_EVT: case ESP_AVRC_CT_PROF_STATE_EVT: - bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL, NULL); break; default: ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); @@ -197,7 +198,7 @@ void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: case ESP_AVRC_TG_PROF_STATE_EVT: - bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL, NULL); break; default: ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event); 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 00b2f538f15..87e32a7d887 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 @@ -129,5 +129,5 @@ void app_main(void) bt_app_task_start_up(); /* bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL); } 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 92f7f5f7b45..0d094121305 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 @@ -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 */ @@ -92,7 +92,7 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); break; } case ESP_A2D_CONNECTION_STATE_EVT: @@ -101,12 +101,12 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_SEP_REG_STATE_EVT: { #if CONFIG_EXAMPLE_A2DP_SINK_STREAM_ENABLE #if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE - bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_int_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #else - bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_ext_codec_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #endif #else - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); #endif break; } @@ -183,7 +183,8 @@ static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t { switch (event) { case ESP_AVRC_CT_METADATA_RSP_EVT: { - bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), bt_avrc_common_copy_metadata); + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), + bt_avrc_common_copy_metadata, bt_avrc_common_free_metadata); break; } case ESP_AVRC_CT_CONNECTION_STATE_EVT: @@ -192,7 +193,7 @@ static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t case ESP_AVRC_CT_REMOTE_FEATURES_EVT: case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: case ESP_AVRC_CT_PROF_STATE_EVT: - bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL, NULL); break; default: ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); @@ -210,7 +211,7 @@ static void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: case ESP_AVRC_TG_PROF_STATE_EVT: - bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL, NULL); break; default: ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event); @@ -291,5 +292,5 @@ void app_main(void) bt_app_task_start_up(); /* bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL); } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_discovery/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_discovery/main/main.c index 1169b184648..384dca582eb 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_discovery/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_discovery/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -124,7 +124,7 @@ static void update_device_info(esp_bt_gap_cb_param_t *param) uint8_t *bdname = NULL; uint8_t bdname_len = 0; uint8_t *eir = NULL; - uint8_t eir_len = 0; + int eir_len = 0; esp_bt_gap_dev_prop_t *p; ESP_LOGI(GAP_TAG, "Device found: %s", bda2str(param->disc_res.bda, bda_str, sizeof(bda_str))); @@ -177,8 +177,9 @@ static void update_device_info(esp_bt_gap_cb_param_t *param) p_dev->bdname_len = bdname_len; } if (eir_len > 0) { - memcpy(p_dev->eir, eir, eir_len); - p_dev->eir_len = eir_len; + uint8_t copy_len = (eir_len > ESP_BT_GAP_EIR_DATA_LEN) ? ESP_BT_GAP_EIR_DATA_LEN : eir_len; + memcpy(p_dev->eir, eir, copy_len); + p_dev->eir_len = copy_len; } if (p_dev->bdname_len == 0) { diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.c index ca7fe6d2aa2..4080389df0c 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -39,7 +39,7 @@ static TaskHandle_t s_bt_app_task_handle = NULL; /* handle of application task static bool bt_app_send_msg(bt_app_msg_t *msg) { - if (msg == NULL) { + if (msg == NULL || s_bt_app_task_queue == NULL) { return false; } @@ -77,6 +77,9 @@ static void bt_app_task_handler(void *arg) } /* switch (msg.sig) */ if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -87,7 +90,8 @@ static void bt_app_task_handler(void *arg) * EXTERNAL FUNCTION DEFINITIONS *******************************/ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback) { ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len); @@ -97,6 +101,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i msg.sig = BT_APP_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return bt_app_send_msg(&msg); @@ -107,7 +112,14 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i if (p_copy_cback) { p_copy_cback(msg.param, p_params, param_len); } - return bt_app_send_msg(&msg); + if (!bt_app_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } @@ -127,6 +139,15 @@ void bt_app_task_shut_down(void) s_bt_app_task_handle = NULL; } if (s_bt_app_task_queue) { + bt_app_msg_t msg; + while (xQueueReceive(s_bt_app_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(s_bt_app_task_queue); s_bt_app_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.h index 7627ae28d1b..a4db145fb80 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.h +++ b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/bt_app_core.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -25,6 +25,13 @@ */ typedef void (* bt_app_cb_t) (uint16_t event, void *param); +/** + * @brief parameter deep-free function + * + * @param [in] p_param pointer to parameter data + */ +typedef void (* bt_app_free_cb_t) (void *p_param); + /** * @brief handler for write and read */ @@ -35,6 +42,7 @@ typedef struct { uint16_t sig; /*!< signal to bt_app_task */ uint16_t event; /*!< message event id */ bt_app_cb_t cb; /*!< context switch callback */ + bt_app_free_cb_t free_cb;/*!< parameter deep-free function */ void *param; /*!< parameter area needs to be last */ } bt_app_msg_t; @@ -52,13 +60,15 @@ typedef void (* bt_app_copy_cb_t) (void *p_dest, void *p_src, int len); * * @param [in] p_cback callback function * @param [in] event event id - * @param [in] p_params callback paramters + * @param [in] p_params callback parameters * @param [in] param_len parameter length in byte * @param [in] p_copy_cback parameter deep-copy function + * @param [in] p_free_cback parameter deep-free function * * @return true if work dispatch successfully, false otherwise */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback); /** * @brief start up the application task diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/main.c index 0ee2eb869a4..2fe077e4d0b 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_client/main/main.c @@ -257,7 +257,7 @@ static void esp_bt_l2cap_cb(esp_bt_l2cap_cb_event_t event, esp_bt_l2cap_cb_param case ESP_BT_L2CAP_START_EVT: case ESP_BT_L2CAP_SRV_STOP_EVT: case ESP_BT_L2CAP_VFS_REGISTER_EVT: { - bt_app_work_dispatch(esp_hdl_bt_l2cap_cb_evt, event, param, sizeof(esp_bt_l2cap_cb_param_t), NULL); + bt_app_work_dispatch(esp_hdl_bt_l2cap_cb_evt, event, param, sizeof(esp_bt_l2cap_cb_param_t), NULL, NULL); break; } default: @@ -324,7 +324,7 @@ static void esp_sdp_cb(esp_sdp_cb_event_t event, esp_sdp_cb_param_t *param) case ESP_SDP_SEARCH_COMP_EVT: case ESP_SDP_CREATE_RECORD_COMP_EVT: case ESP_SDP_REMOVE_RECORD_COMP_EVT: { - bt_app_work_dispatch(esp_hdl_sdp_cb_evt, event, param, sizeof(esp_sdp_cb_param_t), NULL); + bt_app_work_dispatch(esp_hdl_sdp_cb_evt, event, param, sizeof(esp_sdp_cb_param_t), NULL, NULL); break; } default: @@ -359,7 +359,7 @@ static void esp_hdl_sdp_cb_evt(uint16_t event, void *p_param) break; case ESP_SDP_SEARCH_COMP_EVT: ESP_LOGI(SDP_TAG, "ESP_SDP_SEARCH_COMP_EVT: status:%d", sdp_param->search.status); - if (sdp_param->search.status == ESP_SDP_SUCCESS) { + if (sdp_param->search.status == ESP_SDP_SUCCESS && sdp_param->search.record_count > 0 && sdp_param->search.records) { ESP_LOGI(SDP_TAG, "Remote device address: %s", bda2str(sdp_param->search.remote_addr, bda_str, sizeof(bda_str))); ESP_LOGI(SDP_TAG, "Remote device record count: %d", sdp_param->search.record_count); ESP_LOGI(SDP_TAG, "Remote device rfcomm channel number: %"PRId32, sdp_param->search.records->hdr.rfcomm_channel_number); diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.c index ca7fe6d2aa2..4080389df0c 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -39,7 +39,7 @@ static TaskHandle_t s_bt_app_task_handle = NULL; /* handle of application task static bool bt_app_send_msg(bt_app_msg_t *msg) { - if (msg == NULL) { + if (msg == NULL || s_bt_app_task_queue == NULL) { return false; } @@ -77,6 +77,9 @@ static void bt_app_task_handler(void *arg) } /* switch (msg.sig) */ if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -87,7 +90,8 @@ static void bt_app_task_handler(void *arg) * EXTERNAL FUNCTION DEFINITIONS *******************************/ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback) { ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len); @@ -97,6 +101,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i msg.sig = BT_APP_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return bt_app_send_msg(&msg); @@ -107,7 +112,14 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i if (p_copy_cback) { p_copy_cback(msg.param, p_params, param_len); } - return bt_app_send_msg(&msg); + if (!bt_app_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } @@ -127,6 +139,15 @@ void bt_app_task_shut_down(void) s_bt_app_task_handle = NULL; } if (s_bt_app_task_queue) { + bt_app_msg_t msg; + while (xQueueReceive(s_bt_app_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(s_bt_app_task_queue); s_bt_app_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.h index 7627ae28d1b..a4db145fb80 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.h +++ b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/bt_app_core.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -25,6 +25,13 @@ */ typedef void (* bt_app_cb_t) (uint16_t event, void *param); +/** + * @brief parameter deep-free function + * + * @param [in] p_param pointer to parameter data + */ +typedef void (* bt_app_free_cb_t) (void *p_param); + /** * @brief handler for write and read */ @@ -35,6 +42,7 @@ typedef struct { uint16_t sig; /*!< signal to bt_app_task */ uint16_t event; /*!< message event id */ bt_app_cb_t cb; /*!< context switch callback */ + bt_app_free_cb_t free_cb;/*!< parameter deep-free function */ void *param; /*!< parameter area needs to be last */ } bt_app_msg_t; @@ -52,13 +60,15 @@ typedef void (* bt_app_copy_cb_t) (void *p_dest, void *p_src, int len); * * @param [in] p_cback callback function * @param [in] event event id - * @param [in] p_params callback paramters + * @param [in] p_params callback parameters * @param [in] param_len parameter length in byte * @param [in] p_copy_cback parameter deep-copy function + * @param [in] p_free_cback parameter deep-free function * * @return true if work dispatch successfully, false otherwise */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback); /** * @brief start up the application task diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/main.c index 454d3ada9d3..c6dceec32ba 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_l2cap_server/main/main.c @@ -164,7 +164,7 @@ static void esp_bt_l2cap_cb(esp_bt_l2cap_cb_event_t event, esp_bt_l2cap_cb_param case ESP_BT_L2CAP_START_EVT: case ESP_BT_L2CAP_SRV_STOP_EVT: case ESP_BT_L2CAP_VFS_REGISTER_EVT: { - bt_app_work_dispatch(esp_hdl_bt_l2cap_cb_evt, event, param, sizeof(esp_bt_l2cap_cb_param_t), NULL); + bt_app_work_dispatch(esp_hdl_bt_l2cap_cb_evt, event, param, sizeof(esp_bt_l2cap_cb_param_t), NULL, NULL); break; } default: @@ -239,7 +239,7 @@ static void esp_sdp_cb(esp_sdp_cb_event_t event, esp_sdp_cb_param_t *param) case ESP_SDP_SEARCH_COMP_EVT: case ESP_SDP_CREATE_RECORD_COMP_EVT: case ESP_SDP_REMOVE_RECORD_COMP_EVT: { - bt_app_work_dispatch(esp_hdl_sdp_cb_evt, event, param, sizeof(esp_sdp_cb_param_t), NULL); + bt_app_work_dispatch(esp_hdl_sdp_cb_evt, event, param, sizeof(esp_sdp_cb_param_t), NULL, NULL); break; } default: diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/console_uart.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/console_uart.c index 13a3ee4d87c..0ce6c71dc2c 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/console_uart.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/console_uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -49,7 +49,7 @@ static void console_uart_task(void *pvParameters) if ((tmp_buf = (uint8_t *)calloc(TMP_BUF_LEN, sizeof(uint8_t))) == NULL) { ESP_LOGE(TAG_CNSL,"temp buf malloc fail"); - return; + vTaskDelete(NULL); } for (;;) { @@ -118,8 +118,16 @@ esp_err_t console_uart_init(void) } uart_set_pin(CONSOLE_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); - uart_driver_install(CONSOLE_UART_NUM, 1024, 1024, 8, &uart_queue, 0); - xTaskCreate(console_uart_task, "uTask", 4 * 1024, NULL, 8, NULL); + ret = uart_driver_install(CONSOLE_UART_NUM, 1024, 1024, 8, &uart_queue, 0); + if (ret != ESP_OK) { + ESP_LOGE(TAG_CNSL, "Uart %d driver install err %04x", CONSOLE_UART_NUM, ret); + return ret; + } + if (xTaskCreate(console_uart_task, "uTask", 4 * 1024, NULL, 8, NULL) != pdPASS) { + ESP_LOGE(TAG_CNSL, "Create console task failed"); + uart_driver_delete(CONSOLE_UART_NUM); + return ESP_FAIL; + } return ESP_OK; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c index 6bf544f8f0a..3b0619bb39e 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c @@ -153,7 +153,7 @@ static void esp_spp_cb(uint16_t e, void *p) static void esp_spp_stack_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) { /* To avoid stucking Bluetooth stack, we dispatch the SPP callback event to the other lower priority task */ - spp_task_work_dispatch(esp_spp_cb, event, param, sizeof(esp_spp_cb_param_t), NULL); + spp_task_work_dispatch(esp_spp_cb, event, param, sizeof(esp_spp_cb_param_t), NULL, NULL); } void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.c index 4bb4f234782..48605e2ae42 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -21,7 +21,8 @@ static void spp_task_work_dispatched(spp_task_msg_t *msg); static QueueHandle_t spp_task_task_queue = NULL; static TaskHandle_t spp_task_task_handle = NULL; -bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, spp_task_copy_cb_t p_copy_cback) +bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, + spp_task_copy_cb_t p_copy_cback, spp_task_free_cb_t p_free_cback) { ESP_LOGD(SPP_TASK_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); @@ -31,6 +32,7 @@ bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_param msg.sig = SPP_TASK_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return spp_task_send_msg(&msg); @@ -41,7 +43,14 @@ bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_param if (p_copy_cback) { p_copy_cback(&msg, msg.param, p_params); } - return spp_task_send_msg(&msg); + if (!spp_task_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } @@ -84,6 +93,9 @@ static void spp_task_task_handler(void *arg) } if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -104,6 +116,15 @@ void spp_task_task_shut_down(void) spp_task_task_handle = NULL; } if (spp_task_task_queue) { + spp_task_msg_t msg; + while (xQueueReceive(spp_task_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(spp_task_task_queue); spp_task_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.h b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.h index c0810cd79a9..cb1a08b1715 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.h +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/spp_task.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -20,11 +20,17 @@ */ typedef void (* spp_task_cb_t) (uint16_t event, void *param); +/** + * @brief parameter deep-free function + */ +typedef void (* spp_task_free_cb_t) (void *p_param); + /* message to be sent */ typedef struct { uint16_t sig; /*!< signal to spp_task_task */ uint16_t event; /*!< message event id */ spp_task_cb_t cb; /*!< context switch callback */ + spp_task_free_cb_t free_cb; /*!< parameter deep-free function */ void *param; /*!< parameter area needs to be last */ } spp_task_msg_t; @@ -36,7 +42,8 @@ typedef void (* spp_task_copy_cb_t) (spp_task_msg_t *msg, void *p_dest, void *p_ /** * @brief work dispatcher for the application task */ -bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, spp_task_copy_cb_t p_copy_cback); +bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, + spp_task_copy_cb_t p_copy_cback, spp_task_free_cb_t p_free_cback); void spp_task_task_start_up(void); diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c index ab64f6367cf..b0661bdc111 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c @@ -290,7 +290,7 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa static void esp_spp_stack_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) { /* To avoid stucking Bluetooth stack, we dispatch the SPP callback event to the other lower priority task */ - spp_task_work_dispatch(esp_spp_cb, event, param, sizeof(esp_spp_cb_param_t), NULL); + spp_task_work_dispatch(esp_spp_cb, event, param, sizeof(esp_spp_cb_param_t), NULL, NULL); } void app_main(void) diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.c index 4bb4f234782..48605e2ae42 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -21,7 +21,8 @@ static void spp_task_work_dispatched(spp_task_msg_t *msg); static QueueHandle_t spp_task_task_queue = NULL; static TaskHandle_t spp_task_task_handle = NULL; -bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, spp_task_copy_cb_t p_copy_cback) +bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, + spp_task_copy_cb_t p_copy_cback, spp_task_free_cb_t p_free_cback) { ESP_LOGD(SPP_TASK_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); @@ -31,6 +32,7 @@ bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_param msg.sig = SPP_TASK_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return spp_task_send_msg(&msg); @@ -41,7 +43,14 @@ bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_param if (p_copy_cback) { p_copy_cback(&msg, msg.param, p_params); } - return spp_task_send_msg(&msg); + if (!spp_task_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } @@ -84,6 +93,9 @@ static void spp_task_task_handler(void *arg) } if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -104,6 +116,15 @@ void spp_task_task_shut_down(void) spp_task_task_handle = NULL; } if (spp_task_task_queue) { + spp_task_msg_t msg; + while (xQueueReceive(spp_task_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(spp_task_task_queue); spp_task_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.h b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.h index c0810cd79a9..cb1a08b1715 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.h +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/spp_task.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -20,11 +20,17 @@ */ typedef void (* spp_task_cb_t) (uint16_t event, void *param); +/** + * @brief parameter deep-free function + */ +typedef void (* spp_task_free_cb_t) (void *p_param); + /* message to be sent */ typedef struct { uint16_t sig; /*!< signal to spp_task_task */ uint16_t event; /*!< message event id */ spp_task_cb_t cb; /*!< context switch callback */ + spp_task_free_cb_t free_cb; /*!< parameter deep-free function */ void *param; /*!< parameter area needs to be last */ } spp_task_msg_t; @@ -36,7 +42,8 @@ typedef void (* spp_task_copy_cb_t) (spp_task_msg_t *msg, void *p_dest, void *p_ /** * @brief work dispatcher for the application task */ -bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, spp_task_copy_cb_t p_copy_cback); +bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, + spp_task_copy_cb_t p_copy_cback, spp_task_free_cb_t p_free_cback); void spp_task_task_start_up(void); diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_dac.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_dac.c index 0e5e377c4ca..44132db0df8 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_dac.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_dac.c @@ -67,7 +67,9 @@ static void audio_sink_srv_dac_task_handler(void *arg) break; } - dac_continuous_write(s_dac_cb.tx_chan, data, item_size, &bytes_written, -1); + if (s_dac_cb.chan_st == CHANNEL_STATUS_ENABLED) { + dac_continuous_write(s_dac_cb.tx_chan, data, item_size, &bytes_written, -1); + } vRingbufferReturnItem(s_dac_cb.ringbuf, (void *)data); } } @@ -80,7 +82,10 @@ static void audio_sink_srv_dac_task_handler(void *arg) void audio_sink_srv_open(void) { - memset(&s_dac_cb, 0, sizeof(audio_sink_srv_dac_cb_t)); + if (s_dac_cb.chan_st != CHANNEL_STATUS_IDLE) { + ESP_LOGW(AUDIO_SNK_SRV_DAC_TAG, "Service already opened"); + return; + } dac_continuous_config_t cont_cfg = { .chan_mask = DAC_CHANNEL_MASK_ALL, .desc_num = 8, @@ -91,7 +96,11 @@ void audio_sink_srv_open(void) .chan_mode = DAC_CHANNEL_MODE_ALTER, }; /* Allocate continuous channels */ - ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &s_dac_cb.tx_chan)); + esp_err_t ret = dac_continuous_new_channels(&cont_cfg, &s_dac_cb.tx_chan); + if (ret != ESP_OK) { + ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "Failed to create DAC channels: %s", esp_err_to_name(ret)); + return; + } s_dac_cb.chan_st = CHANNEL_STATUS_OPENED; } @@ -99,10 +108,6 @@ void audio_sink_srv_close(void) { audio_sink_srv_stop(); - if (s_dac_cb.chan_st == CHANNEL_STATUS_OPENED) { - ESP_ERROR_CHECK(dac_continuous_del_channels(s_dac_cb.tx_chan)); - s_dac_cb.chan_st = CHANNEL_STATUS_IDLE; - } if (s_dac_cb.write_task_handle) { vTaskDelete(s_dac_cb.write_task_handle); s_dac_cb.write_task_handle = NULL; @@ -115,6 +120,10 @@ void audio_sink_srv_close(void) vSemaphoreDelete(s_dac_cb.write_semaphore); s_dac_cb.write_semaphore = NULL; } + if (s_dac_cb.chan_st == CHANNEL_STATUS_OPENED) { + ESP_ERROR_CHECK(dac_continuous_del_channels(s_dac_cb.tx_chan)); + s_dac_cb.chan_st = CHANNEL_STATUS_IDLE; + } memset(&s_dac_cb, 0, sizeof(audio_sink_srv_dac_cb_t)); } @@ -125,19 +134,37 @@ void audio_sink_srv_start(void) return; } ESP_ERROR_CHECK(dac_continuous_enable(s_dac_cb.tx_chan)); - s_dac_cb.chan_st = CHANNEL_STATUS_ENABLED; ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer data empty! mode changed: RINGBUFFER_MODE_PREFETCHING"); s_dac_cb.ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; - if ((s_dac_cb.write_semaphore = xSemaphoreCreateBinary()) == NULL) { + if ((s_dac_cb.write_semaphore == NULL) && ((s_dac_cb.write_semaphore = xSemaphoreCreateBinary()) == NULL)) { ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "%s, Semaphore create failed", __func__); - return; + goto err_sem; } - if ((s_dac_cb.ringbuf = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) { + if ((s_dac_cb.ringbuf == NULL) && + ((s_dac_cb.ringbuf = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL)) { ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "%s, ringbuffer create failed", __func__); - return; + goto err_rb; } - xTaskCreate(audio_sink_srv_dac_task_handler, "BtDACTask", 4 * 1024, NULL, configMAX_PRIORITIES - 3, &s_dac_cb.write_task_handle); + + if (s_dac_cb.write_task_handle == NULL) { + if (xTaskCreate(audio_sink_srv_dac_task_handler, "BtDACTask", 4 * 1024, NULL, + configMAX_PRIORITIES - 3, &s_dac_cb.write_task_handle) != pdPASS) { + ESP_LOGE(AUDIO_SNK_SRV_DAC_TAG, "%s, Task create failed", __func__); + goto err_task; + } + } + s_dac_cb.chan_st = CHANNEL_STATUS_ENABLED; + return; + +err_task: + vRingbufferDelete(s_dac_cb.ringbuf); + s_dac_cb.ringbuf = NULL; +err_rb: + vSemaphoreDelete(s_dac_cb.write_semaphore); + s_dac_cb.write_semaphore = NULL; +err_sem: + dac_continuous_disable(s_dac_cb.tx_chan); } void audio_sink_srv_stop(void) @@ -151,6 +178,7 @@ void audio_sink_srv_stop(void) void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) { ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "A2DP audio stream configuration, codec type: %d", mcc->type); + audio_sink_srv_stop(); /* for now only SBC stream is supported */ if (mcc->type == ESP_A2D_MCT_SBC) { int sample_rate = 16000; @@ -166,7 +194,10 @@ void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) if (mcc->cie.sbc_info.ch_mode & ESP_A2D_SBC_CIE_CH_MODE_MONO) { ch_count = 1; } - dac_continuous_del_channels(s_dac_cb.tx_chan); + if (s_dac_cb.tx_chan) { + dac_continuous_del_channels(s_dac_cb.tx_chan); + s_dac_cb.tx_chan = NULL; + } dac_continuous_config_t cont_cfg = { .chan_mask = DAC_CHANNEL_MASK_ALL, .desc_num = 8, @@ -177,7 +208,7 @@ void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) .chan_mode = (ch_count == 1) ? DAC_CHANNEL_MODE_SIMUL : DAC_CHANNEL_MODE_ALTER, }; /* Allocate continuous channels */ - dac_continuous_new_channels(&cont_cfg, &s_dac_cb.tx_chan); + ESP_ERROR_CHECK(dac_continuous_new_channels(&cont_cfg, &s_dac_cb.tx_chan)); ESP_LOGI(AUDIO_SNK_SRV_DAC_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", mcc->cie.sbc_info.samp_freq, mcc->cie.sbc_info.ch_mode, @@ -195,6 +226,10 @@ size_t audio_sink_srv_data_output(const uint8_t *data, size_t size) size_t item_size = 0; BaseType_t done = pdFALSE; + if (s_dac_cb.ringbuf == NULL) { + return 0; + } + if (s_dac_cb.ringbuffer_mode == RINGBUFFER_MODE_DROPPING) { ESP_LOGW(AUDIO_SNK_SRV_DAC_TAG, "ringbuffer is full, drop this packet!"); vRingbufferGetInfo(s_dac_cb.ringbuf, NULL, NULL, NULL, NULL, &item_size); diff --git a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_i2s.c b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_i2s.c index dc53afe2b1a..9049d74710f 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_i2s.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/a2dp_utils/a2dp_sink_int_codec_utils/audio_sink_service_i2s.c @@ -72,7 +72,9 @@ static void audio_sink_srv_i2s_task_handler(void *arg) break; } - i2s_channel_write(s_i2s_cb.tx_chan, data, item_size, &bytes_written, portMAX_DELAY); + if (s_i2s_cb.chan_st == CHANNEL_STATUS_ENABLED) { + i2s_channel_write(s_i2s_cb.tx_chan, data, item_size, &bytes_written, portMAX_DELAY); + } vRingbufferReturnItem(s_i2s_cb.ringbuf, (void *)data); } } @@ -85,7 +87,10 @@ static void audio_sink_srv_i2s_task_handler(void *arg) void audio_sink_srv_open(void) { - memset(&s_i2s_cb, 0, sizeof(audio_sink_srv_i2s_cb_t)); + if (s_i2s_cb.chan_st != CHANNEL_STATUS_IDLE) { + ESP_LOGW(AUDIO_SNK_SRV_I2S_TAG, "Service already open, skipping initialization"); + return; + } i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); chan_cfg.auto_clear = true; i2s_std_config_t std_cfg = { @@ -114,10 +119,6 @@ void audio_sink_srv_close(void) { audio_sink_srv_stop(); - if (s_i2s_cb.chan_st == CHANNEL_STATUS_OPENED) { - ESP_ERROR_CHECK(i2s_del_channel(s_i2s_cb.tx_chan)); - s_i2s_cb.chan_st = CHANNEL_STATUS_IDLE; - } if (s_i2s_cb.write_task_handle) { vTaskDelete(s_i2s_cb.write_task_handle); s_i2s_cb.write_task_handle = NULL; @@ -130,6 +131,10 @@ void audio_sink_srv_close(void) vSemaphoreDelete(s_i2s_cb.write_semaphore); s_i2s_cb.write_semaphore = NULL; } + if (s_i2s_cb.chan_st == CHANNEL_STATUS_OPENED) { + ESP_ERROR_CHECK(i2s_del_channel(s_i2s_cb.tx_chan)); + s_i2s_cb.chan_st = CHANNEL_STATUS_IDLE; + } memset(&s_i2s_cb, 0, sizeof(audio_sink_srv_i2s_cb_t)); } @@ -140,19 +145,36 @@ void audio_sink_srv_start(void) return; } ESP_ERROR_CHECK(i2s_channel_enable(s_i2s_cb.tx_chan)); - s_i2s_cb.chan_st = CHANNEL_STATUS_ENABLED; ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer data empty! mode changed: RINGBUFFER_MODE_PREFETCHING"); s_i2s_cb.ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING; - if ((s_i2s_cb.write_semaphore = xSemaphoreCreateBinary()) == NULL) { + if ((s_i2s_cb.write_semaphore == NULL) && (s_i2s_cb.write_semaphore = xSemaphoreCreateBinary()) == NULL) { ESP_LOGE(AUDIO_SNK_SRV_I2S_TAG, "%s, Semaphore create failed", __func__); - return; + goto err_sem; } - if ((s_i2s_cb.ringbuf = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) { + if ((s_i2s_cb.ringbuf == NULL) && + (s_i2s_cb.ringbuf = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) { ESP_LOGE(AUDIO_SNK_SRV_I2S_TAG, "%s, ringbuffer create failed", __func__); - return; + goto err_rb; } - xTaskCreate(audio_sink_srv_i2s_task_handler, "BtI2STask", 4 * 1024, NULL, configMAX_PRIORITIES - 3, &s_i2s_cb.write_task_handle); + if (s_i2s_cb.write_task_handle == NULL) { + if (xTaskCreate(audio_sink_srv_i2s_task_handler, "BtI2STask", 4 * 1024, NULL, + configMAX_PRIORITIES - 3, &s_i2s_cb.write_task_handle) != pdPASS) { + ESP_LOGE(AUDIO_SNK_SRV_I2S_TAG, "%s, Task create failed", __func__); + goto err_task; + } + } + s_i2s_cb.chan_st = CHANNEL_STATUS_ENABLED; + return; + +err_task: + vRingbufferDelete(s_i2s_cb.ringbuf); + s_i2s_cb.ringbuf = NULL; +err_rb: + vSemaphoreDelete(s_i2s_cb.write_semaphore); + s_i2s_cb.write_semaphore = NULL; +err_sem: + i2s_channel_disable(s_i2s_cb.tx_chan); } void audio_sink_srv_stop(void) @@ -166,6 +188,7 @@ void audio_sink_srv_stop(void) void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) { ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "A2DP audio stream configuration, codec type: %d", mcc->type); + audio_sink_srv_stop(); /* for now only SBC stream is supported */ if (mcc->type == ESP_A2D_MCT_SBC) { int sample_rate = 16000; @@ -183,8 +206,8 @@ void audio_sink_srv_codec_info_update(esp_a2d_mcc_t *mcc) } i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(sample_rate); i2s_std_slot_config_t slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, ch_count); - i2s_channel_reconfig_std_clock(s_i2s_cb.tx_chan, &clk_cfg); - i2s_channel_reconfig_std_slot(s_i2s_cb.tx_chan, &slot_cfg); + ESP_ERROR_CHECK(i2s_channel_reconfig_std_clock(s_i2s_cb.tx_chan, &clk_cfg)); + ESP_ERROR_CHECK(i2s_channel_reconfig_std_slot(s_i2s_cb.tx_chan, &slot_cfg)); ESP_LOGI(AUDIO_SNK_SRV_I2S_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", mcc->cie.sbc_info.samp_freq, mcc->cie.sbc_info.ch_mode, @@ -202,6 +225,10 @@ size_t audio_sink_srv_data_output(const uint8_t *data, size_t size) size_t item_size = 0; BaseType_t done = pdFALSE; + if (s_i2s_cb.ringbuf == NULL) { + return 0; + } + if (s_i2s_cb.ringbuffer_mode == RINGBUFFER_MODE_DROPPING) { ESP_LOGW(AUDIO_SNK_SRV_I2S_TAG, "ringbuffer is full, drop this packet!"); vRingbufferGetInfo(s_i2s_cb.ringbuf, NULL, NULL, NULL, NULL, &item_size); diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.c index 889b2651115..ace645d8cd1 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_service.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 */ @@ -33,11 +33,17 @@ static avrc_abs_vol_srv_cb_t s_avrc_abs_vol_srv_cb; void avrc_abs_vol_srv_open(void) { - memset(&s_avrc_abs_vol_srv_cb, 0, sizeof(avrc_abs_vol_srv_cb_t)); + if (s_avrc_abs_vol_srv_cb.volume_lock) { + _lock_close(&s_avrc_abs_vol_srv_cb.volume_lock); + } + _lock_init(&s_avrc_abs_vol_srv_cb.volume_lock); + s_avrc_abs_vol_srv_cb.volume = 0; + s_avrc_abs_vol_srv_cb.volume_notify = false; } void avrc_abs_vol_srv_close(void) { + _lock_close(&s_avrc_abs_vol_srv_cb.volume_lock); memset(&s_avrc_abs_vol_srv_cb, 0, sizeof(avrc_abs_vol_srv_cb_t)); } diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.c index 0a41ae063a4..ee84b1b9827 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_abs_vol_utils/avrcp_abs_vol_utils.c @@ -72,11 +72,11 @@ void bt_avrc_avc_tg_evt_hdl(uint16_t event, void *param) avrc_abs_vol_srv_open(); xTaskCreate(volume_change_simulation, "vcsTask", 4 * 1024, NULL, 5, &s_vcs_task_hdl); } else { - avrc_abs_vol_srv_close(); if (s_vcs_task_hdl) { vTaskDelete(s_vcs_task_hdl); s_vcs_task_hdl = NULL; } + avrc_abs_vol_srv_close(); ESP_LOGI(BT_RC_TG_TAG, "Stop volume change simulation"); } break; diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.c index 6f3ae6801e4..9931a8556b0 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.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 */ @@ -54,7 +54,11 @@ void bt_avrc_common_ct_evt_def_hdl(uint16_t event, void *param) } /* when metadata response, this event comes */ case ESP_AVRC_CT_METADATA_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + if (rc->meta_rsp.attr_text) { + ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + } else { + ESP_LOGE(BT_RC_CT_TAG, "AVRC metadata rsp: attr_text NULL"); + } break; } /* when notified, this event comes */ @@ -161,8 +165,20 @@ void bt_avrc_common_copy_metadata(void *p_dest, void *p_src, int len) p_dest_rc->meta_rsp.attr_length = p_src_rc->meta_rsp.attr_length; p_dest_rc->meta_rsp.attr_text = (uint8_t *) malloc(p_dest_rc->meta_rsp.attr_length + 1); - memcpy(p_dest_rc->meta_rsp.attr_text, p_src_rc->meta_rsp.attr_text, p_dest_rc->meta_rsp.attr_length); - p_dest_rc->meta_rsp.attr_text[p_dest_rc->meta_rsp.attr_length] = 0; + if (p_dest_rc->meta_rsp.attr_text) { + memcpy(p_dest_rc->meta_rsp.attr_text, p_src_rc->meta_rsp.attr_text, p_dest_rc->meta_rsp.attr_length); + p_dest_rc->meta_rsp.attr_text[p_dest_rc->meta_rsp.attr_length] = 0; + } +} + +void bt_avrc_common_free_metadata(void *p_param) +{ + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)p_param; + + if (rc && rc->meta_rsp.attr_text) { + free(rc->meta_rsp.attr_text); + rc->meta_rsp.attr_text = NULL; + } } void bt_avrc_common_ct_get_peer_rn_cap(void) diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.h index e7d4c00fb8c..7392c75c2a9 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.h +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils/avrcp_common_utils.h @@ -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 */ @@ -44,6 +44,13 @@ uint8_t bt_avrc_common_alloc_tl(void); */ void bt_avrc_common_copy_metadata(void *p_dest, void *p_src, int len); +/** + * @brief AVRCP deep free function for copied metadata + * + * @param [in] p_param pointer to copied callback parameter + */ +void bt_avrc_common_free_metadata(void *p_param); + /** * @brief AVRCP controller get notification capabilities command */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c index bd837329f6a..5ee9120badc 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_service.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 */ @@ -181,6 +181,11 @@ static void avrc_cover_art_srv_init_display(void) static void avrc_cover_art_srv_deinit_display(void) { + /* Check if initialized by looking at handles */ + if (s_avrc_cover_art_srv_cb.panel_handle == NULL && s_avrc_cover_art_srv_cb.io_handle == NULL) { + return; + } + /* Turn off backlight first */ ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL)); @@ -320,6 +325,11 @@ void avrc_cover_art_srv_ca_req(void) void avrc_cover_art_srv_save_image_data(uint8_t *p_data, uint16_t data_len) { + if (s_avrc_cover_art_srv_cb.image_size > UINT32_MAX - data_len) { + ESP_LOGE(RC_CA_SRV_TAG, "Image size overflow"); + avrc_cover_art_srv_free_image_data(); + return; + } s_avrc_cover_art_srv_cb.image_size += data_len; uint8_t *p_buf = (uint8_t *)realloc(s_avrc_cover_art_srv_cb.image_data, s_avrc_cover_art_srv_cb.image_size * sizeof(uint8_t)); diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.c index 1d9eeefaf88..d09a851cec1 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_cover_art_utils/avrcp_cover_art_utils.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 */ @@ -34,9 +34,13 @@ void bt_avrc_ca_ct_evt_hdl(uint16_t event, void *param) } /* when metadata response, this event comes */ case ESP_AVRC_CT_METADATA_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); - if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_COVER_ART) { - avrc_cover_art_srv_ct_metadata_update(rc->meta_rsp.attr_text, rc->meta_rsp.attr_length); + if (rc->meta_rsp.attr_text) { + ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_COVER_ART) { + avrc_cover_art_srv_ct_metadata_update(rc->meta_rsp.attr_text, rc->meta_rsp.attr_length); + } + } else { + ESP_LOGE(BT_RC_CT_TAG, "AVRC metadata rsp: attr_text NULL"); } break; } diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.c index 271311afb12..7ec9161f846 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_service.c @@ -34,6 +34,10 @@ static avrc_metadata_srv_cb_t s_avrc_metadata_srv_cb; static void avrc_metadata_srv_copy_metadata(avrc_metadata_srv_param_t *p_dest, avrc_metadata_srv_param_t *p_src) { + if (p_src->attr_length < 0) { + ESP_LOGE(RC_MD_SRV_TAG, "Invalid attribute length: %d", p_src->attr_length); + return; + } p_dest->attr_id = p_src->attr_id; p_dest->attr_length = p_src->attr_length; diff --git a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.c index 5516db7d4e3..020bbd46a62 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_metadata_utils/avrcp_metadata_utils.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 */ @@ -46,10 +46,14 @@ void bt_avrc_md_ct_evt_hdl(uint16_t event, void *param) } /* when metadata response, this event comes */ case ESP_AVRC_CT_METADATA_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); - /* save metadata to avrcp metadata service and then if there is a need to handle metadata, - functions can be added in the avrcp metadata service for processing */ - avrc_metadata_srv_md_save((avrc_metadata_srv_param_t *)rc); + if (rc->meta_rsp.attr_text) { + ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + /* save metadata to avrcp metadata service and then if there is a need to handle metadata, + functions can be added in the avrcp metadata service for processing */ + avrc_metadata_srv_md_save((avrc_metadata_srv_param_t *)rc); + } else { + ESP_LOGE(BT_RC_CT_TAG, "AVRC metadata rsp: attr_text NULL"); + } break; } /* when notified, this event comes */ diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/CMakeLists.txt index 2f000acd2b0..12cdefebf14 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/CMakeLists.txt +++ b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/CMakeLists.txt @@ -1,2 +1,3 @@ idf_component_register(SRCS "bt_app_core_utils.c" + PRIV_REQUIRES bt INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.c b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.c index 514ce77f80d..3141ce04c95 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.c +++ b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.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 */ @@ -44,7 +44,7 @@ static TaskHandle_t s_bt_app_task_handle = NULL; /* handle of application task static bool bt_app_send_msg(bt_app_msg_t *msg) { - if (msg == NULL) { + if (msg == NULL || s_bt_app_task_queue == NULL) { return false; } @@ -82,6 +82,9 @@ static void bt_app_task_handler(void *arg) } /* switch (msg.sig) */ if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -92,7 +95,8 @@ static void bt_app_task_handler(void *arg) * EXTERNAL FUNCTION DEFINITIONS *******************************/ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback) { ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len); @@ -102,6 +106,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i msg.sig = BT_APP_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return bt_app_send_msg(&msg); @@ -112,7 +117,14 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i if (p_copy_cback) { p_copy_cback(msg.param, p_params, param_len); } - return bt_app_send_msg(&msg); + if (!bt_app_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } @@ -132,6 +144,15 @@ void bt_app_task_shut_down(void) s_bt_app_task_handle = NULL; } if (s_bt_app_task_queue) { + bt_app_msg_t msg; + while (xQueueReceive(s_bt_app_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(s_bt_app_task_queue); s_bt_app_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.h b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.h index 9161f08155a..5f5d729c767 100644 --- a/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.h +++ b/examples/bluetooth/bluedroid/classic_bt/common/bt_app_core_utils/bt_app_core_utils.h @@ -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 */ @@ -22,11 +22,19 @@ */ typedef void (* bt_app_cb_t)(uint16_t event, void *param); +/** + * @brief parameter deep-free function + * + * @param [in] p_param pointer to parameter data + */ +typedef void (* bt_app_free_cb_t)(void *p_param); + /* message to be sent */ typedef struct { uint16_t sig; /*!< signal to bt_app_task */ uint16_t event; /*!< message event id */ bt_app_cb_t cb; /*!< context switch callback */ + bt_app_free_cb_t free_cb;/*!< parameter deep-free function */ void *param; /*!< parameter area needs to be last */ } bt_app_msg_t; @@ -47,10 +55,12 @@ typedef void (* bt_app_copy_cb_t)(void *p_dest, void *p_src, int len); * @param [in] p_params callback parameters * @param [in] param_len parameter length in byte * @param [in] p_copy_cback parameter deep-copy function + * @param [in] p_free_cback parameter deep-free function * * @return true if work dispatch successfully, false otherwise */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback); /** * @brief start up the application task diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c index 2b8821a5674..fabd8bf1a8b 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -21,7 +21,8 @@ static void bt_app_work_dispatched(bt_app_msg_t *msg); static QueueHandle_t bt_app_task_queue = NULL; static TaskHandle_t bt_app_task_handle = NULL; -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback) { ESP_LOGD(BT_APP_CORE_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); @@ -31,6 +32,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i msg.sig = BT_APP_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return bt_app_send_msg(&msg); @@ -41,7 +43,14 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i if (p_copy_cback) { p_copy_cback(&msg, msg.param, p_params); } - return bt_app_send_msg(&msg); + if (!bt_app_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } return false; @@ -49,7 +58,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i static bool bt_app_send_msg(bt_app_msg_t *msg) { - if (msg == NULL) { + if (msg == NULL || bt_app_task_queue == NULL) { return false; } @@ -83,6 +92,9 @@ static void bt_app_task_handler(void *arg) } // switch (msg.sig) if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -103,6 +115,15 @@ void bt_app_task_shut_down(void) bt_app_task_handle = NULL; } if (bt_app_task_queue) { + bt_app_msg_t msg; + while (xQueueReceive(bt_app_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(bt_app_task_queue); bt_app_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h index 2e88bcdf7df..e7236ce4d98 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -20,11 +20,17 @@ */ typedef void (* bt_app_cb_t) (uint16_t event, void *param); +/** + * @brief parameter deep-free function + */ +typedef void (* bt_app_free_cb_t) (void *p_param); + /* message to be sent */ typedef struct { uint16_t sig; /*!< signal to bt_app_task */ uint16_t event; /*!< message event id */ bt_app_cb_t cb; /*!< context switch callback */ + bt_app_free_cb_t free_cb; /*!< parameter deep-free function */ void *param; /*!< parameter area needs to be last */ } bt_app_msg_t; @@ -36,7 +42,8 @@ typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src) /** * @brief work dispatcher for the application task */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback); void bt_app_task_start_up(void); diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c index d4b0defcc4e..07ee4b07916 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -279,6 +279,7 @@ void bt_app_send_data_shut_down(void) if(s_periodic_timer) { ESP_ERROR_CHECK(esp_timer_stop(s_periodic_timer)); ESP_ERROR_CHECK(esp_timer_delete(s_periodic_timer)); + s_periodic_timer = NULL; } if (s_send_data_Semaphore) { vSemaphoreDelete(s_send_data_Semaphore); @@ -286,6 +287,7 @@ void bt_app_send_data_shut_down(void) } if (s_m_rb) { vRingbufferDelete(s_m_rb); + s_m_rb = NULL; } return; } diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/main.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/main.c index eadb52f870f..0bf67f5efb5 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/main.c @@ -121,7 +121,7 @@ void app_main(void) bt_app_task_start_up(); /* Bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_hf_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + bt_app_work_dispatch(bt_hf_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL); #if CONFIG_BT_HFP_AUDIO_DATA_PATH_PCM /* configure the PCM interface and PINs used */ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.c index 3d0d8d11c6e..6a8fc1c3e3f 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -21,7 +21,8 @@ static void bt_app_work_dispatched(bt_app_msg_t *msg); static QueueHandle_t bt_app_task_queue = NULL; static TaskHandle_t bt_app_task_handle = NULL; -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback) { ESP_LOGD(BT_APP_CORE_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); @@ -31,6 +32,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i msg.sig = BT_APP_SIG_WORK_DISPATCH; msg.event = event; msg.cb = p_cback; + msg.free_cb = p_free_cback; if (param_len == 0) { return bt_app_send_msg(&msg); @@ -41,7 +43,14 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i if (p_copy_cback) { p_copy_cback(&msg, msg.param, p_params); } - return bt_app_send_msg(&msg); + if (!bt_app_send_msg(&msg)) { + if (p_free_cback) { + p_free_cback(msg.param); + } + free(msg.param); + return false; + } + return true; } } @@ -50,7 +59,7 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i static bool bt_app_send_msg(bt_app_msg_t *msg) { - if (msg == NULL) { + if (msg == NULL || bt_app_task_queue == NULL) { return false; } @@ -87,6 +96,9 @@ static void bt_app_task_handler(void *arg) } // switch (msg.sig) if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } free(msg.param); } } @@ -107,6 +119,15 @@ void bt_app_task_shut_down(void) bt_app_task_handle = NULL; } if (bt_app_task_queue) { + bt_app_msg_t msg; + while (xQueueReceive(bt_app_task_queue, &msg, 0) == pdTRUE) { + if (msg.param) { + if (msg.free_cb) { + msg.free_cb(msg.param); + } + free(msg.param); + } + } vQueueDelete(bt_app_task_queue); bt_app_task_queue = NULL; } diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.h index cdb942ca95d..a5450f99a39 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.h +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_core.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -20,11 +20,17 @@ */ typedef void (* bt_app_cb_t) (uint16_t event, void *param); +/** + * @brief parameter deep-free function + */ +typedef void (* bt_app_free_cb_t) (void *p_param); + /* message to be sent */ typedef struct { uint16_t sig; /*!< signal to bt_app_task */ uint16_t event; /*!< message event id */ bt_app_cb_t cb; /*!< context switch callback */ + bt_app_free_cb_t free_cb; /*!< parameter deep-free function */ void *param; /*!< parameter area needs to be the last */ } bt_app_msg_t; @@ -36,7 +42,8 @@ typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src) /** * @brief work dispatcher for the application task */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, + bt_app_copy_cb_t p_copy_cback, bt_app_free_cb_t p_free_cback); void bt_app_task_start_up(void); diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c index ade3f995b99..3f3f65bc8e5 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c @@ -160,9 +160,9 @@ const char *c_at_response_code_str[] = { // esp_hf_subscriber_service_type_t const char *c_subscriber_service_type_str[] = { - "unknown", - "voice", - "fax", + [ESP_HF_SUBSCRIBER_SERVICE_TYPE_UNKNOWN] = "unknown", + [ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE] = "voice", + [ESP_HF_SUBSCRIBER_SERVICE_TYPE_FAX] = "fax", }; // esp_hf_client_in_band_ring_state_t @@ -242,6 +242,7 @@ static void bt_app_hf_client_audio_close(void) } vRingbufferDelete(m_rb); + m_rb = NULL; } static uint32_t bt_app_hf_client_outgoing_cb(uint8_t *p_buf, uint32_t sz) @@ -329,11 +330,14 @@ void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_ } else if (param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED) { s_sync_conn_hdl = 0; s_msbc_air_mode = false; - esp_hf_audio_buff_t *buff_to_free = NULL; - while (xQueueReceive(s_audio_buff_queue, &buff_to_free, 0)) { - esp_hf_client_audio_buff_free(buff_to_free); + if (s_audio_buff_queue) { + esp_hf_audio_buff_t *buff_to_free = NULL; + while (xQueueReceive(s_audio_buff_queue, &buff_to_free, 0)) { + esp_hf_client_audio_buff_free(buff_to_free); + } + vQueueDelete(s_audio_buff_queue); + s_audio_buff_queue = NULL; } - vQueueDelete(s_audio_buff_queue); s_audio_buff_cnt = 0; } #else diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c index 230b72c9d2a..85bef1a6820 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c @@ -207,7 +207,7 @@ void app_main(void) bt_app_task_start_up(); /* Bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_hf_client_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + bt_app_work_dispatch(bt_hf_client_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL); #if CONFIG_BT_HFP_AUDIO_DATA_PATH_PCM /* configure the PCM interface and PINs used */ 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 7bed853682b..754ea42a82b 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 @@ -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 */ @@ -92,14 +92,14 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) 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); + 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: { - bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL); + bt_app_work_dispatch(bt_a2d_evt_def_hdl, event, param, sizeof(esp_a2d_cb_param_t), NULL, NULL); break; } default: @@ -117,7 +117,8 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param { switch (event) { case ESP_AVRC_CT_METADATA_RSP_EVT: { - bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), bt_avrc_common_copy_metadata); + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), + bt_avrc_common_copy_metadata, bt_avrc_common_free_metadata); break; } case ESP_AVRC_CT_CONNECTION_STATE_EVT: @@ -126,7 +127,7 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param case ESP_AVRC_CT_REMOTE_FEATURES_EVT: case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: case ESP_AVRC_CT_PROF_STATE_EVT: - bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + bt_app_work_dispatch(bt_app_avrc_ct_evt_hdl, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL, NULL); break; default: ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event); @@ -141,13 +142,13 @@ void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: case ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT: case ESP_AVRC_TG_PROF_STATE_EVT: { - bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + bt_app_work_dispatch(bt_avrc_common_tg_evt_def_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL, NULL); break; } case ESP_AVRC_TG_CONNECTION_STATE_EVT: case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT: case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { - bt_app_work_dispatch(bt_avrc_avc_tg_evt_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL); + bt_app_work_dispatch(bt_avrc_avc_tg_evt_hdl, event, param, sizeof(esp_avrc_tg_cb_param_t), NULL, NULL); break; } default: 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 4b9288eedb1..e5988c921ad 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/main.c @@ -732,7 +732,7 @@ void app_main(void) bt_app_task_start_up(); /* bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL); /* gatt server init */ ble_gatts_init();