1 /******************************************************************************
3 * Copyright (C) 2004-2012 Broadcom Corporation
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 ******************************************************************************/
19 /******************************************************************************
21 * This is the advanced audio/video call-out function implementation for
24 ******************************************************************************/
30 #include "bta_av_api.h"
31 #include "bta_av_co.h"
32 #include "bta_av_ci.h"
33 #include "bta_av_sbc.h"
35 #include "btif_media.h"
36 #include "sbc_encoder.h"
37 #include "btif_av_co.h"
38 #include "btif_util.h"
41 /*****************************************************************************
43 *****************************************************************************/
45 #define FUNC_TRACE() APPL_TRACE_DEBUG("%s", __FUNCTION__);
47 /* Macro to retrieve the number of elements in a statically allocated array */
48 #define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a)/sizeof((__a)[0]))
50 /* MIN and MAX macros */
51 #define BTA_AV_CO_MIN(X,Y) ((X) < (Y) ? (X) : (Y))
52 #define BTA_AV_CO_MAX(X,Y) ((X) > (Y) ? (X) : (Y))
54 /* Macro to convert audio handle to index and vice versa */
55 #define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1)
56 #define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)
59 /* Offsets to access codec information in SBC codec */
60 #define BTA_AV_CO_SBC_FREQ_CHAN_OFF 3
61 #define BTA_AV_CO_SBC_BLOCK_BAND_OFF 4
62 #define BTA_AV_CO_SBC_MIN_BITPOOL_OFF 5
63 #define BTA_AV_CO_SBC_MAX_BITPOOL_OFF 6
65 #define BTA_AV_CO_SBC_MAX_BITPOOL 53
67 /* SCMS-T protect info */
68 const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00";
70 /* SBC SRC codec capabilities */
71 const tA2D_SBC_CIE bta_av_co_sbc_caps =
73 (A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
74 (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL), /* ch_mode */
75 (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */
76 (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */
77 (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S), /* alloc_mthd */
78 BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */
79 A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
82 /* SBC SINK codec capabilities */
83 const tA2D_SBC_CIE bta_av_co_sbc_sink_caps =
85 (A2D_SBC_IE_SAMP_FREQ_48 | A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
86 (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL), /* ch_mode */
87 (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */
88 (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */
89 (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S), /* alloc_mthd */
90 A2D_SBC_IE_MAX_BITPOOL, /* max_bitpool */
91 A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
94 #if !defined(BTIF_AV_SBC_DEFAULT_SAMP_FREQ)
95 #define BTIF_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_44
98 /* Default SBC codec configuration */
99 const tA2D_SBC_CIE btif_av_sbc_default_config =
101 BTIF_AV_SBC_DEFAULT_SAMP_FREQ, /* samp_freq */
102 A2D_SBC_IE_CH_MD_JOINT, /* ch_mode */
103 A2D_SBC_IE_BLOCKS_16, /* block_len */
104 A2D_SBC_IE_SUBBAND_8, /* num_subbands */
105 A2D_SBC_IE_ALLOC_MD_L, /* alloc_mthd */
106 BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */
107 A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
111 /*****************************************************************************
113 *****************************************************************************/
116 UINT8 sep_info_idx; /* local SEP index (in BTA tables) */
117 UINT8 seid; /* peer SEP index (in peer tables) */
118 UINT8 codec_type; /* peer SEP codec type */
119 UINT8 codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */
120 UINT8 num_protect; /* peer SEP number of CP elements */
121 UINT8 protect_info[BTA_AV_CP_INFO_LEN]; /* peer SEP content protection info */
126 BD_ADDR addr; /* address of audio/video peer */
127 tBTA_AV_CO_SINK snks[BTIF_SV_AV_AA_SEP_INDEX]; /* array of supported sinks */
128 tBTA_AV_CO_SINK srcs[BTIF_SV_AV_AA_SEP_INDEX]; /* array of supported srcs */
129 UINT8 num_snks; /* total number of sinks at peer */
130 UINT8 num_srcs; /* total number of srcs at peer */
131 UINT8 num_seps; /* total number of seids at peer */
132 UINT8 num_rx_snks; /* number of received sinks */
133 UINT8 num_rx_srcs; /* number of received srcs */
134 UINT8 num_sup_snks; /* number of supported sinks in the snks array */
135 UINT8 num_sup_srcs; /* number of supported srcs in the srcs array */
136 tBTA_AV_CO_SINK *p_snk; /* currently selected sink */
137 tBTA_AV_CO_SINK *p_src; /* currently selected src */
138 UINT8 codec_cfg[AVDT_CODEC_SIZE]; /* current codec configuration */
139 BOOLEAN cp_active; /* current CP configuration */
140 BOOLEAN acp; /* acceptor */
141 BOOLEAN recfg_needed; /* reconfiguration is needed */
142 BOOLEAN opened; /* opened */
143 UINT16 mtu; /* maximum transmit unit size */
144 UINT16 uuid_to_connect; /* uuid of peer device */
155 /* Connected peer information */
156 tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
157 /* Current codec configuration - access to this variable must be protected */
158 tBTIF_AV_CODEC_INFO codec_cfg;
159 tBTIF_AV_CODEC_INFO codec_cfg_setconfig; /* remote peer setconfig preference */
164 /* Control block instance */
165 static tBTA_AV_CO_CB bta_av_co_cb;
167 static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg);
168 static void bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER *p_peer);
169 static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo);
170 static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink);
171 static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index);
172 static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
173 static BOOLEAN bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
174 static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index);
178 /*******************************************************************************
180 ** Function bta_av_co_cp_is_active
182 ** Description Get the current configuration of content protection
184 ** Returns TRUE if the current streaming has CP, FALSE otherwise
186 *******************************************************************************/
187 BOOLEAN bta_av_co_cp_is_active(void)
190 return bta_av_co_cb.cp.active;
193 /*******************************************************************************
195 ** Function bta_av_co_cp_get_flag
197 ** Description Get content protection flag
198 ** BTA_AV_CP_SCMS_COPY_NEVER
199 ** BTA_AV_CP_SCMS_COPY_ONCE
200 ** BTA_AV_CP_SCMS_COPY_FREE
202 ** Returns The current flag value
204 *******************************************************************************/
205 UINT8 bta_av_co_cp_get_flag(void)
208 return bta_av_co_cb.cp.flag;
211 /*******************************************************************************
213 ** Function bta_av_co_cp_set_flag
215 ** Description Set content protection flag
216 ** BTA_AV_CP_SCMS_COPY_NEVER
217 ** BTA_AV_CP_SCMS_COPY_ONCE
218 ** BTA_AV_CP_SCMS_COPY_FREE
220 ** Returns TRUE if setting the SCMS flag is supported else FALSE
222 *******************************************************************************/
223 BOOLEAN bta_av_co_cp_set_flag(UINT8 cp_flag)
227 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
229 if (cp_flag != BTA_AV_CP_SCMS_COPY_FREE)
234 bta_av_co_cb.cp.flag = cp_flag;
238 /*******************************************************************************
240 ** Function bta_av_co_get_peer
242 ** Description find the peer entry for a given handle
244 ** Returns the control block
246 *******************************************************************************/
247 static tBTA_AV_CO_PEER *bta_av_co_get_peer(tBTA_AV_HNDL hndl)
252 index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl);
255 if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers))
257 APPL_TRACE_ERROR("bta_av_co_get_peer peer index out of bounds:%d", index);
261 return &bta_av_co_cb.peers[index];
264 /*******************************************************************************
266 ** Function bta_av_co_audio_init
268 ** Description This callout function is executed by AV when it is
269 ** started by calling BTA_AvRegister(). This function can be
270 ** used by the phone to initialize audio paths or for other
271 ** initialization purposes.
274 ** Returns Stream codec and content protection capabilities info.
276 *******************************************************************************/
277 BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_num_protect,
278 UINT8 *p_protect_info, UINT8 index)
282 APPL_TRACE_DEBUG("bta_av_co_audio_init: %d", index);
284 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
286 UINT8 *p = p_protect_info;
288 /* Content protection info - support SCMS-T */
290 *p++ = BTA_AV_CP_LOSC;
291 UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
295 /* By default - no content protection info */
300 /* reset remote preference through setconfig */
301 bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
305 case BTIF_SV_AV_AA_SBC_INDEX:
306 /* Set up for SBC codec for SRC*/
307 *p_codec_type = BTA_AV_CODEC_SBC;
309 /* This should not fail because we are using constants for parameters */
310 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info);
314 #if (BTA_AV_SINK_INCLUDED == TRUE)
315 case BTIF_SV_AV_AA_SBC_SINK_INDEX:
316 *p_codec_type = BTA_AV_CODEC_SBC;
318 /* This should not fail because we are using constants for parameters */
319 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_sink_caps, p_codec_info);
330 /*******************************************************************************
332 ** Function bta_av_co_audio_disc_res
334 ** Description This callout function is executed by AV to report the
335 ** number of stream end points (SEP) were found during the
336 ** AVDT stream discovery process.
341 *******************************************************************************/
342 BTA_API void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk,
343 UINT8 num_src, BD_ADDR addr, UINT16 uuid_local)
345 tBTA_AV_CO_PEER *p_peer;
349 APPL_TRACE_DEBUG("bta_av_co_audio_disc_res h:x%x num_seps:%d num_snk:%d num_src:%d",
350 hndl, num_seps, num_snk, num_src);
352 /* Find the peer info */
353 p_peer = bta_av_co_get_peer(hndl);
356 APPL_TRACE_ERROR("bta_av_co_audio_disc_res could not find peer entry");
360 /* Sanity check : this should never happen */
363 APPL_TRACE_ERROR("bta_av_co_audio_disc_res peer already opened");
366 /* Copy the discovery results */
367 bdcpy(p_peer->addr, addr);
368 p_peer->num_snks = num_snk;
369 p_peer->num_srcs = num_src;
370 p_peer->num_seps = num_seps;
371 p_peer->num_rx_snks = 0;
372 p_peer->num_rx_srcs = 0;
373 p_peer->num_sup_snks = 0;
374 if (uuid_local == UUID_SERVCLASS_AUDIO_SINK)
375 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE;
376 else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE)
377 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK;
380 /*******************************************************************************
382 ** Function bta_av_build_src_cfg
384 ** Description This function will build preferred config from src capabilities
387 ** Returns Pass or Fail for current getconfig.
389 *******************************************************************************/
390 void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap)
392 tA2D_SBC_CIE src_cap;
393 tA2D_SBC_CIE pref_cap;
396 /* initialize it to default SBC configuration */
397 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &btif_av_sbc_default_config, p_pref_cfg);
398 /* now try to build a preferred one */
399 /* parse configuration */
400 if ((status = A2D_ParsSbcInfo(&src_cap, p_src_cap, TRUE)) != 0)
402 APPL_TRACE_DEBUG(" Cant parse src cap ret = %d", status);
406 if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_48)
407 pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
408 else if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_44)
409 pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
411 if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_JOINT)
412 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_JOINT;
413 else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_STEREO)
414 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_STEREO;
415 else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL)
416 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL;
417 else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_MONO)
418 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_MONO;
420 if (src_cap.block_len & A2D_SBC_IE_BLOCKS_16)
421 pref_cap.block_len = A2D_SBC_IE_BLOCKS_16;
422 else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_12)
423 pref_cap.block_len = A2D_SBC_IE_BLOCKS_12;
424 else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_8)
425 pref_cap.block_len = A2D_SBC_IE_BLOCKS_8;
426 else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_4)
427 pref_cap.block_len = A2D_SBC_IE_BLOCKS_4;
429 if (src_cap.num_subbands & A2D_SBC_IE_SUBBAND_8)
430 pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_8;
431 else if(src_cap.num_subbands & A2D_SBC_IE_SUBBAND_4)
432 pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_4;
434 if (src_cap.alloc_mthd & A2D_SBC_IE_ALLOC_MD_L)
435 pref_cap.alloc_mthd = A2D_SBC_IE_ALLOC_MD_L;
436 else if(src_cap.alloc_mthd & A2D_SBC_IE_ALLOC_MD_S)
437 pref_cap.alloc_mthd = A2D_SBC_IE_ALLOC_MD_S;
439 pref_cap.max_bitpool = src_cap.max_bitpool;
440 pref_cap.min_bitpool = src_cap.min_bitpool;
442 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &pref_cap, p_pref_cfg);
445 /*******************************************************************************
447 ** Function bta_av_audio_sink_getconfig
449 ** Description This callout function is executed by AV to retrieve the
450 ** desired codec and content protection configuration for the
451 ** A2DP Sink audio stream in Initiator.
454 ** Returns Pass or Fail for current getconfig.
456 *******************************************************************************/
457 UINT8 bta_av_audio_sink_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
458 UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid, UINT8 *p_num_protect,
459 UINT8 *p_protect_info)
462 UINT8 result = A2D_FAIL;
464 tBTA_AV_CO_PEER *p_peer;
465 tBTA_AV_CO_SINK *p_src;
466 UINT8 pref_cfg[AVDT_CODEC_SIZE];
471 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig handle:0x%x codec_type:%d seid:%d",
472 hndl, codec_type, seid);
473 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
474 *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
476 /* Retrieve the peer info */
477 p_peer = bta_av_co_get_peer(hndl);
480 APPL_TRACE_ERROR("bta_av_audio_sink_getconfig could not find peer entry");
484 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
485 p_peer->opened, p_peer->num_srcs, p_peer->num_rx_srcs, p_peer->num_sup_srcs);
487 p_peer->num_rx_srcs++;
489 /* Check if this is a supported configuration */
493 case BTA_AV_CODEC_SBC:
503 /* If there is room for a new one */
504 if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))
506 p_src = &p_peer->srcs[p_peer->num_sup_srcs++];
508 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig saved caps[%x:%x:%x:%x:%x:%x]",
509 p_codec_info[1], p_codec_info[2], p_codec_info[3],
510 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
512 memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
513 p_src->codec_type = codec_type;
514 p_src->sep_info_idx = *p_sep_info_idx;
516 p_src->num_protect = *p_num_protect;
517 memcpy(p_src->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
521 APPL_TRACE_ERROR("bta_av_audio_sink_getconfig no more room for SRC info");
525 /* If last SNK get capabilities or all supported codec caps retrieved */
526 if ((p_peer->num_rx_srcs == p_peer->num_srcs) ||
527 (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)))
529 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig last SRC reached");
531 /* Protect access to bta_av_co_cb.codec_cfg */
534 /* Find a src that matches the codec config */
535 if (bta_av_co_audio_peer_src_supports_codec(p_peer, &index))
537 APPL_TRACE_DEBUG(" Codec Supported ");
538 p_src = &p_peer->srcs[index];
540 /* Build the codec configuration for this sink */
542 /* Save the new configuration */
543 p_peer->p_src = p_src;
544 /* get preferred config from src_caps */
545 bta_av_build_src_cfg(pref_cfg, p_src->codec_caps);
546 memcpy(p_peer->codec_cfg, pref_cfg, AVDT_CODEC_SIZE);
548 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
549 p_peer->codec_cfg[1], p_peer->codec_cfg[2], p_peer->codec_cfg[3],
550 p_peer->codec_cfg[4], p_peer->codec_cfg[5], p_peer->codec_cfg[6]);
551 /* By default, no content protection */
554 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
555 /* Check if this sink supports SCMS */
556 if (bta_av_co_audio_sink_has_scmst(p_sink))
558 p_peer->cp_active = TRUE;
559 bta_av_co_cb.cp.active = TRUE;
560 *p_num_protect = BTA_AV_CP_INFO_LEN;
561 memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN);
565 p_peer->cp_active = FALSE;
566 bta_av_co_cb.cp.active = FALSE;
570 *p_sep_info_idx = p_src->sep_info_idx;
571 memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
572 result = A2D_SUCCESS;
575 /* Protect access to bta_av_co_cb.codec_cfg */
580 /*******************************************************************************
582 ** Function bta_av_co_audio_getconfig
584 ** Description This callout function is executed by AV to retrieve the
585 ** desired codec and content protection configuration for the
589 ** Returns Stream codec and content protection configuration info.
591 *******************************************************************************/
592 BTA_API UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
593 UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid, UINT8 *p_num_protect,
594 UINT8 *p_protect_info)
597 UINT8 result = A2D_FAIL;
599 tBTA_AV_CO_PEER *p_peer;
600 tBTA_AV_CO_SINK *p_sink;
601 UINT8 codec_cfg[AVDT_CODEC_SIZE];
606 /* Retrieve the peer info */
607 p_peer = bta_av_co_get_peer(hndl);
610 APPL_TRACE_ERROR("bta_av_co_audio_getconfig could not find peer entry");
614 if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE)
616 result = bta_av_audio_sink_getconfig(hndl, codec_type, p_codec_info, p_sep_info_idx,
617 seid, p_num_protect, p_protect_info);
620 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d",
621 hndl, codec_type, seid);
622 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
623 *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
625 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
626 p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks);
628 p_peer->num_rx_snks++;
630 /* Check if this is a supported configuration */
634 case BTA_AV_CODEC_SBC:
644 /* If there is room for a new one */
645 if (p_peer->num_sup_snks < BTA_AV_CO_NUM_ELEMENTS(p_peer->snks))
647 p_sink = &p_peer->snks[p_peer->num_sup_snks++];
649 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig saved caps[%x:%x:%x:%x:%x:%x]",
650 p_codec_info[1], p_codec_info[2], p_codec_info[3],
651 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
653 memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
654 p_sink->codec_type = codec_type;
655 p_sink->sep_info_idx = *p_sep_info_idx;
657 p_sink->num_protect = *p_num_protect;
658 memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
662 APPL_TRACE_ERROR("bta_av_co_audio_getconfig no more room for SNK info");
666 /* If last SNK get capabilities or all supported codec capa retrieved */
667 if ((p_peer->num_rx_snks == p_peer->num_snks) ||
668 (p_peer->num_sup_snks == BTA_AV_CO_NUM_ELEMENTS(p_peer->snks)))
670 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig last sink reached");
672 /* Protect access to bta_av_co_cb.codec_cfg */
675 /* Find a sink that matches the codec config */
676 if (bta_av_co_audio_peer_supports_codec(p_peer, &index))
678 /* stop fetching caps once we retrieved a supported codec */
681 *p_sep_info_idx = p_peer->num_seps;
682 APPL_TRACE_EVENT("no need to fetch more SEPs");
685 p_sink = &p_peer->snks[index];
687 /* Build the codec configuration for this sink */
688 if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg))
690 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig reconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
691 codec_cfg[1], codec_cfg[2], codec_cfg[3],
692 codec_cfg[4], codec_cfg[5], codec_cfg[6]);
694 /* Save the new configuration */
695 p_peer->p_snk = p_sink;
696 memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
698 /* By default, no content protection */
701 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
702 /* Check if this sink supports SCMS */
703 if (bta_av_co_audio_sink_has_scmst(p_sink))
705 p_peer->cp_active = TRUE;
706 bta_av_co_cb.cp.active = TRUE;
707 *p_num_protect = BTA_AV_CP_INFO_LEN;
708 memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN);
712 p_peer->cp_active = FALSE;
713 bta_av_co_cb.cp.active = FALSE;
717 /* If acceptor -> reconfig otherwise reply for configuration */
720 if (p_peer->recfg_needed)
722 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig call BTA_AvReconfig(x%x)", hndl);
723 BTA_AvReconfig(hndl, TRUE, p_sink->sep_info_idx, p_peer->codec_cfg, *p_num_protect, (UINT8 *)bta_av_co_cp_scmst);
728 *p_sep_info_idx = p_sink->sep_info_idx;
729 memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
731 result = A2D_SUCCESS;
734 /* Protect access to bta_av_co_cb.codec_cfg */
740 /*******************************************************************************
742 ** Function bta_av_co_audio_setconfig
744 ** Description This callout function is executed by AV to set the codec and
745 ** content protection configuration of the audio stream.
750 *******************************************************************************/
751 BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
752 UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr, UINT8 num_protect, UINT8 *p_protect_info,
753 UINT8 t_local_sep, UINT8 avdt_handle)
756 tBTA_AV_CO_PEER *p_peer;
757 UINT8 status = A2D_SUCCESS;
758 UINT8 category = A2D_SUCCESS;
759 BOOLEAN recfg_needed = FALSE;
760 BOOLEAN codec_cfg_supported = FALSE;
766 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
767 p_codec_info[1], p_codec_info[2], p_codec_info[3],
768 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
769 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
770 num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
772 /* Retrieve the peer info */
773 p_peer = bta_av_co_get_peer(hndl);
776 APPL_TRACE_ERROR("bta_av_co_audio_setconfig could not find peer entry");
778 /* Call call-in rejecting the configuration */
779 bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE, avdt_handle);
782 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
783 p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks);
785 /* Sanity check: should not be opened at this point */
788 APPL_TRACE_ERROR("bta_av_co_audio_setconfig peer already in use");
791 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
792 if (num_protect != 0)
794 /* If CP is supported */
795 if ((num_protect != 1) ||
796 (bta_av_co_cp_is_scmst(p_protect_info) == FALSE))
798 APPL_TRACE_ERROR("bta_av_co_audio_setconfig wrong CP configuration");
799 status = A2D_BAD_CP_TYPE;
800 category = AVDT_ASC_PROTECT;
804 /* Do not support content protection for the time being */
805 if (num_protect != 0)
807 APPL_TRACE_ERROR("bta_av_co_audio_setconfig wrong CP configuration");
808 status = A2D_BAD_CP_TYPE;
809 category = AVDT_ASC_PROTECT;
812 if (status == A2D_SUCCESS)
814 if(AVDT_TSEP_SNK == t_local_sep)
816 codec_cfg_supported = bta_av_co_audio_sink_supports_config(codec_type, p_codec_info);
817 APPL_TRACE_DEBUG(" Peer is A2DP SRC ");
819 if(AVDT_TSEP_SRC == t_local_sep)
821 codec_cfg_supported = bta_av_co_audio_media_supports_config(codec_type, p_codec_info);
822 APPL_TRACE_DEBUG(" Peer is A2DP SINK ");
824 /* Check if codec configuration is supported */
825 if (codec_cfg_supported)
828 /* Protect access to bta_av_co_cb.codec_cfg */
831 /* Check if the configuration matches the current codec config */
832 switch (bta_av_co_cb.codec_cfg.id)
834 case BTIF_AV_CODEC_SBC:
835 if ((codec_type != BTA_AV_CODEC_SBC) || memcmp(p_codec_info, bta_av_co_cb.codec_cfg.info, 5))
839 else if ((num_protect == 1) && (!bta_av_co_cb.cp.active))
844 /* if remote side requests a restricted notify sinks preferred bitpool range as all other params are
845 already checked for validify */
846 APPL_TRACE_EVENT("remote peer setconfig bitpool range [%d:%d]",
847 p_codec_info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
848 p_codec_info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] );
850 bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_SBC;
851 memcpy(bta_av_co_cb.codec_cfg_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
852 if(AVDT_TSEP_SNK == t_local_sep)
854 /* If Peer is SRC, and our cfg subset matches with what is requested by peer, then
855 just accept what peer wants */
856 memcpy(bta_av_co_cb.codec_cfg.info, p_codec_info, AVDT_CODEC_SIZE);
857 recfg_needed = FALSE;
863 APPL_TRACE_ERROR("bta_av_co_audio_setconfig unsupported cid %d", bta_av_co_cb.codec_cfg.id);
867 /* Protect access to bta_av_co_cb.codec_cfg */
872 category = AVDT_ASC_CODEC;
873 status = A2D_WRONG_CODEC;
877 if (status != A2D_SUCCESS)
879 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig reject s=%d c=%d", status, category);
881 /* Call call-in rejecting the configuration */
882 bta_av_ci_setconfig(hndl, status, category, 0, NULL, FALSE, avdt_handle);
886 /* Mark that this is an acceptor peer */
888 p_peer->recfg_needed = recfg_needed;
890 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig accept reconf=%d", recfg_needed);
892 /* Call call-in accepting the configuration */
893 bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed, avdt_handle);
897 /*******************************************************************************
899 ** Function bta_av_co_audio_open
901 ** Description This function is called by AV when the audio stream connection
907 *******************************************************************************/
908 BTA_API void bta_av_co_audio_open(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
911 tBTA_AV_CO_PEER *p_peer;
912 UNUSED(p_codec_info);
916 APPL_TRACE_DEBUG("bta_av_co_audio_open mtu:%d codec_type:%d", mtu, codec_type);
918 /* Retrieve the peer info */
919 p_peer = bta_av_co_get_peer(hndl);
922 APPL_TRACE_ERROR("bta_av_co_audio_setconfig could not find peer entry");
926 p_peer->opened = TRUE;
931 /*******************************************************************************
933 ** Function bta_av_co_audio_close
935 ** Description This function is called by AV when the audio stream connection
941 *******************************************************************************/
942 BTA_API void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu)
945 tBTA_AV_CO_PEER *p_peer;
951 APPL_TRACE_DEBUG("bta_av_co_audio_close");
953 /* Retrieve the peer info */
954 p_peer = bta_av_co_get_peer(hndl);
957 /* Mark the peer closed and clean the peer info */
958 memset(p_peer, 0, sizeof(*p_peer));
962 APPL_TRACE_ERROR("bta_av_co_audio_close could not find peer entry");
965 /* reset remote preference through setconfig */
966 bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
969 /*******************************************************************************
971 ** Function bta_av_co_audio_start
973 ** Description This function is called by AV when the audio streaming data
974 ** transfer is started.
979 *******************************************************************************/
980 BTA_API void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
981 UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr)
985 UNUSED(p_codec_info);
986 UNUSED(p_no_rtp_hdr);
990 APPL_TRACE_DEBUG("bta_av_co_audio_start");
994 /*******************************************************************************
996 ** Function bta_av_co_audio_stop
998 ** Description This function is called by AV when the audio streaming data
999 ** transfer is stopped.
1004 *******************************************************************************/
1005 BTA_API extern void bta_av_co_audio_stop(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type)
1012 APPL_TRACE_DEBUG("bta_av_co_audio_stop");
1015 /*******************************************************************************
1017 ** Function bta_av_co_audio_src_data_path
1019 ** Description This function is called to manage data transfer from
1020 ** the audio codec to AVDTP.
1022 ** Returns Pointer to the GKI buffer to send, NULL if no buffer to send
1024 *******************************************************************************/
1025 BTA_API void * bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type, UINT32 *p_len,
1026 UINT32 *p_timestamp)
1033 p_buf = btif_media_aa_readbuf();
1038 case BTA_AV_CODEC_SBC:
1039 /* In media packet SBC, the following information is available:
1040 * p_buf->layer_specific : number of SBC frames in the packet
1041 * p_buf->word[0] : timestamp
1043 /* Retrieve the timestamp information from the media packet */
1044 *p_timestamp = *((UINT32 *) (p_buf + 1));
1046 /* Set up packet header */
1047 bta_av_sbc_bld_hdr(p_buf, p_buf->layer_specific);
1052 APPL_TRACE_ERROR("bta_av_co_audio_src_data_path Unsupported codec type (%d)", codec_type);
1055 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1058 if (bta_av_co_cp_is_active())
1062 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1063 *p = bta_av_co_cp_get_flag();
1071 /*******************************************************************************
1073 ** Function bta_av_co_audio_drop
1075 ** Description An Audio packet is dropped. .
1076 ** It's very likely that the connected headset with this handle
1077 ** is moved far away. The implementation may want to reduce
1078 ** the encoder bit rate setting to reduce the packet size.
1082 *******************************************************************************/
1083 void bta_av_co_audio_drop(tBTA_AV_HNDL hndl)
1087 APPL_TRACE_ERROR("bta_av_co_audio_drop dropped: x%x", hndl);
1090 /*******************************************************************************
1092 ** Function bta_av_co_audio_delay
1094 ** Description This function is called by AV when the audio stream connection
1095 ** needs to send the initial delay report to the connected SRC.
1100 *******************************************************************************/
1101 void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, UINT16 delay)
1105 APPL_TRACE_ERROR("bta_av_co_audio_delay handle: x%x, delay:0x%x", hndl, delay);
1110 /*******************************************************************************
1112 ** Function bta_av_co_audio_codec_build_config
1114 ** Description Build the codec configuration
1116 ** Returns TRUE if the codec was built successfully, FALSE otherwise
1118 *******************************************************************************/
1119 static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg)
1123 memset(p_codec_cfg, 0, AVDT_CODEC_SIZE);
1125 switch (bta_av_co_cb.codec_cfg.id)
1127 case BTIF_AV_CODEC_SBC:
1128 /* only copy the relevant portions for this codec to avoid issues when
1129 comparing codec configs covering larger codec sets than SBC (7 bytes) */
1130 memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF+1);
1132 /* Update the bit pool boundaries with the codec capabilities */
1133 p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
1134 p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
1136 APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config : bitpool min %d, max %d",
1137 p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1138 p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
1141 APPL_TRACE_ERROR("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
1148 /*******************************************************************************
1150 ** Function bta_av_co_audio_codec_cfg_matches_caps
1152 ** Description Check if a codec config matches a codec capabilities
1154 ** Returns TRUE if it codec config is supported, FALSE otherwise
1156 *******************************************************************************/
1157 static BOOLEAN bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id, const UINT8 *p_codec_caps, const UINT8 *p_codec_cfg)
1163 case BTIF_AV_CODEC_SBC:
1165 APPL_TRACE_EVENT("bta_av_co_audio_codec_cfg_matches_caps : min %d/%d max %d/%d",
1166 p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1167 p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1168 p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
1169 p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
1171 /* Must match all items exactly except bitpool boundaries which can be adjusted */
1172 if (!((p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF] & p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF]) &&
1173 (p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF] & p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF])))
1175 APPL_TRACE_EVENT("FALSE %x %x %x %x",
1176 p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
1177 p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
1178 p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF],
1179 p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]);
1186 APPL_TRACE_ERROR("bta_av_co_audio_codec_cfg_matches_caps: unsupported codec id %d", codec_id);
1190 APPL_TRACE_EVENT("TRUE");
1195 /*******************************************************************************
1197 ** Function bta_av_co_audio_codec_match
1199 ** Description Check if a codec capabilities supports the codec config
1201 ** Returns TRUE if the connection supports this codec, FALSE otherwise
1203 *******************************************************************************/
1204 static BOOLEAN bta_av_co_audio_codec_match(const UINT8 *p_codec_caps)
1208 return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg.id, p_codec_caps, bta_av_co_cb.codec_cfg.info);
1211 /*******************************************************************************
1213 ** Function bta_av_co_audio_peer_reset_config
1215 ** Description Reset the peer codec configuration
1219 *******************************************************************************/
1220 static void bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER *p_peer)
1224 /* Indicate that there is no currently selected sink */
1225 p_peer->p_snk = NULL;
1228 /*******************************************************************************
1230 ** Function bta_av_co_cp_is_scmst
1232 ** Description Check if a content protection service is SCMS-T
1234 ** Returns TRUE if this CP is SCMS-T, FALSE otherwise
1236 *******************************************************************************/
1237 static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo)
1242 if (*p_protectinfo >= BTA_AV_CP_LOSC)
1245 STREAM_TO_UINT16(cp_id, p_protectinfo);
1246 if (cp_id == BTA_AV_CP_SCMS_T_ID)
1248 APPL_TRACE_DEBUG("bta_av_co_cp_is_scmst: SCMS-T found");
1256 /*******************************************************************************
1258 ** Function bta_av_co_audio_sink_has_scmst
1260 ** Description Check if a sink supports SCMS-T
1262 ** Returns TRUE if the sink supports this CP, FALSE otherwise
1264 *******************************************************************************/
1265 static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink)
1271 /* Check if sink supports SCMS-T */
1272 index = p_sink->num_protect;
1273 p = &p_sink->protect_info[0];
1277 if (bta_av_co_cp_is_scmst(p))
1281 /* Move to the next SC */
1283 /* Decrement the SC counter */
1286 APPL_TRACE_DEBUG("bta_av_co_audio_sink_has_scmst: SCMS-T not found");
1290 /*******************************************************************************
1292 ** Function bta_av_co_audio_sink_supports_cp
1294 ** Description Check if a sink supports the current content protection
1296 ** Returns TRUE if the sink supports this CP, FALSE otherwise
1298 *******************************************************************************/
1299 static BOOLEAN bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK *p_sink)
1303 /* Check if content protection is enabled for this stream */
1304 if (bta_av_co_cp_get_flag() != BTA_AV_CP_SCMS_COPY_FREE)
1306 return bta_av_co_audio_sink_has_scmst(p_sink);
1310 APPL_TRACE_DEBUG("bta_av_co_audio_sink_supports_cp: not required");
1315 /*******************************************************************************
1317 ** Function bta_av_co_audio_peer_supports_codec
1319 ** Description Check if a connection supports the codec config
1321 ** Returns TRUE if the connection supports this codec, FALSE otherwise
1323 *******************************************************************************/
1324 static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index)
1330 /* Configure the codec type to look for */
1331 codec_type = bta_av_co_cb.codec_cfg.id;
1334 for (index = 0; index < p_peer->num_sup_snks; index++)
1336 if (p_peer->snks[index].codec_type == codec_type)
1338 switch (bta_av_co_cb.codec_cfg.id)
1340 case BTIF_AV_CODEC_SBC:
1341 if (p_snk_index) *p_snk_index = index;
1342 return bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps);
1347 APPL_TRACE_ERROR("bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
1356 /*******************************************************************************
1358 ** Function bta_av_co_audio_peer_src_supports_codec
1360 ** Description Check if a peer acting as src supports codec config
1362 ** Returns TRUE if the connection supports this codec, FALSE otherwise
1364 *******************************************************************************/
1365 static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index)
1371 /* Configure the codec type to look for */
1372 codec_type = bta_av_co_cb.codec_cfg.id;
1375 for (index = 0; index < p_peer->num_sup_srcs; index++)
1377 if (p_peer->srcs[index].codec_type == codec_type)
1379 switch (bta_av_co_cb.codec_cfg.id)
1381 case BTIF_AV_CODEC_SBC:
1382 if (p_src_index) *p_src_index = index;
1383 if (0 == bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps,
1384 (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps))
1391 APPL_TRACE_ERROR("peer_src_supports_codec: unsupported codec id %d",
1392 bta_av_co_cb.codec_cfg.id);
1401 /*******************************************************************************
1403 ** Function bta_av_co_audio_sink_supports_config
1405 ** Description Check if the media source supports a given configuration
1407 ** Returns TRUE if the media source supports this config, FALSE otherwise
1409 *******************************************************************************/
1410 static BOOLEAN bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg)
1416 case BTA_AV_CODEC_SBC:
1417 if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps))
1425 APPL_TRACE_ERROR("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type);
1432 /*******************************************************************************
1434 ** Function bta_av_co_audio_media_supports_config
1436 ** Description Check if the media sink supports a given configuration
1438 ** Returns TRUE if the media source supports this config, FALSE otherwise
1440 *******************************************************************************/
1441 static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg)
1447 case BTA_AV_CODEC_SBC:
1448 if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps))
1456 APPL_TRACE_ERROR("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type);
1463 /*******************************************************************************
1465 ** Function bta_av_co_audio_codec_supported
1467 ** Description Check if all opened connections are compatible with a codec
1468 ** configuration and content protection
1470 ** Returns TRUE if all opened devices support this codec, FALSE otherwise
1472 *******************************************************************************/
1473 BOOLEAN bta_av_co_audio_codec_supported(tBTIF_STATUS *p_status)
1477 tBTA_AV_CO_PEER *p_peer;
1478 tBTA_AV_CO_SINK *p_sink;
1479 UINT8 codec_cfg[AVDT_CODEC_SIZE];
1480 UINT8 num_protect = 0;
1481 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1487 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported");
1489 /* Check AV feeding is supported */
1490 *p_status = BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
1492 for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++)
1494 p_peer = &bta_av_co_cb.peers[index];
1497 if (bta_av_co_audio_peer_supports_codec(p_peer, &snk_index))
1499 p_sink = &p_peer->snks[snk_index];
1501 /* Check that this sink is compatible with the CP */
1502 if (!bta_av_co_audio_sink_supports_cp(p_sink))
1504 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported sink %d of peer %d doesn't support cp",
1506 *p_status = BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED;
1510 /* Build the codec configuration for this sink */
1511 if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg))
1513 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1514 /* Check if this sink supports SCMS */
1515 cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
1517 /* Check if this is a new configuration (new sink or new config) */
1518 if ((p_sink != p_peer->p_snk) ||
1519 (memcmp(codec_cfg, p_peer->codec_cfg, AVDT_CODEC_SIZE))
1520 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1521 || (p_peer->cp_active != cp_active)
1525 /* Save the new configuration */
1526 p_peer->p_snk = p_sink;
1527 memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
1528 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1529 p_peer->cp_active = cp_active;
1530 if (p_peer->cp_active)
1532 bta_av_co_cb.cp.active = TRUE;
1533 num_protect = BTA_AV_CP_INFO_LEN;
1537 bta_av_co_cb.cp.active = FALSE;
1540 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported call BTA_AvReconfig(x%x)", BTA_AV_CO_AUDIO_INDX_TO_HNDL(index));
1541 BTA_AvReconfig(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index), TRUE, p_sink->sep_info_idx,
1542 p_peer->codec_cfg, num_protect, (UINT8 *)bta_av_co_cp_scmst);
1548 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported index %d doesn't support codec", index);
1554 *p_status = BTIF_SUCCESS;
1558 /*******************************************************************************
1560 ** Function bta_av_co_audio_codec_reset
1562 ** Description Reset the current codec configuration
1566 *******************************************************************************/
1567 void bta_av_co_audio_codec_reset(void)
1572 /* Reset the current configuration to SBC */
1573 bta_av_co_cb.codec_cfg.id = BTIF_AV_CODEC_SBC;
1575 if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btif_av_sbc_default_config, bta_av_co_cb.codec_cfg.info) != A2D_SUCCESS)
1577 APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed");
1583 /*******************************************************************************
1585 ** Function bta_av_co_audio_set_codec
1587 ** Description Set the current codec configuration from the feeding type.
1588 ** This function is starting to modify the configuration, it
1589 ** should be protected.
1591 ** Returns TRUE if successful, FALSE otherwise
1593 *******************************************************************************/
1594 BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTIF_STATUS *p_status)
1596 tA2D_SBC_CIE sbc_config;
1597 tBTIF_AV_CODEC_INFO new_cfg;
1601 /* Check AV feeding is supported */
1602 *p_status = BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
1604 APPL_TRACE_DEBUG("bta_av_co_audio_set_codec cid=%d", p_feeding->format);
1606 /* Supported codecs */
1607 switch (p_feeding->format)
1609 case BTIF_AV_CODEC_PCM:
1610 new_cfg.id = BTIF_AV_CODEC_SBC;
1612 sbc_config = btif_av_sbc_default_config;
1613 if ((p_feeding->cfg.pcm.num_channel != 1) &&
1614 (p_feeding->cfg.pcm.num_channel != 2))
1616 APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM channel number unsupported");
1619 if ((p_feeding->cfg.pcm.bit_per_sample != 8) &&
1620 (p_feeding->cfg.pcm.bit_per_sample != 16))
1622 APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM sample size unsupported");
1625 switch (p_feeding->cfg.pcm.sampling_freq)
1633 sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
1639 sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
1642 APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM sampling frequency unsupported");
1646 /* Build the codec config */
1647 if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &sbc_config, new_cfg.info) != A2D_SUCCESS)
1649 APPL_TRACE_ERROR("bta_av_co_audio_set_codec A2D_BldSbcInfo failed");
1656 APPL_TRACE_ERROR("bta_av_co_audio_set_codec Feeding format unsupported");
1661 /* The new config was correctly built */
1662 bta_av_co_cb.codec_cfg = new_cfg;
1665 /* Check all devices support it */
1666 *p_status = BTIF_SUCCESS;
1667 return bta_av_co_audio_codec_supported(p_status);
1670 /*******************************************************************************
1672 ** Function bta_av_co_audio_get_sbc_config
1674 ** Description Retrieves the SBC codec configuration. If the codec in use
1675 ** is not SBC, return the default SBC codec configuration.
1677 ** Returns TRUE if codec is SBC, FALSE otherwise
1679 *******************************************************************************/
1680 BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_minmtu)
1682 BOOLEAN result = FALSE;
1684 tBTA_AV_CO_PEER *p_peer;
1685 tBTA_AV_CO_SINK *p_sink;
1687 APPL_TRACE_EVENT("bta_av_co_cb.codec_cfg.id : codec 0x%x", bta_av_co_cb.codec_cfg.id);
1689 /* Minimum MTU is by default very large */
1693 if (bta_av_co_cb.codec_cfg.id == BTIF_AV_CODEC_SBC)
1695 if (A2D_ParsSbcInfo(p_sbc_config, bta_av_co_cb.codec_cfg.info, FALSE) == A2D_SUCCESS)
1697 for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++)
1699 p_peer = &bta_av_co_cb.peers[index];
1702 if (p_peer->mtu < *p_minmtu)
1704 *p_minmtu = p_peer->mtu;
1706 for (jndex = 0; jndex < p_peer->num_sup_snks; jndex++)
1708 p_sink = &p_peer->snks[jndex];
1709 if (p_sink->codec_type == A2D_MEDIA_CT_SBC)
1711 /* Update the bitpool boundaries of the current config */
1712 p_sbc_config->min_bitpool =
1713 BTA_AV_CO_MAX(p_sink->codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1714 p_sbc_config->min_bitpool);
1715 p_sbc_config->max_bitpool =
1716 BTA_AV_CO_MIN(p_sink->codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
1717 p_sbc_config->max_bitpool);
1718 APPL_TRACE_EVENT("bta_av_co_audio_get_sbc_config : sink bitpool min %d, max %d",
1719 p_sbc_config->min_bitpool, p_sbc_config->max_bitpool);
1731 /* Not SBC, still return the default values */
1732 *p_sbc_config = btif_av_sbc_default_config;
1739 /*******************************************************************************
1741 ** Function bta_av_co_audio_discard_config
1743 ** Description Discard the codec configuration of a connection
1747 *******************************************************************************/
1748 void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl)
1750 tBTA_AV_CO_PEER *p_peer;
1754 /* Find the peer info */
1755 p_peer = bta_av_co_get_peer(hndl);
1758 APPL_TRACE_ERROR("bta_av_co_audio_discard_config could not find peer entry");
1762 /* Reset the peer codec configuration */
1763 bta_av_co_audio_peer_reset_config(p_peer);
1766 /*******************************************************************************
1768 ** Function bta_av_co_init
1770 ** Description Initialization
1774 *******************************************************************************/
1775 void bta_av_co_init(void)
1779 /* Reset the control block */
1780 memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));
1782 bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
1784 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1785 bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER);
1787 bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_FREE);
1790 /* Reset the current config */
1791 bta_av_co_audio_codec_reset();
1795 /*******************************************************************************
1797 ** Function bta_av_co_peer_cp_supported
1799 ** Description Checks if the peer supports CP
1801 ** Returns TRUE if the peer supports CP
1803 *******************************************************************************/
1804 BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl)
1806 tBTA_AV_CO_PEER *p_peer;
1807 tBTA_AV_CO_SINK *p_sink;
1812 /* Find the peer info */
1813 p_peer = bta_av_co_get_peer(hndl);
1816 APPL_TRACE_ERROR("bta_av_co_peer_cp_supported could not find peer entry");
1820 for (index = 0; index < p_peer->num_sup_snks; index++)
1822 p_sink = &p_peer->snks[index];
1823 if (p_sink->codec_type == A2D_MEDIA_CT_SBC)
1825 return bta_av_co_audio_sink_has_scmst(p_sink);
1828 APPL_TRACE_ERROR("bta_av_co_peer_cp_supported did not find SBC sink");
1833 /*******************************************************************************
1835 ** Function bta_av_co_get_remote_bitpool_pref
1837 ** Description Check if remote side did a setconfig within the limits
1838 ** of our exported bitpool range. If set we will set the
1839 ** remote preference.
1841 ** Returns TRUE if config set, FALSE otherwize
1843 *******************************************************************************/
1845 BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max)
1847 /* check if remote peer did a set config */
1848 if (bta_av_co_cb.codec_cfg_setconfig.id == BTIF_AV_CODEC_NONE)
1851 *min = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
1852 *max = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];