Redesign separating AVRC & A2DP

1. Add g_av_with_rc to avrc_tg_init function
2. Remove g_av_open_fail
3. Add comment in API files
4. Add a2dp init & deinit state variable to inidcate a2dp statement
This commit is contained in:
weitianhua 2020-09-01 19:57:51 +08:00
parent 98e9f62dda
commit 53c57cf2a3
5 changed files with 107 additions and 89 deletions

View File

@ -193,7 +193,8 @@ esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback);
/** /**
* *
* @brief Initialize the bluetooth A2DP sink module. This function should be called * @brief Initialize the bluetooth A2DP sink module. This function should be called
* after esp_bluedroid_enable() completes successfully * after esp_bluedroid_enable() completes successfully. Note: A2DP can work independently.
* If you want to use AVRC together, you should initiate AVRC first.
* *
* @return * @return
* - ESP_OK: if the initialization request is sent successfully * - ESP_OK: if the initialization request is sent successfully
@ -264,7 +265,8 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl);
/** /**
* *
* @brief Initialize the bluetooth A2DP source module. This function should be called * @brief Initialize the bluetooth A2DP source module. This function should be called
* after esp_bluedroid_enable() completes successfully * after esp_bluedroid_enable() completes successfully. Note: A2DP can work independently.
* If you want to use AVRC together, you should initiate AVRC first.
* *
* @return * @return
* - ESP_OK: if the initialization request is sent successfully * - ESP_OK: if the initialization request is sent successfully

View File

@ -414,7 +414,8 @@ esp_err_t esp_avrc_ct_register_callback(esp_avrc_ct_cb_t callback);
/** /**
* *
* @brief Initialize the bluetooth AVRCP controller module, This function should be called * @brief Initialize the bluetooth AVRCP controller module, This function should be called
* after esp_bluedroid_enable() completes successfully * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
* AVRC should be used along with A2DP and AVRC should be initialized before A2DP.
* *
* @return * @return
* - ESP_OK: success * - ESP_OK: success
@ -427,7 +428,8 @@ esp_err_t esp_avrc_ct_init(void);
/** /**
* *
* @brief De-initialize AVRCP controller module. This function should be called after * @brief De-initialize AVRCP controller module. This function should be called after
* after esp_bluedroid_enable() completes successfully * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
* AVRC should be used along with A2DP and AVRC should be deinitialized before A2DP.
* *
* @return * @return
* - ESP_OK: success * - ESP_OK: success
@ -543,7 +545,8 @@ esp_err_t esp_avrc_tg_register_callback(esp_avrc_tg_cb_t callback);
/** /**
* *
* @brief Initialize the bluetooth AVRCP target module, This function should be called * @brief Initialize the bluetooth AVRCP target module, This function should be called
* after esp_bluedroid_enable() completes successfully * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
* AVRC should be used along with A2DP and AVRC should be initialized before A2DP.
* *
* @return * @return
* - ESP_OK: success * - ESP_OK: success
@ -556,7 +559,8 @@ esp_err_t esp_avrc_tg_init(void);
/** /**
* *
* @brief De-initialize AVRCP target module. This function should be called after * @brief De-initialize AVRCP target module. This function should be called after
* after esp_bluedroid_enable() completes successfully * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently,
* AVRC should be used along with A2DP and AVRC should be deinitialized before A2DP.
* *
* @return * @return
* - ESP_OK: success * - ESP_OK: success

View File

@ -42,8 +42,12 @@
#if BTC_AV_INCLUDED #if BTC_AV_INCLUDED
bool g_av_open_fail; // global variable to inidcate avrc is initialized with a2dp
bool g_av_with_rc; 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 ** Constants & Macros
@ -96,14 +100,9 @@ typedef struct {
bt_bdaddr_t target_bda; bt_bdaddr_t target_bda;
} btc_av_disconn_req_t; } btc_av_disconn_req_t;
typedef struct {
esp_a2d_connection_state_t state;
btc_sm_state_t av_state;
} btc_av_open_t;
/***************************************************************************** /*****************************************************************************
** Static variables ** Static variables
******************************************************************************/ ******************************************************************************/
btc_av_open_t av_open;
#if A2D_DYNAMIC_MEMORY == FALSE #if A2D_DYNAMIC_MEMORY == FALSE
static btc_av_cb_t btc_av_cb = {0}; static btc_av_cb_t btc_av_cb = {0};
@ -304,8 +303,6 @@ 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); dump_av_sm_event_name(event), btc_av_cb.flags);
// Init av_open struct
memset(&av_open, 0, sizeof(btc_av_open_t));
switch (event) { switch (event) {
case BTC_SM_ENTER_EVT: case BTC_SM_ENTER_EVT:
@ -314,12 +311,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
btc_av_cb.flags = 0; btc_av_cb.flags = 0;
btc_av_cb.edr = 0; btc_av_cb.edr = 0;
btc_a2dp_on_idle(); btc_a2dp_on_idle();
if(g_av_open_fail) {
BTC_TRACE_ERROR("AV_OPEN: Sta %d , SM Sta %d\n",av_open.state, av_open.av_state);
/* inform the application of the event */
btc_report_connection_state(av_open.state, &(btc_av_cb.peer_bda), 0);
}
break; break;
case BTC_SM_EXIT_EVT: case BTC_SM_EXIT_EVT:
@ -330,9 +321,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
case BTA_AV_REGISTER_EVT: case BTA_AV_REGISTER_EVT:
btc_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl; btc_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl;
// Init av_open struct and av_open_state
memset(&av_open, 0, sizeof(btc_av_open_t));
g_av_open_fail = false;
break; break;
case BTA_AV_PENDING_EVT: case BTA_AV_PENDING_EVT:
@ -363,20 +351,20 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
} break; } break;
case BTC_AV_DISCONNECT_REQ_EVT: case BTC_AV_DISCONNECT_REQ_EVT:
BTC_TRACE_WARNING("BTC_AV_DISCONNECT_REQ_EVT received when no link up."); BTC_TRACE_WARNING("No Link At All.");
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0); btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0);
break; break;
case BTA_AV_RC_OPEN_EVT: case BTA_AV_RC_OPEN_EVT:
/* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So /* 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, * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
* we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state. * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
* We initiate the AV connection after a small 3s timeout to avoid any collisions from the * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
* headsets, as some headsets initiate the AVRC connection first and then * headsets, as some headsets initiate the AVRC connection first and then
* immediately initiate the AV connection * immediately initiate the AV connection
* *
* TODO: We may need to do this only on an AVRCP Play. FixMe * TODO: We may need to do this only on an AVRCP Play. FixMe
*/ */
#if BTC_AV_SRC_INCLUDED #if BTC_AV_SRC_INCLUDED
BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV"); BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
btc_av_cb.tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000); btc_av_cb.tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
@ -407,7 +395,6 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
dump_av_sm_event_name(event)); dump_av_sm_event_name(event));
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
@ -438,32 +425,34 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
break; break;
case BTA_AV_REJECT_EVT: case BTA_AV_REJECT_EVT:
BTC_TRACE_DEBUG(" Received BTA_AV_REJECT_EVT \n"); BTC_TRACE_WARNING(" Received BTA_AV_REJECT_EVT \n");
g_av_open_fail = true; 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); btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
break; break;
case BTA_AV_OPEN_EVT: { case BTA_AV_OPEN_EVT: {
tBTA_AV *p_bta_data = (tBTA_AV *)p_data; tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
esp_a2d_connection_state_t conn_stat;
btc_sm_state_t av_state;
BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status, BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status,
p_bta_data->open.edr, p_bta_data->open.sep); p_bta_data->open.edr, p_bta_data->open.sep);
if (p_bta_data->open.status == BTA_AV_SUCCESS) { if (p_bta_data->open.status == BTA_AV_SUCCESS) {
av_open.state = ESP_A2D_CONNECTION_STATE_CONNECTED;
av_open.av_state = BTC_AV_STATE_OPENED;
btc_av_cb.edr = p_bta_data->open.edr; btc_av_cb.edr = p_bta_data->open.edr;
btc_av_cb.peer_sep = p_bta_data->open.sep; btc_av_cb.peer_sep = p_bta_data->open.sep;
} else {
BTC_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n",
p_bta_data->open.status );
av_open.state = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
av_open.av_state = BTC_AV_STATE_IDLE;
g_av_open_fail = true;
}
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);
conn_stat = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
av_state = BTC_AV_STATE_IDLE;
}
/* inform the application of the event */
btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), 0);
/* change state to open/idle based on the status */ /* change state to open/idle based on the status */
btc_sm_change_state(btc_av_cb.sm_handle, av_open.av_state); btc_sm_change_state(btc_av_cb.sm_handle, av_state);
if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) { if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) {
/* if queued PLAY command, send it now */ /* if queued PLAY command, send it now */
@ -518,13 +507,11 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data)
break; break;
} }
CHECK_RC_EVENT(event, p_data); CHECK_RC_EVENT(event, p_data);
default: default:
BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
dump_av_sm_event_name(event));
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -584,9 +571,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
case BTA_AV_CLOSE_EVT: { case BTA_AV_CLOSE_EVT: {
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data; tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
/* inform the application that we are disconnecting */ /* inform the application that we are disconnecting */
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn);
close->disc_rsn);
g_av_open_fail = false;
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE); btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
break; break;
} }
@ -597,14 +582,12 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
break; break;
default: default:
BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event));
dump_av_sm_event_name(event));
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
/***************************************************************************** /*****************************************************************************
** **
** Function btc_av_state_opened_handler ** Function btc_av_state_opened_handler
@ -614,7 +597,6 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data)
** Returns TRUE if event was processed, FALSE otherwise ** Returns TRUE if event was processed, FALSE otherwise
** **
*******************************************************************************/ *******************************************************************************/
static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
{ {
tBTA_AV *p_av = (tBTA_AV *)p_data; tBTA_AV *p_av = (tBTA_AV *)p_data;
@ -632,8 +614,6 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
case BTC_SM_ENTER_EVT: case BTC_SM_ENTER_EVT:
btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_STOP; btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_STOP;
btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START; btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START;
/* inform the application of the event */
btc_report_connection_state(av_open.state, &(btc_av_cb.peer_bda), 0);
break; break;
case BTC_SM_EXIT_EVT: case BTC_SM_EXIT_EVT:
@ -701,7 +681,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
case BTC_AV_DISCONNECT_REQ_EVT: case BTC_AV_DISCONNECT_REQ_EVT:
BTA_AvClose(btc_av_cb.bta_handle); 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); BTA_AvCloseRc(btc_av_cb.bta_handle);
} }
@ -716,14 +696,14 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
/* inform the application that we are disconnected */ /* inform the application that we are disconnected */
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
close->disc_rsn); close->disc_rsn);
g_av_open_fail = false;
/* change state to idle, send acknowledgement if start is pending */
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) { if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE); btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
/* pending start flag will be cleared when exit current state */ /* 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; break;
} }
@ -750,7 +730,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
btc_queue_advance(); btc_queue_advance();
break; break;
CHECK_RC_EVENT(event, p_data); CHECK_RC_EVENT(event, p_data);
default: default:
BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
@ -837,15 +817,15 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
/* request avdtp to close */ /* request avdtp to close */
BTA_AvClose(btc_av_cb.bta_handle); 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); BTA_AvCloseRc(btc_av_cb.bta_handle);
} }
/* wait in closing state until fully closed */
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
/* inform the application that we are disconnecting */ /* inform the application that we are disconnecting */
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0); btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0);
/* wait in closing state until fully closed */
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING);
break; break;
case BTA_AV_SUSPEND_EVT: case BTA_AV_SUSPEND_EVT:
@ -868,10 +848,6 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
return FALSE; return FALSE;
} }
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
/* suspend completed and state changed, clear pending status */
btc_av_cb.flags &= ~BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
if (p_av->suspend.initiator != TRUE) { if (p_av->suspend.initiator != TRUE) {
/* remote suspend, notify HAL and await audioflinger to /* remote suspend, notify HAL and await audioflinger to
suspend/stop stream */ suspend/stop stream */
@ -886,6 +862,11 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
} else { } else {
btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda)); btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
} }
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
/* suspend completed and state changed, clear pending status */
btc_av_cb.flags &= ~BTC_AV_FLAG_LOCAL_SUSPEND_PENDING;
break; break;
case BTA_AV_STOP_EVT: case BTA_AV_STOP_EVT:
@ -893,29 +874,25 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data)
btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP; btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
btc_a2dp_on_stopped(&p_av->suspend); 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 stop was successful, change state to open */
if (p_av->suspend.status == BTA_AV_SUCCESS) { if (p_av->suspend.status == BTA_AV_SUCCESS) {
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED); btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENED);
} }
btc_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btc_av_cb.peer_bda));
break; break;
case BTA_AV_CLOSE_EVT: { case BTA_AV_CLOSE_EVT:
btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP; btc_av_cb.flags |= BTC_AV_FLAG_PENDING_STOP;
/* avdtp link is closed */ /* avdtp link is closed */
btc_a2dp_on_stopped(NULL); btc_a2dp_on_stopped(NULL);
g_av_open_fail = false;
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data; tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
/* inform the application that we are disconnected */ /* inform the application that we are disconnected */
btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda),
close->disc_rsn); close->disc_rsn);
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE);
break; break;
}
CHECK_RC_EVENT(event, p_data); CHECK_RC_EVENT(event, p_data);
@ -1002,7 +979,6 @@ static void btc_av_event_free_data(btc_sm_event_t event, void *p_data)
** Returns bt_status_t ** Returns bt_status_t
** **
*******************************************************************************/ *******************************************************************************/
static bt_status_t btc_av_init(int service_id) static bt_status_t btc_av_init(int service_id)
{ {
@ -1036,6 +1012,8 @@ static bt_status_t btc_av_init(int service_id)
osi_free(btc_av_cb_ptr); osi_free(btc_av_cb_ptr);
btc_av_cb_ptr = NULL; btc_av_cb_ptr = NULL;
#endif #endif
g_a2dp_on_init = false;
g_a2dp_on_deinit = true;
return BT_STATUS_FAIL; return BT_STATUS_FAIL;
} }
@ -1050,7 +1028,8 @@ static bt_status_t btc_av_init(int service_id)
} }
btc_a2dp_on_init(); btc_a2dp_on_init();
g_a2dp_on_init = true;
g_a2dp_on_deinit = false;
return BT_STATUS_SUCCESS; return BT_STATUS_SUCCESS;
} }
@ -1118,6 +1097,8 @@ static void clean_up(int service_id)
osi_free(btc_av_cb_ptr); osi_free(btc_av_cb_ptr);
btc_av_cb_ptr = NULL; btc_av_cb_ptr = NULL;
#endif #endif
g_a2dp_on_init = false;
g_a2dp_on_deinit = true;
} }
/******************************************************************************* /*******************************************************************************
@ -1293,12 +1274,14 @@ bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
* auto-suspend av streaming on AG events(SCO or Call). The suspend shall * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
* be initiated by the app/audioflinger layers */ * be initiated by the app/audioflinger layers */
if (g_av_with_rc) { if (g_av_with_rc) {
BTC_TRACE_WARNING("A2DP Enable with AVRC")
BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD | 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_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL, BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL,
bte_av_callback); bte_av_callback);
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, &bta_avrc_cos, tsep); BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, &bta_avrc_cos, tsep);
} else { } else {
BTC_TRACE_WARNING("A2DP Enable without AVRC")
BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD, bte_av_callback); 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, NULL, tsep); BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, NULL, tsep);
} }

View File

@ -1011,15 +1011,20 @@ static void btc_avrc_ct_init(void)
return; return;
} }
// indicate that using A2DP with AVRC
g_av_with_rc = true;
/// initialize CT-specific resources /// initialize CT-specific resources
s_rc_ct_init = BTC_RC_CT_INIT_MAGIC; s_rc_ct_init = BTC_RC_CT_INIT_MAGIC;
/// initialize CT-TG shared resources /// initialize CT-TG shared resources
if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t)); memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t));
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 !!!");
}
} }
} }
@ -1037,20 +1042,24 @@ static void btc_avrc_ct_deinit(void)
{ {
BTC_TRACE_API("## %s ##", __FUNCTION__); 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 (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
BTC_TRACE_WARNING("%s not initialized", __FUNCTION__); BTC_TRACE_WARNING("%s not initialized", __FUNCTION__);
return; return;
} }
// indicate that using A2DP with AVRC
g_av_with_rc = true;
/// deinit CT-specific resources /// deinit CT-specific resources
s_rc_ct_init = 0; s_rc_ct_init = 0;
/// deinit CT-TG shared resources /// deinit CT-TG shared resources
if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t)); memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t));
if (g_av_with_rc) {
g_av_with_rc = false;
}
} }
BTC_TRACE_API("## %s ## completed", __FUNCTION__); BTC_TRACE_API("## %s ## completed", __FUNCTION__);
@ -1285,6 +1294,14 @@ static void btc_avrc_tg_init(void)
/// initialize CT-TG shared resources /// initialize CT-TG shared resources
if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
memset (&btc_rc_cb, 0, sizeof(btc_rc_cb)); memset (&btc_rc_cb, 0, sizeof(btc_rc_cb));
if (!g_av_with_rc) {
g_av_with_rc = true;
}
if (g_a2dp_on_init) {
BTC_TRACE_WARNING("AVRC Taget is expected to be initialized in advance of A2DP !!!");
}
} }
s_rc_tg_init = BTC_RC_TG_INIT_MAGIC; s_rc_tg_init = BTC_RC_TG_INIT_MAGIC;
@ -1304,6 +1321,10 @@ static void btc_avrc_tg_deinit(void)
{ {
BTC_TRACE_API("## %s ##", __FUNCTION__); BTC_TRACE_API("## %s ##", __FUNCTION__);
if (g_a2dp_on_deinit) {
BTC_TRACE_WARNING("A2DP already deinit, AVRC TG shuold deinit in advance of A2DP !!!");
}
if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
BTC_TRACE_WARNING("%s not initialized", __FUNCTION__); BTC_TRACE_WARNING("%s not initialized", __FUNCTION__);
return; return;
@ -1317,6 +1338,9 @@ static void btc_avrc_tg_deinit(void)
/// deinit CT-TG shared resources /// deinit CT-TG shared resources
if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
memset (&btc_rc_cb, 0, sizeof(btc_rc_cb)); memset (&btc_rc_cb, 0, sizeof(btc_rc_cb));
if (g_av_with_rc) {
g_av_with_rc = false;
}
} }
BTC_TRACE_API("## %s ## completed", __FUNCTION__); BTC_TRACE_API("## %s ## completed", __FUNCTION__);

View File

@ -33,8 +33,13 @@
#include "bta/bta_av_api.h" #include "bta/bta_av_api.h"
#if (BTC_AV_INCLUDED == TRUE) #if (BTC_AV_INCLUDED == TRUE)
extern bool g_av_open_fail;
// global variable to inidcate avrc is initialized with a2dp
extern bool g_av_with_rc; 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 ** Type definitions for callback functions
********************************************************************************/ ********************************************************************************/