Jelajahi Sumber

Merge branch 'bugfix/add_disconn_req_action_when_no_link_3_3' into 'release/v3.3'

component_bt/bugfix: add_disconn_req_action_when_no_link [backport v3.3]

See merge request espressif/esp-idf!11456
Jiang Jiang Jian 5 tahun lalu
induk
melakukan
a7ec2e6503

+ 8 - 2
components/bt/bluedroid/api/esp_a2dp_api.c

@@ -107,13 +107,15 @@ esp_err_t esp_a2d_sink_disconnect(esp_bd_addr_t remote_bda)
 
     bt_status_t stat;
     btc_msg_t msg;
+    btc_av_args_t arg;
 
     msg.sig = BTC_SIG_API_CALL;
     msg.pid = BTC_PID_A2DP;
     msg.act = BTC_AV_SINK_API_DISCONNECT_EVT;
 
     /* Switch to BTC context */
-    stat = btc_transfer_context(&msg, NULL, 0, NULL);
+    memcpy(&(arg.disconn), remote_bda, sizeof(bt_bdaddr_t));
+    stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL);
     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
 }
 
@@ -219,14 +221,18 @@ esp_err_t esp_a2d_source_disconnect(esp_bd_addr_t remote_bda)
     }
 
     bt_status_t stat;
+    btc_av_args_t arg;
     btc_msg_t msg;
 
     msg.sig = BTC_SIG_API_CALL;
     msg.pid = BTC_PID_A2DP;
     msg.act = BTC_AV_SRC_API_DISCONNECT_EVT;
 
+    memset(&arg, 0, sizeof(btc_av_args_t));
+
     /* Switch to BTC context */
-    stat = btc_transfer_context(&msg, NULL, 0, NULL);
+    memcpy(&(arg.src_disconn), remote_bda, sizeof(bt_bdaddr_t));
+    stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL);
     return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
 }
 

+ 2 - 5
components/bt/bluedroid/bta/av/bta_av_act.c

@@ -208,11 +208,8 @@ static void bta_av_rc_ctrl_cback(UINT8 handle, UINT8 event, UINT16 result, BD_AD
     UINT16 msg_event = 0;
     UNUSED(result);
 
-#if (defined(BTA_AV_MIN_DEBUG_TRACES) && BTA_AV_MIN_DEBUG_TRACES == TRUE)
-    APPL_TRACE_EVENT("rc_ctrl handle: %d event=0x%x", handle, event);
-#else
-    APPL_TRACE_EVENT("bta_av_rc_ctrl_cback handle: %d event=0x%x", handle, event);
-#endif
+    APPL_TRACE_EVENT("%s handle: %d event: 0x%x",__func__, handle, event);
+
     if (event == AVRC_OPEN_IND_EVT) {
         /* save handle of opened connection
         bta_av_cb.rc_handle = handle;*/

+ 0 - 10
components/bt/bluedroid/bta/av/bta_av_main.c

@@ -563,13 +563,8 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
             if (bta_av_cb.features & (BTA_AV_FEAT_RCTG)) {
                 /* register with no authorization; let AVDTP use authorization instead */
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
-#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
-                bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
-                                bta_av_cb.sec_mask, BTA_ID_AV);
-#else
                 bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
                                 (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV);
-#endif
                 if (p_data->api_reg.tsep == AVDT_TSEP_SRC) {
                     bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target\n", NULL,
                                 p_bta_av_cfg->avrc_src_tg_cat, BTA_ID_AV);
@@ -699,13 +694,8 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
                     /* if TG is not supported, we need to register to AVCT now */
                     if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0) {
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
-#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
-                        bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
-                                        bta_av_cb.sec_mask, BTA_ID_AV);
-#else
                         bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
                                         (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV);
-#endif
 #endif
                     }
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)

+ 1 - 8
components/bt/bluedroid/bta/include/bta/bta_av_api.h

@@ -36,12 +36,6 @@
 /*****************************************************************************
 **  Constants and data types
 *****************************************************************************/
-/* Set to TRUE if seperate authorization prompt desired for AVCTP besides A2DP authorization */
-/* Typically FALSE when AVRCP is used in conjunction with A2DP */
-#ifndef BTA_AV_WITH_AVCTP_AUTHORIZATION
-#define BTA_AV_WITH_AVCTP_AUTHORIZATION     FALSE
-#endif
-
 /* AV status values */
 #define BTA_AV_SUCCESS          0       /* successful operation */
 #define BTA_AV_FAIL             1       /* generic failure */
@@ -581,8 +575,7 @@ void BTA_AvDisable(void);
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name,
-                    UINT8 app_id, tBTA_AV_DATA_CBACK  *p_data_cback, tBTA_AV_CO_FUNCTS *bta_av_cos, UINT8 tsep);
+void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id, tBTA_AV_DATA_CBACK  *p_data_cback, tBTA_AV_CO_FUNCTS *bta_av_cos, UINT8 tsep);
 
 /*******************************************************************************
 **

+ 1 - 1
components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp.c

@@ -38,7 +38,7 @@
 *******************************************************************************/
 void btc_a2dp_on_init(void)
 {
-    //tput_mon(1, 0, 1);
+    BTC_TRACE_EVENT("A2DP Initialized.");
 }
 
 /*****************************************************************************

+ 0 - 2
components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c

@@ -1290,8 +1290,6 @@ BOOLEAN btc_media_aa_read_feeding(void)
     /* Read Data from data channel */
     nb_byte_read = btc_aa_src_data_read((uint8_t *)read_buffer, read_size);
 
-    //tput_mon(TRUE, nb_byte_read, FALSE);
-
     if (nb_byte_read < read_size) {
         APPL_TRACE_WARNING("### UNDERRUN :: ONLY READ %d BYTES OUT OF %d ###",
                            nb_byte_read, read_size);

+ 97 - 91
components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c

@@ -42,6 +42,13 @@
 
 #if BTC_AV_INCLUDED
 
+// global variable to inidcate avrc is initialized with a2dp
+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;
+
 /*****************************************************************************
 **  Constants & Macros
 ******************************************************************************/
@@ -86,6 +93,10 @@ typedef struct {
     uint16_t uuid;
 } btc_av_connect_req_t;
 
+typedef struct {
+    bt_bdaddr_t target_bda;
+} btc_av_disconn_req_t;
+
 /*****************************************************************************
 **  Static variables
 ******************************************************************************/
@@ -284,7 +295,7 @@ static void btc_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_
 
 static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
 {
-    BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
+    BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
               dump_av_sm_event_name(event), btc_av_cb.flags);
 
     switch (event) {
@@ -309,20 +320,34 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
     case BTA_AV_PENDING_EVT:
     case BTC_AV_CONNECT_REQ_EVT: {
         if (event == BTC_AV_CONNECT_REQ_EVT) {
-            memcpy(&btc_av_cb.peer_bda, &((btc_av_connect_req_t *)p_data)->target_bda,
-                   sizeof(bt_bdaddr_t));
-            BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
-                       TRUE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid);
+            memcpy(&btc_av_cb.peer_bda, &((btc_av_connect_req_t *)p_data)->target_bda, sizeof(bt_bdaddr_t));
+            if (g_av_with_rc) {
+                BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
+                        TRUE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid);
+            } else {
+                BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
+                        FALSE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid);
+            }
         } else if (event == BTA_AV_PENDING_EVT) {
             bdcpy(btc_av_cb.peer_bda.address, ((tBTA_AV *)p_data)->pend.bd_addr);
-            UINT16 uuid = (btc_av_cb.service_id == BTA_A2DP_SOURCE_SERVICE_ID) ? UUID_SERVCLASS_AUDIO_SOURCE :
-                UUID_SERVCLASS_AUDIO_SINK;
-            BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
-                       TRUE, BTA_SEC_AUTHENTICATE, uuid);
+            UINT16 uuid = (btc_av_cb.service_id == BTA_A2DP_SOURCE_SERVICE_ID) ? UUID_SERVCLASS_AUDIO_SOURCE : UUID_SERVCLASS_AUDIO_SINK;
+            if (g_av_with_rc) {
+                BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
+                        TRUE, BTA_SEC_AUTHENTICATE, uuid);
+            } else {
+                BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
+                       FALSE, BTA_SEC_AUTHENTICATE, uuid);
+            }
         }
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENING);
     } break;
 
+
+    case BTC_AV_DISCONNECT_REQ_EVT:
+        BTC_TRACE_WARNING("No Link At All.");
+        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0);
+        break;
+
     case BTA_AV_RC_OPEN_EVT:
         /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
          * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
@@ -333,7 +358,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
          *
          * TODO: We may need to do this only on an AVRCP Play. FixMe
          */
-
 #if BTC_AV_SRC_INCLUDED
         BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
         tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
@@ -361,15 +385,13 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
         break;
 
     default:
-        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
-                 dump_av_sm_event_name(event));
+        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
         return FALSE;
-
     }
-
     return TRUE;
 }
-/*****************************************************************************
+
+    /*****************************************************************************
 **
 ** Function        btc_av_state_opening_handler
 **
@@ -382,7 +404,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
 
 static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
 {
-    BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
+    BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
               dump_av_sm_event_name(event), btc_av_cb.flags);
 
     switch (event) {
@@ -395,35 +417,36 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
         break;
 
     case BTA_AV_REJECT_EVT:
-        BTC_TRACE_DEBUG(" Received  BTA_AV_REJECT_EVT \n");
+        BTC_TRACE_WARNING(" Received  BTA_AV_REJECT_EVT \n");
         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0);
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
 
     case BTA_AV_OPEN_EVT: {
         tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
-        esp_a2d_connection_state_t state;
+        esp_a2d_connection_state_t conn_stat;
         btc_sm_state_t av_state;
         BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status,
                         p_bta_data->open.edr, p_bta_data->open.sep);
 
         if (p_bta_data->open.status == BTA_AV_SUCCESS) {
-            state = ESP_A2D_CONNECTION_STATE_CONNECTED;
-            av_state = BTC_AV_STATE_OPENED;
             btc_av_cb.edr = p_bta_data->open.edr;
-
             btc_av_cb.peer_sep = p_bta_data->open.sep;
+
+            conn_stat = ESP_A2D_CONNECTION_STATE_CONNECTED;
+            av_state = BTC_AV_STATE_OPENED;
         } else {
-            BTC_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n",
-                     p_bta_data->open.status );
-            state = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
-            av_state  = BTC_AV_STATE_IDLE;
+            BTC_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n", p_bta_data->open.status );
+
+            conn_stat = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
+            av_state = BTC_AV_STATE_IDLE;
         }
 
         /* inform the application of the event */
-        btc_report_connection_state(state, &(btc_av_cb.peer_bda), 0);
+        btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), 0);
         /* change state to open/idle based on the status */
         btc_sm_change_state(btc_av_cb.sm_handle, av_state);
+
         if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
             /* if queued PLAY command,  send it now */
             /* necessary to add this?
@@ -432,8 +455,12 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
             */
         } else if (btc_av_cb.peer_sep == AVDT_TSEP_SRC &&
                    (p_bta_data->open.status == BTA_AV_SUCCESS)) {
-            /* Bring up AVRCP connection too */
-            BTA_AvOpenRc(btc_av_cb.bta_handle);
+            /* Bring up AVRCP connection too if AVRC Initialized */
+            if(g_av_with_rc) {
+                BTA_AvOpenRc(btc_av_cb.bta_handle);
+            } else {
+                BTC_TRACE_WARNING("AVRC not Init, not using it.");
+            }
         }
         btc_queue_advance();
     } break;
@@ -473,11 +500,10 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
             break;
         }
 
-        CHECK_RC_EVENT(event, p_data);
+    CHECK_RC_EVENT(event, p_data);
 
     default:
-        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
-                 dump_av_sm_event_name(event));
+        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
         return FALSE;
 
     }
@@ -498,7 +524,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
 
 static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
 {
-    BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
+    BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
               dump_av_sm_event_name(event), btc_av_cb.flags);
 
     switch (event) {
@@ -539,9 +565,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
     case BTA_AV_CLOSE_EVT: {
         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
         /* inform the application that we are disconnecting */
-        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
-                                    close->disc_rsn);
-
+        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn);
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
     }
@@ -552,14 +576,12 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
         break;
 
     default:
-        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
-                 dump_av_sm_event_name(event));
+        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
         return FALSE;
     }
     return TRUE;
 }
 
-
 /*****************************************************************************
 **
 ** Function     btc_av_state_opened_handler
@@ -569,12 +591,11 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
 ** Returns      TRUE if event was processed, FALSE otherwise
 **
 *******************************************************************************/
-
 static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
 {
     tBTA_AV *p_av = (tBTA_AV *)p_data;
 
-    BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
+     BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
               dump_av_sm_event_name(event), btc_av_cb.flags);
 
     if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btc_av_cb.flags & BTC_AV_FLAG_REMOTE_SUSPEND) &&
@@ -654,10 +675,9 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
 
     case BTC_AV_DISCONNECT_REQ_EVT:
         BTA_AvClose(btc_av_cb.bta_handle);
-        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
+        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC && g_av_with_rc == true) {
             BTA_AvCloseRc(btc_av_cb.bta_handle);
         }
-
         /* inform the application that we are disconnecting */
         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
         break;
@@ -665,17 +685,15 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
     case BTA_AV_CLOSE_EVT: {
         /* avdtp link is closed */
         btc_a2dp_on_stopped(NULL);
-
         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
         /* inform the application that we are disconnected */
-        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
-                                    close->disc_rsn);
-
+        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn);
         /* change state to idle, send acknowledgement if start is pending */
         if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
             btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
             /* pending start flag will be cleared when exit current state */
         }
+        /* change state to idle, send acknowledgement if start is pending */
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
     }
@@ -703,11 +721,10 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
         btc_queue_advance();
         break;
 
-        CHECK_RC_EVENT(event, p_data);
+    CHECK_RC_EVENT(event, p_data);
 
     default:
-        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
-                 dump_av_sm_event_name(event));
+        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
         return FALSE;
 
     }
@@ -728,27 +745,22 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
 {
     tBTA_AV *p_av = (tBTA_AV *)p_data;
 
-    BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
+    BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__,
               dump_av_sm_event_name(event), btc_av_cb.flags);
 
     switch (event) {
     case BTC_SM_ENTER_EVT:
-
         /* we are again in started state, clear any remote suspend flags */
         btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND;
-
         btc_report_audio_state(ESP_A2D_AUDIO_STATE_STARTED, &(btc_av_cb.peer_bda));
-
         /* increase the a2dp consumer task priority temporarily when start
         ** audio playing, to avoid overflow the audio packet queue. */
         // adjust_priority_a2dp(TRUE);
-
         break;
 
     case BTC_SM_EXIT_EVT:
         /* restore the a2dp consumer task priority when stop audio playing. */
         // adjust_priority_a2dp(FALSE);
-
         break;
 
     case BTC_AV_START_STREAM_REQ_EVT:
@@ -763,11 +775,9 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
     /* fixme -- use suspend = true always to work around issue with BTA AV */
     case BTC_AV_STOP_STREAM_REQ_EVT:
     case BTC_AV_SUSPEND_STREAM_REQ_EVT:
-
         /* set pending flag to ensure btc task is not trying to restart
            stream while suspend is in progress */
         btc_av_cb.flags |= BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
-
         /* if we were remotely suspended but suspend locally, local suspend
            always overrides */
         btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND;
@@ -787,25 +797,19 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
         break;
 
     case BTC_AV_DISCONNECT_REQ_EVT:
-
         /* request avdtp to close */
         BTA_AvClose(btc_av_cb.bta_handle);
-        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) {
+        if (btc_av_cb.peer_sep == AVDT_TSEP_SRC && g_av_with_rc == true) {
             BTA_AvCloseRc(btc_av_cb.bta_handle);
         }
-
         /* inform the application that we are disconnecting */
         btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
-
         /* wait in closing state until fully closed */
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
         break;
 
     case BTA_AV_SUSPEND_EVT:
-
-        BTC_TRACE_DEBUG("BTA_AV_SUSPEND_EVT status %d, init %d\n",
-                 p_av->suspend.status, p_av->suspend.initiator);
-
+        BTC_TRACE_DEBUG("BTA_AV_SUSPEND_EVT status %d, init %d\n", p_av->suspend.status, p_av->suspend.initiator);
         /* a2dp suspended, stop media task until resumed */
         btc_a2dp_on_suspended(&p_av->suspend);
 
@@ -824,7 +828,6 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
         if (p_av->suspend.initiator != TRUE) {
             /* remote suspend, notify HAL and await audioflinger to
                suspend/stop stream */
-
             /* set remote suspend flag to block media task from restarting
                stream only if we did not already initiate a local suspend */
             if ((btc_av_cb.flags & BTC_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0) {
@@ -843,31 +846,24 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
         break;
 
     case BTA_AV_STOP_EVT:
-
         btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
         btc_a2dp_on_stopped(&p_av->suspend);
-
         btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
 
         /* if stop was successful, change state to open */
         if (p_av->suspend.status == BTA_AV_SUCCESS) {
             btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
         }
-
         break;
 
     case BTA_AV_CLOSE_EVT: {
-
         btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
-
         /* avdtp link is closed */
         btc_a2dp_on_stopped(NULL);
 
         tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
         /* inform the application that we are disconnected */
-        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
-                                    close->disc_rsn);
-
+        btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn);
         btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
         break;
     }
@@ -875,10 +871,8 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
     CHECK_RC_EVENT(event, p_data);
 
     default:
-        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
-                 dump_av_sm_event_name(event));
+        BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
         return FALSE;
-
     }
     return TRUE;
 }
@@ -957,7 +951,6 @@ static void btc_av_event_free_data(btc_sm_event_t event, void *p_data)
 ** Returns          bt_status_t
 **
 *******************************************************************************/
-
 static bt_status_t btc_av_init(int service_id)
 {
     if (btc_av_cb.sm_handle == NULL) {
@@ -974,6 +967,8 @@ static bt_status_t btc_av_init(int service_id)
         }
 
         if (!stat) {
+            g_a2dp_on_init = false;
+            g_a2dp_on_deinit = true;
             return BT_STATUS_FAIL;
         }
 
@@ -992,6 +987,8 @@ static bt_status_t btc_av_init(int service_id)
         return BT_STATUS_SUCCESS;
     }
 
+    g_a2dp_on_init = true;
+    g_a2dp_on_deinit = false;
     return BT_STATUS_FAIL;
 }
 
@@ -1038,11 +1035,13 @@ static void clean_up(int service_id)
             tle_av_open_on_rc = NULL;
         }
 #endif /* BTC_AV_SRC_INCLUDED */
+        btc_dm_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
     }
 
-    btc_dm_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
-
     if (service_id == BTA_A2DP_SINK_SERVICE_ID) {
+#if BTC_AV_SINK_INCLUDED
+        btc_a2dp_sink_shutdown();
+#endif /* BTC_AV_SINK_INCLUDED */
         btc_dm_disable_service(BTA_A2DP_SINK_SERVICE_ID);
     }
 
@@ -1050,11 +1049,8 @@ static void clean_up(int service_id)
     btc_sm_shutdown(btc_av_cb.sm_handle);
     btc_av_cb.sm_handle = NULL;
 
-    if (service_id == BTA_A2DP_SINK_SERVICE_ID) {
-#if BTC_AV_SINK_INCLUDED
-        btc_a2dp_sink_shutdown();
-#endif /* BTC_AV_SINK_INCLUDED */
-    }
+    g_a2dp_on_init = false;
+    g_a2dp_on_deinit = true;
 }
 
 /*******************************************************************************
@@ -1229,10 +1225,16 @@ bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
         /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
          * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
          * be initiated by the app/audioflinger layers */
-        BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_NO_SCO_SSPD)
-                     | BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR
-                     | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL,
-                     bte_av_callback);
+        if (g_av_with_rc) {
+            BTC_TRACE_WARNING("A2DP Enable with AVRC")
+            BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD |
+                        BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
+                        BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL,
+                        bte_av_callback);
+        } else {
+            BTC_TRACE_WARNING("A2DP Enable without AVRC")
+            BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD, bte_av_callback);
+        }
         BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, tsep);
     } else {
         BTA_AvDeregister(btc_av_cb.bta_handle);
@@ -1384,7 +1386,9 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
     }
     case BTC_AV_SINK_API_DISCONNECT_EVT: {
         CHECK_BTAV_INIT();
-        btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, NULL);
+        btc_av_disconn_req_t disconn_req;   
+        memcpy(&disconn_req.target_bda, &arg->disconn, sizeof(bt_bdaddr_t));
+        btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
         break;
     }
     case BTC_AV_SINK_API_REG_DATA_CB_EVT: {
@@ -1407,7 +1411,9 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
     }
     case BTC_AV_SRC_API_DISCONNECT_EVT: {
         CHECK_BTAV_INIT();
-        btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, NULL);
+        btc_av_disconn_req_t disconn_req;
+        memcpy(&disconn_req.target_bda, &arg->src_disconn, sizeof(bt_bdaddr_t));
+        btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req);
         break;
     }
     case BTC_AV_SRC_API_REG_DATA_CB_EVT: {

+ 15 - 0
components/bt/bluedroid/btc/profile/std/avrc/btc_avrc.c

@@ -424,6 +424,14 @@ static void btc_avrc_ct_init(void)
     BTC_TRACE_DEBUG("## %s ##", __FUNCTION__);
 
     memset (&btc_rc_vb, 0, sizeof(btc_rc_vb));
+
+    if (!g_av_with_rc) {
+        g_av_with_rc = true;
+    }
+    if (g_a2dp_on_init) {
+        BTC_TRACE_WARNING("AVRC Controller is expected to be initialized in advance of A2DP !!!");
+    }
+
     btc_rc_vb.rc_vol_label = MAX_LABEL;
     btc_rc_vb.rc_volume = MAX_VOLUME;
 }
@@ -442,6 +450,13 @@ static void btc_avrc_ct_deinit(void)
 {
     BTC_TRACE_API("## %s ##", __FUNCTION__);
 
+    if (g_a2dp_on_deinit) {
+        BTC_TRACE_WARNING("A2DP already deinit, AVRC CT shuold deinit in advance of A2DP !!!");
+    }
+    if (g_av_with_rc) {
+        g_av_with_rc = false;
+    }
+
     memset(&btc_rc_vb, 0, sizeof(btc_rc_cb_t));
     BTC_TRACE_API("## %s ## completed", __FUNCTION__);
 }

+ 12 - 1
components/bt/bluedroid/btc/profile/std/include/btc_av.h

@@ -33,10 +33,17 @@
 #include "bta/bta_av_api.h"
 
 #if (BTC_AV_INCLUDED == TRUE)
+
+// global variable to inidcate avrc is initialized with a2dp
+extern bool g_av_with_rc;
+// global variable to indicate a2dp is initialized
+extern bool g_a2dp_on_init;
+// global variable to indicate a2dp is deinitialized
+extern bool g_a2dp_on_deinit;
+
 /*******************************************************************************
 **  Type definitions for callback functions
 ********************************************************************************/
-
 enum {
     BTC_AV_DATAPATH_OPEN_EVT, // original UIPC_OPEN_EVT for data channel in bluedroid
     BTC_AV_DATAPATH_MAX_EVT,
@@ -77,6 +84,8 @@ typedef union {
     esp_a2d_mcc_t mcc;
     // BTC_AV_SINK_API_CONNECT_EVT
     bt_bdaddr_t connect;
+    // BTC_AV_SINK_API_DISCONNECT_EVT
+    bt_bdaddr_t disconn;
     // BTC_AV_SINK_API_REG_DATA_CB_EVT
     esp_a2d_sink_data_cb_t data_cb;
 #endif  /* BTC_AV_SINK_INCLUDED */
@@ -85,6 +94,8 @@ typedef union {
     esp_a2d_source_data_cb_t src_data_cb;
     // BTC_AV_SRC_API_CONNECT
     bt_bdaddr_t src_connect;
+    // BTC_AV_SRC_API_DISCONNECT_EVT
+    bt_bdaddr_t src_disconn;
 #endif /* BTC_AV_SRC_INCLUDED */
     // BTC_AV_API_MEDIA_CTRL_EVT
     esp_a2d_media_ctrl_t ctrl;

+ 5 - 4
examples/bluetooth/a2dp_sink/main/main.c

@@ -177,15 +177,16 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
         esp_bt_dev_set_device_name(dev_name);
 
         esp_bt_gap_register_callback(bt_app_gap_cb);
-        /* initialize A2DP sink */
-        esp_a2d_register_callback(&bt_app_a2d_cb);
-        esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
-        esp_a2d_sink_init();
 
         /* initialize AVRCP controller */
         esp_avrc_ct_init();
         esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
 
+        /* initialize A2DP sink */
+        esp_a2d_register_callback(&bt_app_a2d_cb);
+        esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
+        esp_a2d_sink_init();
+
         /* set discoverable and connectable mode, wait to be connected */
         esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
         break;