In pevious implementation, A2DP sink will register an A2DP source Stream End Point(SEP) although the SEP is not\
supposed to be used. Now remove the unused SEP for source so that only one role of A2DP can be supported at one
time. Service record in local SDP server only includes at most one service for A2DP sink role or source
/* store number of stream endpoints returned */
p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
+ UINT8 num_seps = (p_scb->num_seps < BTA_AV_NUM_SEPS) ? p_scb->num_seps : BTA_AV_NUM_SEPS;
+ memcpy(p_scb->sep_info, p_data->str_msg.msg.discover_cfm.p_sep_info, sizeof(tAVDT_SEP_INFO) * num_seps);
+ for (i = 0; i < p_data->str_msg.msg.discover_cfm.num_seps; i++) {
+ APPL_TRACE_DEBUG("peer sep %d, in use %d, seid %d, media type %d, tsep %d",
+ i,
+ p_data->str_msg.msg.discover_cfm.p_sep_info[i].in_use,
+ p_data->str_msg.msg.discover_cfm.p_sep_info[i].seid,
+ p_data->str_msg.msg.discover_cfm.p_sep_info[i].media_type,
+ p_data->str_msg.msg.discover_cfm.p_sep_info[i].tsep
+ );
+ }
for (i = 0; i < p_scb->num_seps; i++) {
/* steam not in use, is a sink, and is audio */
if ((p_scb->sep_info[i].in_use == FALSE) &&
(uuid_int == UUID_SERVCLASS_AUDIO_SINK)) {
num_srcs++;
}
-
+ APPL_TRACE_DEBUG("num srcs: %d, num_snks: %d\n", num_snks, num_srcs);
}
}
** 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)
+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)
{
tBTA_AV_API_REG *p_buf;
p_buf->app_id = app_id;
p_buf->p_app_data_cback = p_data_cback;
p_buf->bta_av_cos = bta_av_cos;
+ p_buf->tsep = tsep;
bta_sys_sendmsg(p_buf);
}
}
}
/* Set the Capturing service class bit */
+ if (p_data->api_reg.tsep == AVDT_TSEP_SRC) {
+ cod.service = BTM_COD_SERVICE_CAPTURING;
+ } else {
#if (BTA_AV_SINK_INCLUDED == TRUE)
- cod.service = BTM_COD_SERVICE_CAPTURING | BTM_COD_SERVICE_RENDERING;
-#else
- cod.service = BTM_COD_SERVICE_CAPTURING;
+ cod.service = BTM_COD_SERVICE_RENDERING;
#endif
+ }
utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
} /* if 1st channel */
/* get stream configuration and create stream */
/* memset(&cs.cfg,0,sizeof(tAVDT_CFG)); */
cs.cfg.num_codec = 1;
- cs.tsep = AVDT_TSEP_SRC;
+ cs.tsep = p_data->api_reg.tsep;
/*
* memset of cs takes care setting call back pointers to null.
memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
while (index < BTA_AV_MAX_SEPS &&
(p_scb->p_cos->init)(&codec_type, cs.cfg.codec_info,
- &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE) {
+ &cs.cfg.num_protect, cs.cfg.protect_info, p_data->api_reg.tsep) == TRUE) {
#if (BTA_AV_SINK_INCLUDED == TRUE)
- if (index == 1) {
- cs.tsep = AVDT_TSEP_SNK;
+ if (p_data->api_reg.tsep == AVDT_TSEP_SNK) {
cs.p_data_cback = bta_av_stream_data_cback;
}
APPL_TRACE_DEBUG(" SEP Type = %d\n", cs.tsep);
}
if (!bta_av_cb.reg_audio) {
- /* create the SDP records on the 1st audio channel */
- bta_av_cb.sdp_a2d_handle = SDP_CreateRecord();
- A2D_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
- A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle);
- bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
-
+ if (p_data->api_reg.tsep == AVDT_TSEP_SRC) {
+ /* create the SDP records on the 1st audio channel */
+ bta_av_cb.sdp_a2d_handle = SDP_CreateRecord();
+ A2D_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
+ A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle);
+ bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+ } else {
#if (BTA_AV_SINK_INCLUDED == TRUE)
- bta_av_cb.sdp_a2d_snk_handle = SDP_CreateRecord();
- A2D_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_avk_service_name, NULL,
- A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_snk_handle);
- bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
+ bta_av_cb.sdp_a2d_snk_handle = SDP_CreateRecord();
+ A2D_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_avk_service_name, NULL,
+ A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_snk_handle);
+ bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
#endif
+ }
/* start listening when A2DP is registered */
if (bta_av_cb.features & BTA_AV_FEAT_RCTG) {
bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
/*****************************************************************************
** Data types
*****************************************************************************/
-#if 0
-/* function types for call-out functions */
-typedef BOOLEAN (*tBTA_AV_CO_INIT) (UINT8 *p_codec_type, UINT8 *p_codec_info,
- UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
-typedef void (*tBTA_AV_CO_DISC_RES) (tBTA_AV_HNDL hndl, UINT8 num_seps,
- UINT8 num_snk, UINT8 num_src, BD_ADDR addr, UINT16 uuid_local);
-typedef UINT8 (*tBTA_AV_CO_GETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
- UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
- UINT8 *p_num_protect, UINT8 *p_protect_info);
-typedef void (*tBTA_AV_CO_SETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
- UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
- UINT8 num_protect, UINT8 *p_protect_info,
- UINT8 t_local_sep, UINT8 avdt_handle);
-typedef void (*tBTA_AV_CO_OPEN) (tBTA_AV_HNDL hndl,
- tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
- UINT16 mtu);
-typedef void (*tBTA_AV_CO_CLOSE) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu);
-typedef void (*tBTA_AV_CO_START) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr);
-typedef void (*tBTA_AV_CO_STOP) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
-typedef void *(*tBTA_AV_CO_DATAPATH) (tBTA_AV_CODEC codec_type,
- UINT32 *p_len, UINT32 *p_timestamp);
-typedef void (*tBTA_AV_CO_DELAY) (tBTA_AV_HNDL hndl, UINT16 delay);
-
-/* the call-out functions for one stream */
-typedef struct {
- tBTA_AV_CO_INIT init;
- tBTA_AV_CO_DISC_RES disc_res;
- tBTA_AV_CO_GETCFG getcfg;
- tBTA_AV_CO_SETCFG setcfg;
- tBTA_AV_CO_OPEN open;
- tBTA_AV_CO_CLOSE close;
- tBTA_AV_CO_START start;
- tBTA_AV_CO_STOP stop;
- tBTA_AV_CO_DATAPATH data;
- tBTA_AV_CO_DELAY delay;
-} tBTA_AV_CO_FUNCTS;
-#endif
-
/* data type for BTA_AV_API_ENABLE_EVT */
typedef struct {
BT_HDR hdr;
BT_HDR hdr;
char p_service_name[BTA_SERVICE_NAME_LEN + 1];
UINT8 app_id;
- tBTA_AV_DATA_CBACK *p_app_data_cback;
+ UINT8 tsep; // local SEP type
+ tBTA_AV_DATA_CBACK *p_app_data_cback;
tBTA_AV_CO_FUNCTS *bta_av_cos;
} tBTA_AV_API_REG;
#endif
#ifndef BTA_AV_MAX_SEPS
-#define BTA_AV_MAX_SEPS 2
+#define BTA_AV_MAX_SEPS 1
#endif
#ifndef BTA_AV_MAX_A2DP_MTU
/* function types for call-out functions */
typedef BOOLEAN (*tBTA_AV_CO_INIT) (UINT8 *p_codec_type, UINT8 *p_codec_info,
- UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
+ UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 tsep);
typedef void (*tBTA_AV_CO_DISC_RES) (tBTA_AV_HNDL hndl, UINT8 num_seps,
UINT8 num_snk, UINT8 num_src, BD_ADDR addr, UINT16 uuid_local);
typedef UINT8 (*tBTA_AV_CO_GETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
**
*******************************************************************************/
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 app_id, tBTA_AV_DATA_CBACK *p_data_cback, tBTA_AV_CO_FUNCTS *bta_av_cos, UINT8 tsep);
/*******************************************************************************
**
**
*******************************************************************************/
extern BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info,
- UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
+ UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 tsep);
/*******************************************************************************
**
** Externs
******************************************************************************/
#if BTC_AV_INCLUDED
-extern bt_status_t btc_av_execute_service(BOOLEAN b_enable);
+extern bt_status_t btc_av_source_execute_service(BOOLEAN b_enable);
extern bt_status_t btc_av_sink_execute_service(BOOLEAN b_enable);
#endif
#if BTC_HF_CLIENT_INCLUDED
switch (service_id) {
#if BTC_AV_INCLUDED
case BTA_A2DP_SOURCE_SERVICE_ID:
- btc_av_execute_service(b_enable);
+ btc_av_source_execute_service(b_enable);
break;
case BTA_A2DP_SINK_SERVICE_ID:
btc_av_sink_execute_service(b_enable);
**
*******************************************************************************/
BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_num_protect,
- UINT8 *p_protect_info, UINT8 index)
+ UINT8 *p_protect_info, UINT8 tsep)
{
FUNC_TRACE();
- APPL_TRACE_DEBUG("bta_av_co_audio_init: %d", index);
+ APPL_TRACE_DEBUG("bta_av_co_audio_init: %d", tsep);
/* By default - no content protection info */
*p_num_protect = 0;
/* reset remote preference through setconfig */
bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_NONE;
- switch (index) {
- case BTC_SV_AV_AA_SBC_INDEX:
+ if (tsep == AVDT_TSEP_SRC) {
#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
- {
- UINT8 *p = p_protect_info;
-
- /* Content protection info - support SCMS-T */
- *p_num_protect = 1;
- *p++ = BTA_AV_CP_LOSC;
- UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
-
- }
+ do {
+ UINT8 *p = p_protect_info;
+
+ /* Content protection info - support SCMS-T */
+ *p_num_protect = 1;
+ *p++ = BTA_AV_CP_LOSC;
+ UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
+ } while (0);
#endif
/* Set up for SBC codec for SRC*/
- *p_codec_type = BTA_AV_CODEC_SBC;
+ *p_codec_type = BTA_AV_CODEC_SBC;
/* This should not fail because we are using constants for parameters */
- A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info);
-
- /* Codec is valid */
- return TRUE;
-#if (BTA_AV_SINK_INCLUDED == TRUE)
- case BTC_SV_AV_AA_SBC_SINK_INDEX:
+ A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info);
+ return TRUE;
+ } else if (tsep == AVDT_TSEP_SNK) {
*p_codec_type = BTA_AV_CODEC_SBC;
/* This should not fail because we are using constants for parameters */
/* Codec is valid */
return TRUE;
-#endif
- default:
- /* Not valid */
+ } else {
+ APPL_TRACE_WARNING("invalid SEP type %d", tsep);
return FALSE;
}
}
TRUE, 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_SERVCLASS_AUDIO_SOURCE);
+ TRUE, BTA_SEC_AUTHENTICATE, uuid);
}
btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_OPENING);
} break;
tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
esp_a2d_connection_state_t state;
btc_sm_state_t av_state;
- BTC_TRACE_DEBUG("status:%d, edr 0x%x\n", p_bta_data->open.status,
- p_bta_data->open.edr);
+ 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;
btc_av_cb.sm_handle =
btc_sm_init((const btc_sm_handler_t *)btc_av_state_handlers, BTC_AV_STATE_IDLE);
- btc_dm_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
-
if (service_id == BTA_A2DP_SINK_SERVICE_ID) {
btc_dm_enable_service(BTA_A2DP_SINK_SERVICE_ID);
+ } else {
+ btc_dm_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
}
btc_a2dp_on_init();
** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btc_av_execute_service(BOOLEAN b_enable)
+bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep)
{
if (b_enable) {
/* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
| BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR
| BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL,
bte_av_callback);
- BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos);
+ 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);
BTA_AvDisable();
return BT_STATUS_SUCCESS;
}
+/*******************************************************************************
+**
+** Function btc_av_source_execute_service
+**
+** Description Initializes/Shuts down the A2DP source service
+**
+** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btc_av_source_execute_service(BOOLEAN b_enable)
+{
+ return btc_av_execute_service(b_enable, AVDT_TSEP_SRC);
+}
+
/*******************************************************************************
**
** Function btc_av_sink_execute_service
*******************************************************************************/
bt_status_t btc_av_sink_execute_service(BOOLEAN b_enable)
{
+ bt_status_t ret = btc_av_execute_service(b_enable, AVDT_TSEP_SNK);
+ if (ret != BT_STATUS_SUCCESS) {
+ return ret;
+ }
#if (BTA_AV_SINK_INCLUDED == TRUE)
BTA_AvEnable_Sink(b_enable);
#endif