/******************************************************************************* ** ** Function bta_ma_get_body_length ** ** Description Returns the combined length in characters of the message ** content. ** ** Parameters p_body - pointer to bBody structure. ** ** Returns Length of the body message text. ** *******************************************************************************/ UINT32 bta_ma_get_body_length(tBTA_MA_BMSG_BODY * p_body) { UINT32 length = 0, len=0; tBTA_MA_BMSG_CONTENT * p_content; char * p_text; APPL_TRACE_EVENT0("bta_ma_get_body_length"); p_content = BTA_MaBmsgGetContentFromBody(p_body); while ( p_content ) { p_text= BTA_MaBmsgGetMsgContent(p_content); while ( p_text ) { len = strlen(p_text); length += len; APPL_TRACE_EVENT3("total=%d len=%d text=%s",length, len, p_text); p_text = BTA_MaBmsgGetNextMsgContent(p_content); } p_content = BTA_MaBmsgGetNextContent(p_content); } APPL_TRACE_EVENT1("bta_ma_get_body_length len=%d", length); return( length ); }
/******************************************************************************* ** ** Function bta_ma_stream_body_content ** ** Description Builds a body content <bmessage-body-content> into a stream. ** ** Parameters p_stream - Output stream. ** p_content - pointer to content structure. ** ** Returns void ** *******************************************************************************/ void bta_ma_stream_body_content(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_CONTENT * p_content) { char * p_text; APPL_TRACE_EVENT0("bta_ma_stream_body_content"); while ( p_stream && p_content ) { bta_ma_stream_str(p_stream, "\r\nBEGIN:MSG"); p_text = BTA_MaBmsgGetMsgContent(p_content); if ( p_text ) { bta_ma_stream_str(p_stream, "\r\n"); while ( p_text ) { bta_ma_stream_str(p_stream, p_text); p_text = BTA_MaBmsgGetNextMsgContent(p_content); } } bta_ma_stream_str(p_stream, "\r\nEND:MSG"); p_content = BTA_MaBmsgGetNextContent(p_content); } }
/******************************************************************************* ** ** Function bta_av_co_audio_codec_cfg_matches_caps ** ** Description Check if a codec config matches a codec capabilities ** ** Returns TRUE if it codec config is supported, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id, const UINT8 *p_codec_caps, const UINT8 *p_codec_cfg) { FUNC_TRACE(); switch(codec_id) { case BTIF_AV_CODEC_SBC: APPL_TRACE_EVENT4("bta_av_co_audio_codec_cfg_matches_caps : min %d/%d max %d/%d", p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]); /* Must match all items exactly except bitpool boundaries which can be adjusted */ if (!((p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF] & p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF]) && (p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF] & p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]))) { APPL_TRACE_EVENT4("FALSE %x %x %x %x", p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF], p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF], p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF], p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]); return FALSE; } break; default: APPL_TRACE_ERROR1("bta_av_co_audio_codec_cfg_matches_caps: unsupported codec id %d", codec_id); return FALSE; break; } APPL_TRACE_EVENT0("TRUE"); return TRUE; }
/******************************************************************************* ** ** Function bta_av_co_audio_getconfig ** ** Description This callout function is executed by AV to retrieve the ** desired codec and content protection configuration for the ** audio stream. ** ** ** Returns Stream codec and content protection configuration info. ** *******************************************************************************/ BTA_API UINT8 bta_av_co_audio_getconfig(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) { UINT8 result = A2D_FAIL; BOOLEAN supported; tBTA_AV_CO_PEER *p_peer; tBTA_AV_CO_SINK *p_sink; UINT8 codec_cfg[AVDT_CODEC_SIZE]; UINT8 index; FUNC_TRACE(); APPL_TRACE_DEBUG3("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d", hndl, codec_type, seid); APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x", *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]); /* Retrieve the peer info */ p_peer = bta_av_co_get_peer(hndl); if (p_peer == NULL) { APPL_TRACE_ERROR0("bta_av_co_audio_getconfig could not find peer entry"); return A2D_FAIL; } APPL_TRACE_DEBUG4("bta_av_co_audio_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)", p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks); /* Increment the number of received sinks capabilities */ p_peer->num_rx_snks++; /* Check if this is a supported configuration */ supported = FALSE; switch (codec_type) { case BTA_AV_CODEC_SBC: supported = TRUE; break; default: break; } if (supported) { /* If there is room for a new one */ if (p_peer->num_sup_snks < BTA_AV_CO_NUM_ELEMENTS(p_peer->snks)) { p_sink = &p_peer->snks[p_peer->num_sup_snks++]; APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig saved caps[%x:%x:%x:%x:%x:%x]", p_codec_info[1], p_codec_info[2], p_codec_info[3], p_codec_info[4], p_codec_info[5], p_codec_info[6]); memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE); p_sink->codec_type = codec_type; p_sink->sep_info_idx = *p_sep_info_idx; p_sink->seid = seid; p_sink->num_protect = *p_num_protect; memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN); } else { APPL_TRACE_ERROR0("bta_av_co_audio_getconfig no more room for SNK info"); } } /* If last SNK get capabilities or all supported codec capa retrieved */ if ((p_peer->num_rx_snks == p_peer->num_snks) || (p_peer->num_sup_snks == BTA_AV_CO_NUM_ELEMENTS(p_peer->snks))) { APPL_TRACE_DEBUG0("bta_av_co_audio_getconfig last sink reached"); /* Protect access to bta_av_co_cb.codec_cfg */ GKI_disable(); /* Find a sink that matches the codec config */ if (bta_av_co_audio_peer_supports_codec(p_peer, &index)) { /* stop fetching caps once we retrieved a supported codec */ if (p_peer->acp) { *p_sep_info_idx = p_peer->num_seps; APPL_TRACE_EVENT0("no need to fetch more SEPs"); } p_sink = &p_peer->snks[index]; /* Build the codec configuration for this sink */ if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg)) { APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig reconfig p_codec_info[%x:%x:%x:%x:%x:%x]", codec_cfg[1], codec_cfg[2], codec_cfg[3], codec_cfg[4], codec_cfg[5], codec_cfg[6]); /* Save the new configuration */ p_peer->p_snk = p_sink; memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE); /* By default, no content protection */ *p_num_protect = 0; #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) /* Check if this sink supports SCMS */ if (bta_av_co_audio_sink_has_scmst(p_sink)) { p_peer->cp_active = TRUE; bta_av_co_cb.cp.active = TRUE; *p_num_protect = BTA_AV_CP_INFO_LEN; memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN); } else { p_peer->cp_active = FALSE; bta_av_co_cb.cp.active = FALSE; } #endif /* If acceptor -> reconfig otherwise reply for configuration */ if (p_peer->acp) { if (p_peer->recfg_needed) { APPL_TRACE_DEBUG1("bta_av_co_audio_getconfig call BTA_AvReconfig(x%x)", hndl); BTA_AvReconfig(hndl, TRUE, p_sink->sep_info_idx, p_peer->codec_cfg, *p_num_protect, (UINT8 *)bta_av_co_cp_scmst); } } else { *p_sep_info_idx = p_sink->sep_info_idx; memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE); } result = A2D_SUCCESS; } } /* Protect access to bta_av_co_cb.codec_cfg */ GKI_enable(); } return result; }