component/bt: modification to a2dp API to support reconnection

1. add API esp_a2d_sink_connect() to initiate connection to other devices;
2. modify lower layers to transfer the disconnection reason upwards
This commit is contained in:
wangmengyang 2017-02-23 14:30:08 +08:00
parent 80cdfc9e0a
commit 118131109e
12 changed files with 82 additions and 24 deletions

19
components/bt/bluedroid/api/include/esp_a2dp_api.h Normal file → Executable file
View File

@ -83,6 +83,12 @@ typedef enum {
ESP_A2D_CONNECTION_STATE_DISCONNECTING
} esp_a2d_connection_state_t;
/// Bluetooth A2DP disconnection reason
typedef enum {
ESP_A2D_DISC_RSN_NORMAL = 0,
ESP_A2D_DISC_RSN_ABNORMAL
} esp_a2d_disc_rsn_t;
/// Bluetooth A2DP datapath states
typedef enum {
ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND = 0,
@ -103,6 +109,7 @@ typedef union {
struct a2d_conn_stat_param {
esp_a2d_connection_state_t state; /*!< one of values from esp_a2d_connection_state_t */
esp_bd_addr_t remote_bda;
esp_a2d_disc_rsn_t disc_rsn; /* disconnection reason */
} conn_stat;
/*< ESP_A2D_AUDIO_STATE_EVT */
@ -183,6 +190,18 @@ esp_err_t esp_a2d_sink_init(void);
void esp_a2d_sink_deinit(void);
/**
*
* @brief This function is called to connect with the remote bluetooth device
*
* @return
* - ESP_OK: connect request is sent to lower layer
* - ESP_FAIL: others
*
*/
esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda);
/**
*
* @brief This function is called to disconnect with the remote bluetooth device

View File

@ -530,9 +530,14 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t
}
break;
case AVDT_SUSPEND_IND_EVT:
p_msg->msg.hdr.err_code = 0;
p_msg->msg.hdr.err_code = 0;
break;
/*
case AVDT_CLOSE_CFM_EVT:
case AVDT_CLOSE_IND_EVT:
p_msg->disc_rsn = p_data->hdr.err_param;
break;
*/
default:
break;
}
@ -1080,6 +1085,7 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
p_scb->cur_psc_mask = 0;
p_scb->wait = 0;
p_scb->num_disc_snks = 0;
p_scb->disc_rsn = 0;
bta_sys_stop_timer(&p_scb->timer);
if (p_scb->deregistring)
{
@ -2571,6 +2577,7 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
p_scb->p_cos->close(p_scb->hndl, p_scb->codec_type, mtu);
data.close.chnl = p_scb->chnl;
data.close.hndl = p_scb->hndl;
data.close.disc_rsn = p_scb->disc_rsn;
event = BTA_AV_CLOSE_EVT;
bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);

View File

@ -1508,6 +1508,7 @@ void bta_av_sig_chg(tBTA_AV_DATA *p_data)
if ((mask & p_lcb->conn_msk) && (p_cb->p_scb[xx]) &&
(bdcmp(p_cb->p_scb[xx]->peer_addr, p_data->str_msg.bd_addr) == 0))
{
p_cb->p_scb[xx]->disc_rsn = p_data->str_msg.hdr.offset;
bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_AVDT_DISCONNECT_EVT, NULL);
}
}

View File

@ -337,7 +337,7 @@ typedef struct {
BD_ADDR bd_addr; /* bd address */
UINT8 handle;
UINT8 avdt_event;
BOOLEAN initiator; /* TRUE, if local device initiates the SUSPEND */
BOOLEAN initiator; /* TRUE, if local device initiates the SUSPEND */
} tBTA_AV_STR_MSG;
/* data type for BTA_AV_AVRC_MSG_EVT */
@ -516,6 +516,7 @@ typedef struct
UINT8 wait; /* set 0x1, when getting Caps as ACP, set 0x2, when started */
UINT8 q_tag; /* identify the associated q_info union member */
BOOLEAN no_rtp_hdr; /* TRUE if add no RTP header*/
UINT8 disc_rsn; /* disconenction reason */
UINT16 uuid_int; /*intended UUID of Initiator to connect to */
} tBTA_AV_SCB;

View File

@ -331,6 +331,7 @@ typedef struct
{
tBTA_AV_CHNL chnl;
tBTA_AV_HNDL hndl;
UINT8 disc_rsn; /* disconnection reason */
} tBTA_AV_CLOSE;
/* data associated with BTA_AV_START_EVT */

48
components/bt/bluedroid/btif/btif_avk.c Normal file → Executable file
View File

@ -238,7 +238,7 @@ static void btif_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle)
/*****************************************************************************
** Static functions
******************************************************************************/
static void btif_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr)
static void btif_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr, int disc_rsn)
{
esp_a2d_cb_param_t param;
memset(&param, 0, sizeof(esp_a2d_cb_param_t));
@ -247,6 +247,10 @@ static void btif_report_connection_state(esp_a2d_connection_state_t state, bt_bd
if (bd_addr) {
memcpy(param.conn_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
}
if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
param.conn_stat.disc_rsn = (disc_rsn == 0) ? ESP_A2D_DISC_RSN_NORMAL :
ESP_A2D_DISC_RSN_ABNORMAL;
}
BTIF_A2D_CB_TO_APP(ESP_A2D_CONNECTION_STATE_EVT, &param);
}
@ -374,7 +378,7 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
switch (event) {
case BTIF_SM_ENTER_EVT:
/* inform the application that we are entering connecting state */
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btif_av_cb.peer_bda));
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btif_av_cb.peer_bda), 0);
break;
case BTIF_SM_EXIT_EVT:
@ -382,7 +386,7 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
case BTA_AV_REJECT_EVT:
BTIF_TRACE_DEBUG(" Received BTA_AV_REJECT_EVT \n");
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda), 0);
btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
break;
@ -408,7 +412,7 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
}
/* inform the application of the event */
btif_report_connection_state(state, &(btif_av_cb.peer_bda));
btif_report_connection_state(state, &(btif_av_cb.peer_bda), 0);
/* change state to open/idle based on the status */
btif_sm_change_state(btif_av_cb.sm_handle, av_state);
if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
@ -442,7 +446,7 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
break;
} else {
BTIF_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__);
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data);
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0);
btif_queue_advance();
break;
}
@ -506,13 +510,15 @@ static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data
case BTIF_SM_EXIT_EVT:
break;
case BTA_AV_CLOSE_EVT:
case BTA_AV_CLOSE_EVT: {
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
/* inform the application that we are disconnecting */
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda),
close->disc_rsn);
btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
break;
}
/* Handle the RC_CLOSE event for the cleanup */
case BTA_AV_RC_CLOSE_EVT:
@ -599,15 +605,17 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
}
/* inform the application that we are disconnecting */
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda), 0);
break;
case BTA_AV_CLOSE_EVT:
case BTA_AV_CLOSE_EVT: {
/* avdtp link is closed */
btif_a2dp_on_stopped(NULL);
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
/* inform the application that we are disconnected */
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda),
close->disc_rsn);
/* change state to idle, send acknowledgement if start is pending */
if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
@ -615,6 +623,7 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
}
btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
break;
}
case BTA_AV_RECONFIG_EVT:
if ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
@ -633,7 +642,7 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
} else {
BTIF_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__);
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED,
(bt_bdaddr_t *)p_data);
(bt_bdaddr_t *)p_data, ESP_A2D_DISC_RSN_NORMAL);
}
btif_queue_advance();
break;
@ -718,7 +727,7 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
}
/* inform the application that we are disconnecting */
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda), 0);
/* wait in closing state until fully closed */
btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING);
@ -774,20 +783,23 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
break;
case BTA_AV_CLOSE_EVT:
case BTA_AV_CLOSE_EVT: {
btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
/* avdtp link is closed */
btif_a2dp_on_stopped(NULL);
tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data;
/* inform the application that we are disconnected */
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda),
close->disc_rsn);
btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
break;
CHECK_RC_EVENT(event, p_data);
}
CHECK_RC_EVENT(event, p_data);
default:
BTIF_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,

View File

@ -326,9 +326,10 @@ void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
tAVDT_CCB *p_ccb;
tAVDT_SCB *p_scb;
tAVDT_SCB_TC_CLOSE close;
UNUSED(reason);
// UNUSED(reason);
close.old_tc_state = p_tbl->state;
/* clear avdt_ad_tc_tbl entry */
p_tbl->state = AVDT_AD_ST_UNUSED;
p_tbl->cfg_flags = 0;
@ -336,10 +337,12 @@ void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
AVDT_TRACE_DEBUG("avdt_ad_tc_close_ind tcid: %d, old: %d\n",
p_tbl->tcid, close.old_tc_state);
/* if signaling channel, notify ccb that channel open */
if (p_tbl->tcid == 0)
{
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
p_ccb->disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL;
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
}
/* if media or other channel, notify scb that channel close */
@ -351,6 +354,7 @@ void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
{
close.tcid = p_tbl->tcid;
close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
close.disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL;
avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, (tAVDT_SCB_EVT *)&close);
}
}

View File

@ -1077,6 +1077,7 @@ void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
tAVDT_CTRL_CBACK *p_cback;
BD_ADDR bd_addr;
tAVDT_CTRL avdt_ctrl;
UINT8 disc_rsn;
UNUSED(p_data);
/* clear any pending commands */
@ -1088,6 +1089,8 @@ void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
p_cback = avdt_cb.p_conn_cback;
memcpy(bd_addr, p_ccb->peer_addr, BD_ADDR_LEN);
disc_rsn = p_ccb->disc_rsn;
/* dealloc ccb */
avdt_ccb_dealloc(p_ccb, NULL);
@ -1095,6 +1098,8 @@ void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
if (p_cback)
{
avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = disc_rsn;
(*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
}
}

View File

@ -444,7 +444,7 @@ void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
{
tAVDT_TC_TBL *p_tbl;
UINT16 disc_rsn = AVDT_DISC_RSN_NORMAL;
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d\n",
lcid, ack_needed);
/* look up info for this channel */
@ -454,9 +454,11 @@ void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
{
/* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid);
} else {
disc_rsn = AVDT_DISC_RSN_ABNORMAL;
}
avdt_ad_tc_close_ind(p_tbl, 0);
avdt_ad_tc_close_ind(p_tbl, disc_rsn);
}
}

View File

@ -1007,6 +1007,7 @@ void avdt_scb_hdl_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
/* set up hdr */
avdt_ctrl.hdr.err_code = p_scb->close_code;
avdt_ctrl.hdr.err_param = p_data->close.disc_rsn;
/* clear sep variables */
avdt_scb_clr_vars(p_scb, p_data);

View File

@ -440,6 +440,7 @@ typedef struct {
UINT8 label; /* Message header "label" (sequence number) */
BOOLEAN reconn; /* If TRUE, reinitiate connection after transitioning from CLOSING to IDLE state */
UINT8 ret_count; /* Command retransmission count */
UINT8 disc_rsn; /* disconnection reason */
} tAVDT_CCB;
/* type for action functions */
@ -463,6 +464,7 @@ typedef struct {
UINT8 old_tc_state; /* channel state before closed */
UINT8 tcid; /* TCID */
UINT8 type; /* channel type */
UINT8 disc_rsn; /* disconnection reason */
} tAVDT_SCB_TC_CLOSE;
/* type for scb event data */

View File

@ -203,6 +203,9 @@ typedef UINT8 AVDT_REPORT_TYPE;
#define AVDT_NSC_RECONFIG 0x02 /* Reconfigure command not supported */
#define AVDT_NSC_SECURITY 0x04 /* Security command not supported */
/* AVDT disconnection reason */
#define AVDT_DISC_RSN_NORMAL 0
#define AVDT_DISC_RSN_ABNORMAL (0xce) /* unintentional disconnection */
/*****************************************************************************
** Type Definitions
*****************************************************************************/