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,
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 */
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
}
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;
}
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)
{
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);
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);
}
}
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 */
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;
{
tBTA_AV_CHNL chnl;
tBTA_AV_HNDL hndl;
+ UINT8 disc_rsn; /* disconnection reason */
} tBTA_AV_CLOSE;
/* data associated with BTA_AV_START_EVT */
/*****************************************************************************
** 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(¶m, 0, sizeof(esp_a2d_cb_param_t));
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, ¶m);
}
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:
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;
}
/* 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) {
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;
}
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:
}
/* 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) {
}
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) &&
} 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;
}
/* 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);
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__,
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;
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 */
{
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);
}
}
tAVDT_CTRL_CBACK *p_cback;
BD_ADDR bd_addr;
tAVDT_CTRL avdt_ctrl;
+ UINT8 disc_rsn;
UNUSED(p_data);
/* clear any pending commands */
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);
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);
}
}
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 */
{
/* 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);
}
}
/* 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);
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 */
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 */
#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
*****************************************************************************/