1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2012 Broadcom Corporation
4 *
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:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This is the advanced audio/video call-out function implementation for
22 * BTC.
23 *
24 ******************************************************************************/
25 #include "string.h"
26 #include "common/bt_target.h"
27 #include "stack/a2d_api.h"
28 #include "stack/a2d_sbc.h"
29 #include "bta/bta_sys.h"
30 #include "bta/bta_av_api.h"
31 #include "bta/bta_av_co.h"
32 #include "bta/bta_av_ci.h"
33 #include "bta/bta_av_sbc.h"
34 #include "btc_a2dp.h"
35 #include "btc_a2dp_source.h"
36 #include "btc_av_co.h"
37 #include "btc/btc_util.h"
38 #include "osi/mutex.h"
39
40 #if BTC_AV_INCLUDED
41
42 /*****************************************************************************
43 ** Constants
44 *****************************************************************************/
45
46 #define FUNC_TRACE() APPL_TRACE_DEBUG("%s", __FUNCTION__);
47
48 /* Macro to retrieve the number of elements in a statically allocated array */
49 #define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a)/sizeof((__a)[0]))
50
51 /* MIN and MAX macros */
52 #define BTA_AV_CO_MIN(X,Y) ((X) < (Y) ? (X) : (Y))
53 #define BTA_AV_CO_MAX(X,Y) ((X) > (Y) ? (X) : (Y))
54
55 /* Macro to convert audio handle to index and vice versa */
56 #define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1)
57 #define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)
58
59
60 /* Offsets to access codec information in SBC codec */
61 #define BTA_AV_CO_SBC_FREQ_CHAN_OFF 3
62 #define BTA_AV_CO_SBC_BLOCK_BAND_OFF 4
63 #define BTA_AV_CO_SBC_MIN_BITPOOL_OFF 5
64 #define BTA_AV_CO_SBC_MAX_BITPOOL_OFF 6
65
66 #define BTA_AV_CO_SBC_MAX_BITPOOL 53
67
68 /* SCMS-T protect info */
69 const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00";
70
71 /* SBC SRC codec capabilities */
72 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 */
80 };
81
82 /* SBC SINK codec capabilities */
83 const tA2D_SBC_CIE bta_av_co_sbc_sink_caps = {
84 (A2D_SBC_IE_SAMP_FREQ_48 | A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
85 (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 */
86 (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */
87 (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */
88 (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S), /* alloc_mthd */
89 A2D_SBC_IE_MAX_BITPOOL, /* max_bitpool */
90 A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
91 };
92
93 #if !defined(BTC_AV_SBC_DEFAULT_SAMP_FREQ)
94 #define BTC_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_44
95 #endif
96
97 /* Default SBC codec configuration */
98 const tA2D_SBC_CIE btc_av_sbc_default_config = {
99 BTC_AV_SBC_DEFAULT_SAMP_FREQ, /* samp_freq */
100 A2D_SBC_IE_CH_MD_JOINT, /* ch_mode */
101 A2D_SBC_IE_BLOCKS_16, /* block_len */
102 A2D_SBC_IE_SUBBAND_8, /* num_subbands */
103 A2D_SBC_IE_ALLOC_MD_L, /* alloc_mthd */
104 BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */
105 A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
106 };
107
108 /* Control block instance */
109 #if AVRC_DYNAMIC_MEMORY == FALSE
110 tBTA_AV_CO_CB bta_av_co_cb;
111 #else
112 tBTA_AV_CO_CB *bta_av_co_cb_ptr;
113 #endif
114
115 static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg);
116 static void bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER *p_peer);
117 static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo);
118 static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink);
119 static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index);
120 static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
121 static BOOLEAN bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
122 static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index);
123
124
125
126 /*******************************************************************************
127 **
128 ** Function bta_av_co_cp_is_active
129 **
130 ** Description Get the current configuration of content protection
131 **
132 ** Returns TRUE if the current streaming has CP, FALSE otherwise
133 **
134 *******************************************************************************/
bta_av_co_cp_is_active(void)135 BOOLEAN bta_av_co_cp_is_active(void)
136 {
137 FUNC_TRACE();
138 return bta_av_co_cb.cp.active;
139 }
140
141 /*******************************************************************************
142 **
143 ** Function bta_av_co_cp_get_flag
144 **
145 ** Description Get content protection flag
146 ** BTA_AV_CP_SCMS_COPY_NEVER
147 ** BTA_AV_CP_SCMS_COPY_ONCE
148 ** BTA_AV_CP_SCMS_COPY_FREE
149 **
150 ** Returns The current flag value
151 **
152 *******************************************************************************/
bta_av_co_cp_get_flag(void)153 UINT8 bta_av_co_cp_get_flag(void)
154 {
155 FUNC_TRACE();
156 return bta_av_co_cb.cp.flag;
157 }
158
159 /*******************************************************************************
160 **
161 ** Function bta_av_co_cp_set_flag
162 **
163 ** Description Set content protection flag
164 ** BTA_AV_CP_SCMS_COPY_NEVER
165 ** BTA_AV_CP_SCMS_COPY_ONCE
166 ** BTA_AV_CP_SCMS_COPY_FREE
167 **
168 ** Returns TRUE if setting the SCMS flag is supported else FALSE
169 **
170 *******************************************************************************/
bta_av_co_cp_set_flag(UINT8 cp_flag)171 BOOLEAN bta_av_co_cp_set_flag(UINT8 cp_flag)
172 {
173 FUNC_TRACE();
174
175 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
176 #else
177 if (cp_flag != BTA_AV_CP_SCMS_COPY_FREE) {
178 return FALSE;
179 }
180 #endif
181 bta_av_co_cb.cp.flag = cp_flag;
182 return TRUE;
183 }
184
185 /*******************************************************************************
186 **
187 ** Function bta_av_co_get_peer
188 **
189 ** Description find the peer entry for a given handle
190 **
191 ** Returns the control block
192 **
193 *******************************************************************************/
bta_av_co_get_peer(tBTA_AV_HNDL hndl)194 static tBTA_AV_CO_PEER *bta_av_co_get_peer(tBTA_AV_HNDL hndl)
195 {
196 UINT8 index;
197 FUNC_TRACE();
198
199 index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl);
200
201 /* Sanity check */
202 if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) {
203 APPL_TRACE_ERROR("bta_av_co_get_peer peer index out of bounds:%d", index);
204 return NULL;
205 }
206
207 return &bta_av_co_cb.peers[index];
208 }
209
210 /*******************************************************************************
211 **
212 ** Function bta_av_co_audio_init
213 **
214 ** Description This callout function is executed by AV when it is
215 ** started by calling BTA_AvRegister(). This function can be
216 ** used by the phone to initialize audio paths or for other
217 ** initialization purposes.
218 **
219 **
220 ** Returns Stream codec and content protection capabilities info.
221 **
222 *******************************************************************************/
bta_av_co_audio_init(UINT8 * p_codec_type,UINT8 * p_codec_info,UINT8 * p_num_protect,UINT8 * p_protect_info,UINT8 tsep)223 BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_num_protect,
224 UINT8 *p_protect_info, UINT8 tsep)
225 {
226 FUNC_TRACE();
227
228 APPL_TRACE_DEBUG("bta_av_co_audio_init: %d", tsep);
229
230 /* By default - no content protection info */
231 *p_num_protect = 0;
232 *p_protect_info = 0;
233
234 /* reset remote preference through setconfig */
235 bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_NONE;
236
237 if (tsep == AVDT_TSEP_SRC) {
238 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
239 do {
240 UINT8 *p = p_protect_info;
241
242 /* Content protection info - support SCMS-T */
243 *p_num_protect = 1;
244 *p++ = BTA_AV_CP_LOSC;
245 UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
246 } while (0);
247 #endif
248 /* Set up for SBC codec for SRC*/
249 *p_codec_type = BTA_AV_CODEC_SBC;
250
251 /* This should not fail because we are using constants for parameters */
252 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info);
253 return TRUE;
254 } else if (tsep == AVDT_TSEP_SNK) {
255 *p_codec_type = BTA_AV_CODEC_SBC;
256
257 /* This should not fail because we are using constants for parameters */
258 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_sink_caps, p_codec_info);
259
260 /* Codec is valid */
261 return TRUE;
262 } else {
263 APPL_TRACE_WARNING("invalid SEP type %d", tsep);
264 return FALSE;
265 }
266 }
267
268 /*******************************************************************************
269 **
270 ** Function bta_av_co_audio_disc_res
271 **
272 ** Description This callout function is executed by AV to report the
273 ** number of stream end points (SEP) were found during the
274 ** AVDT stream discovery process.
275 **
276 **
277 ** Returns void.
278 **
279 *******************************************************************************/
bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl,UINT8 num_seps,UINT8 num_snk,UINT8 num_src,BD_ADDR addr,UINT16 uuid_local)280 void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk,
281 UINT8 num_src, BD_ADDR addr, UINT16 uuid_local)
282 {
283 tBTA_AV_CO_PEER *p_peer;
284
285 FUNC_TRACE();
286
287 APPL_TRACE_DEBUG("bta_av_co_audio_disc_res h:x%x num_seps:%d num_snk:%d num_src:%d",
288 hndl, num_seps, num_snk, num_src);
289
290 /* Find the peer info */
291 p_peer = bta_av_co_get_peer(hndl);
292 if (p_peer == NULL) {
293 APPL_TRACE_ERROR("bta_av_co_audio_disc_res could not find peer entry");
294 return;
295 }
296
297 /* Sanity check : this should never happen */
298 if (p_peer->opened) {
299 APPL_TRACE_ERROR("bta_av_co_audio_disc_res peer already opened");
300 }
301
302 /* Copy the discovery results */
303 bdcpy(p_peer->addr, addr);
304 p_peer->num_snks = num_snk;
305 p_peer->num_srcs = num_src;
306 p_peer->num_seps = num_seps;
307 p_peer->num_rx_snks = 0;
308 p_peer->num_rx_srcs = 0;
309 p_peer->num_sup_snks = 0;
310 if (uuid_local == UUID_SERVCLASS_AUDIO_SINK) {
311 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE;
312 } else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE) {
313 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK;
314 }
315 }
316
317 /*******************************************************************************
318 **
319 ** Function bta_av_build_src_cfg
320 **
321 ** Description This function will build preferred config from src capabilities
322 **
323 **
324 ** Returns Pass or Fail for current getconfig.
325 **
326 *******************************************************************************/
bta_av_build_src_cfg(UINT8 * p_pref_cfg,UINT8 * p_src_cap)327 void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap)
328 {
329 tA2D_SBC_CIE src_cap;
330 tA2D_SBC_CIE pref_cap;
331 UINT8 status = 0;
332
333 /* initialize it to default SBC configuration */
334 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &btc_av_sbc_default_config, p_pref_cfg);
335 /* now try to build a preferred one */
336 /* parse configuration */
337 if ((status = A2D_ParsSbcInfo(&src_cap, p_src_cap, TRUE)) != 0) {
338 APPL_TRACE_DEBUG(" Cant parse src cap ret = %d", status);
339 return ;
340 }
341
342 if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_48) {
343 pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
344 } else if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_44) {
345 pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
346 }
347
348 if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_JOINT) {
349 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_JOINT;
350 } else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_STEREO) {
351 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_STEREO;
352 } else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL) {
353 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL;
354 } else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_MONO) {
355 pref_cap.ch_mode = A2D_SBC_IE_CH_MD_MONO;
356 }
357
358 if (src_cap.block_len & A2D_SBC_IE_BLOCKS_16) {
359 pref_cap.block_len = A2D_SBC_IE_BLOCKS_16;
360 } else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_12) {
361 pref_cap.block_len = A2D_SBC_IE_BLOCKS_12;
362 } else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_8) {
363 pref_cap.block_len = A2D_SBC_IE_BLOCKS_8;
364 } else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_4) {
365 pref_cap.block_len = A2D_SBC_IE_BLOCKS_4;
366 }
367
368 if (src_cap.num_subbands & A2D_SBC_IE_SUBBAND_8) {
369 pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_8;
370 } else if (src_cap.num_subbands & A2D_SBC_IE_SUBBAND_4) {
371 pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_4;
372 }
373
374 if (src_cap.alloc_mthd & A2D_SBC_IE_ALLOC_MD_L) {
375 pref_cap.alloc_mthd = A2D_SBC_IE_ALLOC_MD_L;
376 } else if (src_cap.alloc_mthd & A2D_SBC_IE_ALLOC_MD_S) {
377 pref_cap.alloc_mthd = A2D_SBC_IE_ALLOC_MD_S;
378 }
379
380 pref_cap.max_bitpool = src_cap.max_bitpool;
381 pref_cap.min_bitpool = src_cap.min_bitpool;
382
383 A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &pref_cap, p_pref_cfg);
384 }
385
386 /*******************************************************************************
387 **
388 ** Function bta_av_audio_sink_getconfig
389 **
390 ** Description This callout function is executed by AV to retrieve the
391 ** desired codec and content protection configuration for the
392 ** A2DP Sink audio stream in Initiator.
393 **
394 **
395 ** Returns Pass or Fail for current getconfig.
396 **
397 *******************************************************************************/
bta_av_audio_sink_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)398 UINT8 bta_av_audio_sink_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
399 UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid, UINT8 *p_num_protect,
400 UINT8 *p_protect_info)
401 {
402
403 UINT8 result = A2D_FAIL;
404 BOOLEAN supported;
405 tBTA_AV_CO_PEER *p_peer;
406 tBTA_AV_CO_SINK *p_src;
407 UINT8 pref_cfg[AVDT_CODEC_SIZE];
408 UINT8 index;
409
410 FUNC_TRACE();
411
412 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig handle:0x%x codec_type:%d seid:%d",
413 hndl, codec_type, seid);
414 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
415 *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
416
417 /* Retrieve the peer info */
418 p_peer = bta_av_co_get_peer(hndl);
419 if (p_peer == NULL) {
420 APPL_TRACE_ERROR("bta_av_audio_sink_getconfig could not find peer entry");
421 return A2D_FAIL;
422 }
423
424 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
425 p_peer->opened, p_peer->num_srcs, p_peer->num_rx_srcs, p_peer->num_sup_srcs);
426
427 p_peer->num_rx_srcs++;
428
429 /* Check if this is a supported configuration */
430 supported = FALSE;
431 switch (codec_type) {
432 case BTA_AV_CODEC_SBC:
433 supported = TRUE;
434 break;
435
436 default:
437 break;
438 }
439
440 if (supported) {
441 /* If there is room for a new one */
442 if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)) {
443 p_src = &p_peer->srcs[p_peer->num_sup_srcs++];
444
445 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig saved caps[%x:%x:%x:%x:%x:%x]",
446 p_codec_info[1], p_codec_info[2], p_codec_info[3],
447 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
448
449 memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
450 p_src->codec_type = codec_type;
451 p_src->sep_info_idx = *p_sep_info_idx;
452 p_src->seid = seid;
453 p_src->num_protect = *p_num_protect;
454 memcpy(p_src->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
455 } else {
456 APPL_TRACE_ERROR("bta_av_audio_sink_getconfig no more room for SRC info");
457 }
458 }
459
460 /* If last SNK get capabilities or all supported codec caps retrieved */
461 if ((p_peer->num_rx_srcs == p_peer->num_srcs) ||
462 (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))) {
463 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig last SRC reached");
464
465 /* Protect access to bta_av_co_cb.codec_cfg */
466 osi_mutex_global_lock();
467
468 /* Find a src that matches the codec config */
469 if (bta_av_co_audio_peer_src_supports_codec(p_peer, &index)) {
470 APPL_TRACE_DEBUG(" Codec Supported ");
471 p_src = &p_peer->srcs[index];
472
473 /* Build the codec configuration for this sink */
474 {
475 /* Save the new configuration */
476 p_peer->p_src = p_src;
477 /* get preferred config from src_caps */
478 bta_av_build_src_cfg(pref_cfg, p_src->codec_caps);
479 memcpy(p_peer->codec_cfg, pref_cfg, AVDT_CODEC_SIZE);
480
481 APPL_TRACE_DEBUG("bta_av_audio_sink_getconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
482 p_peer->codec_cfg[1], p_peer->codec_cfg[2], p_peer->codec_cfg[3],
483 p_peer->codec_cfg[4], p_peer->codec_cfg[5], p_peer->codec_cfg[6]);
484 /* By default, no content protection */
485 *p_num_protect = 0;
486
487 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
488 p_peer->cp_active = FALSE;
489 bta_av_co_cb.cp.active = FALSE;
490 #endif
491
492 *p_sep_info_idx = p_src->sep_info_idx;
493 memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
494 result = A2D_SUCCESS;
495 }
496 }
497 /* Protect access to bta_av_co_cb.codec_cfg */
498 osi_mutex_global_unlock();
499 }
500 return result;
501 }
502 /*******************************************************************************
503 **
504 ** Function bta_av_co_audio_getconfig
505 **
506 ** Description This callout function is executed by AV to retrieve the
507 ** desired codec and content protection configuration for the
508 ** audio stream.
509 **
510 **
511 ** Returns Stream codec and content protection configuration info.
512 **
513 *******************************************************************************/
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)514 UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
515 UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid, UINT8 *p_num_protect,
516 UINT8 *p_protect_info)
517
518 {
519 UINT8 result = A2D_FAIL;
520 BOOLEAN supported;
521 tBTA_AV_CO_PEER *p_peer;
522 tBTA_AV_CO_SINK *p_sink;
523 UINT8 codec_cfg[AVDT_CODEC_SIZE];
524 UINT8 index;
525
526 FUNC_TRACE();
527
528 /* Retrieve the peer info */
529 p_peer = bta_av_co_get_peer(hndl);
530 if (p_peer == NULL) {
531 APPL_TRACE_ERROR("bta_av_co_audio_getconfig could not find peer entry");
532 return A2D_FAIL;
533 }
534
535 if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) {
536 result = bta_av_audio_sink_getconfig(hndl, codec_type, p_codec_info, p_sep_info_idx,
537 seid, p_num_protect, p_protect_info);
538 return result;
539 }
540 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d",
541 hndl, codec_type, seid);
542 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
543 *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
544
545 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
546 p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks);
547
548 p_peer->num_rx_snks++;
549
550 /* Check if this is a supported configuration */
551 supported = FALSE;
552 switch (codec_type) {
553 case BTA_AV_CODEC_SBC:
554 supported = TRUE;
555 break;
556
557 default:
558 break;
559 }
560
561 if (supported) {
562 /* If there is room for a new one */
563 if (p_peer->num_sup_snks < BTA_AV_CO_NUM_ELEMENTS(p_peer->snks)) {
564 p_sink = &p_peer->snks[p_peer->num_sup_snks++];
565
566 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig saved caps[%x:%x:%x:%x:%x:%x]",
567 p_codec_info[1], p_codec_info[2], p_codec_info[3],
568 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
569
570 memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
571 p_sink->codec_type = codec_type;
572 p_sink->sep_info_idx = *p_sep_info_idx;
573 p_sink->seid = seid;
574 p_sink->num_protect = *p_num_protect;
575 memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
576 } else {
577 APPL_TRACE_ERROR("bta_av_co_audio_getconfig no more room for SNK info");
578 }
579 }
580
581 /* If last SNK get capabilities or all supported codec capa retrieved */
582 if ((p_peer->num_rx_snks == p_peer->num_snks) ||
583 (p_peer->num_sup_snks == BTA_AV_CO_NUM_ELEMENTS(p_peer->snks))) {
584 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig last sink reached");
585
586 /* Protect access to bta_av_co_cb.codec_cfg */
587 osi_mutex_global_lock();
588
589 /* Find a sink that matches the codec config */
590 if (bta_av_co_audio_peer_supports_codec(p_peer, &index)) {
591 /* stop fetching caps once we retrieved a supported codec */
592 if (p_peer->acp) {
593 *p_sep_info_idx = p_peer->num_seps;
594 APPL_TRACE_EVENT("no need to fetch more SEPs");
595 }
596
597 p_sink = &p_peer->snks[index];
598
599 /* Build the codec configuration for this sink */
600 if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg)) {
601 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig reconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
602 codec_cfg[1], codec_cfg[2], codec_cfg[3],
603 codec_cfg[4], codec_cfg[5], codec_cfg[6]);
604
605 /* Save the new configuration */
606 p_peer->p_snk = p_sink;
607 memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
608
609 /* By default, no content protection */
610 *p_num_protect = 0;
611
612 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
613 /* Check if this sink supports SCMS */
614 if (bta_av_co_audio_sink_has_scmst(p_sink)) {
615 p_peer->cp_active = TRUE;
616 bta_av_co_cb.cp.active = TRUE;
617 *p_num_protect = BTA_AV_CP_INFO_LEN;
618 memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN);
619 } else {
620 p_peer->cp_active = FALSE;
621 bta_av_co_cb.cp.active = FALSE;
622 }
623 #endif
624
625 /* If acceptor -> reconfig otherwise reply for configuration */
626 if (p_peer->acp) {
627 if (p_peer->recfg_needed) {
628 APPL_TRACE_DEBUG("bta_av_co_audio_getconfig call BTA_AvReconfig(x%x)", hndl);
629 BTA_AvReconfig(hndl, TRUE, p_sink->sep_info_idx, p_peer->codec_cfg, *p_num_protect, (UINT8 *)bta_av_co_cp_scmst);
630 }
631 } else {
632 *p_sep_info_idx = p_sink->sep_info_idx;
633 memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
634 }
635 result = A2D_SUCCESS;
636 }
637 }
638 /* Protect access to bta_av_co_cb.codec_cfg */
639 osi_mutex_global_unlock();
640 }
641 return result;
642 }
643
644 /*******************************************************************************
645 **
646 ** Function bta_av_co_audio_setconfig
647 **
648 ** Description This callout function is executed by AV to set the codec and
649 ** content protection configuration of the audio stream.
650 **
651 **
652 ** Returns void
653 **
654 *******************************************************************************/
bta_av_co_audio_setconfig(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)655 void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
656 UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr, UINT8 num_protect, UINT8 *p_protect_info,
657 UINT8 t_local_sep, UINT8 avdt_handle)
658 {
659 tBTA_AV_CO_PEER *p_peer;
660 UINT8 status = A2D_SUCCESS;
661 UINT8 category = A2D_SUCCESS;
662 BOOLEAN recfg_needed = FALSE;
663 BOOLEAN codec_cfg_supported = FALSE;
664 UNUSED(seid);
665 UNUSED(addr);
666
667 FUNC_TRACE();
668
669 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
670 p_codec_info[1], p_codec_info[2], p_codec_info[3],
671 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
672 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
673 num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
674
675 /* Retrieve the peer info */
676 p_peer = bta_av_co_get_peer(hndl);
677 if (p_peer == NULL) {
678 APPL_TRACE_ERROR("bta_av_co_audio_setconfig could not find peer entry");
679
680 /* Call call-in rejecting the configuration */
681 bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE, avdt_handle);
682 return;
683 }
684 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
685 p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks);
686
687 /* Sanity check: should not be opened at this point */
688 if (p_peer->opened) {
689 APPL_TRACE_ERROR("bta_av_co_audio_setconfig peer already in use");
690 }
691
692 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
693 if (num_protect != 0) {
694 /* If CP is supported */
695 if ((num_protect != 1) ||
696 (bta_av_co_cp_is_scmst(p_protect_info) == FALSE)) {
697 APPL_TRACE_ERROR("bta_av_co_audio_setconfig wrong CP configuration");
698 status = A2D_BAD_CP_TYPE;
699 category = AVDT_ASC_PROTECT;
700 }
701 }
702 #else
703 /* Do not support content protection for the time being */
704 if (num_protect != 0) {
705 APPL_TRACE_ERROR("bta_av_co_audio_setconfig wrong CP configuration");
706 status = A2D_BAD_CP_TYPE;
707 category = AVDT_ASC_PROTECT;
708 }
709 #endif
710 if (status == A2D_SUCCESS) {
711 if (AVDT_TSEP_SNK == t_local_sep) {
712 codec_cfg_supported = bta_av_co_audio_sink_supports_config(codec_type, p_codec_info);
713 APPL_TRACE_DEBUG(" Peer is A2DP SRC ");
714 }
715 if (AVDT_TSEP_SRC == t_local_sep) {
716 codec_cfg_supported = bta_av_co_audio_media_supports_config(codec_type, p_codec_info);
717 APPL_TRACE_DEBUG(" Peer is A2DP SINK ");
718 }
719 /* Check if codec configuration is supported */
720 if (codec_cfg_supported) {
721
722 /* Protect access to bta_av_co_cb.codec_cfg */
723 osi_mutex_global_lock();
724
725 /* Check if the configuration matches the current codec config */
726 switch (bta_av_co_cb.codec_cfg.id) {
727 case BTC_AV_CODEC_SBC:
728 if ((codec_type != BTA_AV_CODEC_SBC) || memcmp(p_codec_info, bta_av_co_cb.codec_cfg.info, 5)) {
729 recfg_needed = TRUE;
730 } else if ((num_protect == 1) && (!bta_av_co_cb.cp.active)) {
731 recfg_needed = TRUE;
732 }
733
734 /* if remote side requests a restricted notify sinks preferred bitpool range as all other params are
735 already checked for validify */
736 APPL_TRACE_EVENT("remote peer setconfig bitpool range [%d:%d]",
737 p_codec_info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
738 p_codec_info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] );
739
740 bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_SBC;
741 memcpy(bta_av_co_cb.codec_cfg_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
742 if (AVDT_TSEP_SNK == t_local_sep) {
743 /* If Peer is SRC, and our cfg subset matches with what is requested by peer, then
744 just accept what peer wants */
745 memcpy(bta_av_co_cb.codec_cfg.info, p_codec_info, AVDT_CODEC_SIZE);
746 recfg_needed = FALSE;
747 }
748 break;
749
750
751 default:
752 APPL_TRACE_ERROR("bta_av_co_audio_setconfig unsupported cid %d", bta_av_co_cb.codec_cfg.id);
753 recfg_needed = TRUE;
754 break;
755 }
756 /* Protect access to bta_av_co_cb.codec_cfg */
757 osi_mutex_global_unlock();
758 } else {
759 category = AVDT_ASC_CODEC;
760 status = A2D_WRONG_CODEC;
761 }
762 }
763
764 if (status != A2D_SUCCESS) {
765 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig reject s=%d c=%d", status, category);
766
767 /* Call call-in rejecting the configuration */
768 bta_av_ci_setconfig(hndl, status, category, 0, NULL, FALSE, avdt_handle);
769 } else {
770 /* Mark that this is an acceptor peer */
771 p_peer->acp = TRUE;
772 p_peer->recfg_needed = recfg_needed;
773
774 APPL_TRACE_DEBUG("bta_av_co_audio_setconfig accept reconf=%d", recfg_needed);
775
776 /* Call call-in accepting the configuration */
777 bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed, avdt_handle);
778 }
779 }
780
781 /*******************************************************************************
782 **
783 ** Function bta_av_co_audio_open
784 **
785 ** Description This function is called by AV when the audio stream connection
786 ** is opened.
787 **
788 **
789 ** Returns void
790 **
791 *******************************************************************************/
bta_av_co_audio_open(tBTA_AV_HNDL hndl,tBTA_AV_CODEC codec_type,UINT8 * p_codec_info,UINT16 mtu)792 void bta_av_co_audio_open(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
793 UINT16 mtu)
794 {
795 tBTA_AV_CO_PEER *p_peer;
796 UNUSED(p_codec_info);
797
798 FUNC_TRACE();
799
800 APPL_TRACE_DEBUG("bta_av_co_audio_open mtu:%d codec_type:%d", mtu, codec_type);
801
802 /* Retrieve the peer info */
803 p_peer = bta_av_co_get_peer(hndl);
804 if (p_peer == NULL) {
805 APPL_TRACE_ERROR("bta_av_co_audio_setconfig could not find peer entry");
806 } else {
807 p_peer->opened = TRUE;
808 p_peer->mtu = mtu;
809 }
810 }
811
812 /*******************************************************************************
813 **
814 ** Function bta_av_co_audio_close
815 **
816 ** Description This function is called by AV when the audio stream connection
817 ** is closed.
818 **
819 **
820 ** Returns void
821 **
822 *******************************************************************************/
bta_av_co_audio_close(tBTA_AV_HNDL hndl,tBTA_AV_CODEC codec_type,UINT16 mtu)823 void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu)
824
825 {
826 tBTA_AV_CO_PEER *p_peer;
827 UNUSED(codec_type);
828 UNUSED(mtu);
829
830 FUNC_TRACE();
831
832 APPL_TRACE_DEBUG("bta_av_co_audio_close");
833
834 /* Retrieve the peer info */
835 p_peer = bta_av_co_get_peer(hndl);
836 if (p_peer) {
837 /* Mark the peer closed and clean the peer info */
838 memset(p_peer, 0, sizeof(*p_peer));
839 } else {
840 APPL_TRACE_ERROR("bta_av_co_audio_close could not find peer entry");
841 }
842
843 /* reset remote preference through setconfig */
844 bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_NONE;
845 }
846
847 /*******************************************************************************
848 **
849 ** Function bta_av_co_audio_start
850 **
851 ** Description This function is called by AV when the audio streaming data
852 ** transfer is started.
853 **
854 **
855 ** Returns void
856 **
857 *******************************************************************************/
bta_av_co_audio_start(tBTA_AV_HNDL hndl,tBTA_AV_CODEC codec_type,UINT8 * p_codec_info,BOOLEAN * p_no_rtp_hdr)858 void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
859 UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr)
860 {
861 UNUSED(hndl);
862 UNUSED(codec_type);
863 UNUSED(p_codec_info);
864 UNUSED(p_no_rtp_hdr);
865
866 FUNC_TRACE();
867
868 APPL_TRACE_DEBUG("bta_av_co_audio_start");
869
870 }
871
872 /*******************************************************************************
873 **
874 ** Function bta_av_co_audio_stop
875 **
876 ** Description This function is called by AV when the audio streaming data
877 ** transfer is stopped.
878 **
879 **
880 ** Returns void
881 **
882 *******************************************************************************/
bta_av_co_audio_stop(tBTA_AV_HNDL hndl,tBTA_AV_CODEC codec_type)883 extern void bta_av_co_audio_stop(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type)
884 {
885 UNUSED(hndl);
886 UNUSED(codec_type);
887
888 FUNC_TRACE();
889
890 APPL_TRACE_DEBUG("bta_av_co_audio_stop");
891 }
892
893 /*******************************************************************************
894 **
895 ** Function bta_av_co_audio_src_data_path
896 **
897 ** Description This function is called to manage data transfer from
898 ** the audio codec to AVDTP.
899 **
900 ** Returns Pointer to the buffer to send, NULL if no buffer to send
901 **
902 *******************************************************************************/
bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type,UINT32 * p_len,UINT32 * p_timestamp)903 void *bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type, UINT32 *p_len,
904 UINT32 *p_timestamp)
905 {
906 #if BTC_AV_SRC_INCLUDED
907 BT_HDR *p_buf;
908 UNUSED(p_len);
909
910 FUNC_TRACE();
911
912 p_buf = btc_a2dp_source_audio_readbuf();
913 if (p_buf != NULL) {
914 switch (codec_type) {
915 case BTA_AV_CODEC_SBC:
916 /* In media packet SBC, the following information is available:
917 * p_buf->layer_specific : number of SBC frames in the packet
918 * p_buf->word[0] : timestamp
919 */
920 /* Retrieve the timestamp information from the media packet */
921 *p_timestamp = *((UINT32 *) (p_buf + 1));
922
923 /* Set up packet header */
924 bta_av_sbc_bld_hdr(p_buf, p_buf->layer_specific);
925 break;
926
927
928 default:
929 APPL_TRACE_ERROR("bta_av_co_audio_src_data_path Unsupported codec type (%d)", codec_type);
930 break;
931 }
932 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
933 {
934 UINT8 *p;
935 if (bta_av_co_cp_is_active()) {
936 p_buf->len++;
937 p_buf->offset--;
938 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
939 *p = bta_av_co_cp_get_flag();
940 }
941 }
942 #endif
943 }
944 return p_buf;
945 #else /* BTC_AV_SRC_INCLUDED */
946 return NULL;
947 #endif /* BTC_AV_SRC_INCLUDED */
948 }
949
950 /*******************************************************************************
951 **
952 ** Function bta_av_co_audio_drop
953 **
954 ** Description An Audio packet is dropped. .
955 ** It's very likely that the connected headset with this handle
956 ** is moved far away. The implementation may want to reduce
957 ** the encoder bit rate setting to reduce the packet size.
958 **
959 ** Returns void
960 **
961 *******************************************************************************/
bta_av_co_audio_drop(tBTA_AV_HNDL hndl)962 void bta_av_co_audio_drop(tBTA_AV_HNDL hndl)
963 {
964 FUNC_TRACE();
965
966 APPL_TRACE_ERROR("bta_av_co_audio_drop dropped: x%x", hndl);
967 }
968
969 /*******************************************************************************
970 **
971 ** Function bta_av_co_audio_delay
972 **
973 ** Description This function is called by AV when the audio stream connection
974 ** needs to send the initial delay report to the connected SRC.
975 **
976 **
977 ** Returns void
978 **
979 *******************************************************************************/
bta_av_co_audio_delay(tBTA_AV_HNDL hndl,UINT16 delay)980 void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, UINT16 delay)
981 {
982 FUNC_TRACE();
983
984 APPL_TRACE_ERROR("bta_av_co_audio_delay handle: x%x, delay:0x%x", hndl, delay);
985 }
986
987
988
989 /*******************************************************************************
990 **
991 ** Function bta_av_co_audio_codec_build_config
992 **
993 ** Description Build the codec configuration
994 **
995 ** Returns TRUE if the codec was built successfully, FALSE otherwise
996 **
997 *******************************************************************************/
bta_av_co_audio_codec_build_config(const UINT8 * p_codec_caps,UINT8 * p_codec_cfg)998 static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg)
999 {
1000 FUNC_TRACE();
1001
1002 memset(p_codec_cfg, 0, AVDT_CODEC_SIZE);
1003
1004 switch (bta_av_co_cb.codec_cfg.id) {
1005 case BTC_AV_CODEC_SBC:
1006 /* only copy the relevant portions for this codec to avoid issues when
1007 comparing codec configs covering larger codec sets than SBC (7 bytes) */
1008 memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF + 1);
1009
1010 /* Update the bit pool boundaries with the codec capabilities */
1011 p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
1012 p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
1013
1014 APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config : bitpool min %d, max %d",
1015 p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1016 p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
1017 break;
1018 default:
1019 APPL_TRACE_ERROR("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
1020 return FALSE;
1021 break;
1022 }
1023 return TRUE;
1024 }
1025
1026 /*******************************************************************************
1027 **
1028 ** Function bta_av_co_audio_codec_cfg_matches_caps
1029 **
1030 ** Description Check if a codec config matches a codec capabilities
1031 **
1032 ** Returns TRUE if it codec config is supported, FALSE otherwise
1033 **
1034 *******************************************************************************/
bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id,const UINT8 * p_codec_caps,const UINT8 * p_codec_cfg)1035 static BOOLEAN bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id, const UINT8 *p_codec_caps, const UINT8 *p_codec_cfg)
1036 {
1037 FUNC_TRACE();
1038
1039 switch (codec_id) {
1040 case BTC_AV_CODEC_SBC:
1041
1042 APPL_TRACE_EVENT("bta_av_co_audio_codec_cfg_matches_caps : min %d/%d max %d/%d",
1043 p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1044 p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1045 p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
1046 p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
1047
1048 /* Must match all items exactly except bitpool boundaries which can be adjusted */
1049 if (!((p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF] & p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF]) &&
1050 (p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF] & p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]))) {
1051 APPL_TRACE_EVENT("FALSE %x %x %x %x",
1052 p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
1053 p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
1054 p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF],
1055 p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]);
1056 return FALSE;
1057 }
1058 break;
1059
1060
1061 default:
1062 APPL_TRACE_ERROR("bta_av_co_audio_codec_cfg_matches_caps: unsupported codec id %d", codec_id);
1063 return FALSE;
1064 break;
1065 }
1066 APPL_TRACE_EVENT("TRUE");
1067
1068 return TRUE;
1069 }
1070
1071 /*******************************************************************************
1072 **
1073 ** Function bta_av_co_audio_codec_match
1074 **
1075 ** Description Check if a codec capabilities supports the codec config
1076 **
1077 ** Returns TRUE if the connection supports this codec, FALSE otherwise
1078 **
1079 *******************************************************************************/
bta_av_co_audio_codec_match(const UINT8 * p_codec_caps)1080 static BOOLEAN bta_av_co_audio_codec_match(const UINT8 *p_codec_caps)
1081 {
1082 FUNC_TRACE();
1083
1084 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);
1085 }
1086
1087 /*******************************************************************************
1088 **
1089 ** Function bta_av_co_audio_peer_reset_config
1090 **
1091 ** Description Reset the peer codec configuration
1092 **
1093 ** Returns Nothing
1094 **
1095 *******************************************************************************/
bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER * p_peer)1096 static void bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER *p_peer)
1097 {
1098 FUNC_TRACE();
1099
1100 /* Indicate that there is no currently selected sink */
1101 p_peer->p_snk = NULL;
1102 }
1103
1104 /*******************************************************************************
1105 **
1106 ** Function bta_av_co_cp_is_scmst
1107 **
1108 ** Description Check if a content protection service is SCMS-T
1109 **
1110 ** Returns TRUE if this CP is SCMS-T, FALSE otherwise
1111 **
1112 *******************************************************************************/
bta_av_co_cp_is_scmst(const UINT8 * p_protectinfo)1113 static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo)
1114 {
1115 UINT16 cp_id;
1116 FUNC_TRACE();
1117
1118 if (*p_protectinfo >= BTA_AV_CP_LOSC) {
1119 p_protectinfo++;
1120 STREAM_TO_UINT16(cp_id, p_protectinfo);
1121 if (cp_id == BTA_AV_CP_SCMS_T_ID) {
1122 APPL_TRACE_DEBUG("bta_av_co_cp_is_scmst: SCMS-T found");
1123 return TRUE;
1124 }
1125 }
1126
1127 return FALSE;
1128 }
1129
1130 /*******************************************************************************
1131 **
1132 ** Function bta_av_co_audio_sink_has_scmst
1133 **
1134 ** Description Check if a sink supports SCMS-T
1135 **
1136 ** Returns TRUE if the sink supports this CP, FALSE otherwise
1137 **
1138 *******************************************************************************/
bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK * p_sink)1139 static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink)
1140 {
1141 UINT8 index;
1142 const UINT8 *p;
1143 FUNC_TRACE();
1144
1145 /* Check if sink supports SCMS-T */
1146 index = p_sink->num_protect;
1147 p = &p_sink->protect_info[0];
1148
1149 while (index) {
1150 if (bta_av_co_cp_is_scmst(p)) {
1151 return TRUE;
1152 }
1153 /* Move to the next SC */
1154 p += *p + 1;
1155 /* Decrement the SC counter */
1156 index--;
1157 }
1158 APPL_TRACE_DEBUG("bta_av_co_audio_sink_has_scmst: SCMS-T not found");
1159 return FALSE;
1160 }
1161
1162 /*******************************************************************************
1163 **
1164 ** Function bta_av_co_audio_sink_supports_cp
1165 **
1166 ** Description Check if a sink supports the current content protection
1167 **
1168 ** Returns TRUE if the sink supports this CP, FALSE otherwise
1169 **
1170 *******************************************************************************/
bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK * p_sink)1171 static BOOLEAN bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK *p_sink)
1172 {
1173 FUNC_TRACE();
1174
1175 /* Check if content protection is enabled for this stream */
1176 if (bta_av_co_cp_get_flag() != BTA_AV_CP_SCMS_COPY_FREE) {
1177 return bta_av_co_audio_sink_has_scmst(p_sink);
1178 } else {
1179 APPL_TRACE_DEBUG("bta_av_co_audio_sink_supports_cp: not required");
1180 return TRUE;
1181 }
1182 }
1183
1184 /*******************************************************************************
1185 **
1186 ** Function bta_av_co_audio_peer_supports_codec
1187 **
1188 ** Description Check if a connection supports the codec config
1189 **
1190 ** Returns TRUE if the connection supports this codec, FALSE otherwise
1191 **
1192 *******************************************************************************/
bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER * p_peer,UINT8 * p_snk_index)1193 static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index)
1194 {
1195 int index;
1196 UINT8 codec_type;
1197 FUNC_TRACE();
1198
1199 /* Configure the codec type to look for */
1200 codec_type = bta_av_co_cb.codec_cfg.id;
1201
1202
1203 for (index = 0; index < p_peer->num_sup_snks; index++) {
1204 if (p_peer->snks[index].codec_type == codec_type) {
1205 switch (bta_av_co_cb.codec_cfg.id) {
1206 case BTC_AV_CODEC_SBC:
1207 if (p_snk_index) {
1208 *p_snk_index = index;
1209 }
1210 return bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps);
1211 break;
1212
1213
1214 default:
1215 APPL_TRACE_ERROR("bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
1216 return FALSE;
1217 break;
1218 }
1219 }
1220 }
1221 return FALSE;
1222 }
1223
1224 /*******************************************************************************
1225 **
1226 ** Function bta_av_co_audio_peer_src_supports_codec
1227 **
1228 ** Description Check if a peer acting as src supports codec config
1229 **
1230 ** Returns TRUE if the connection supports this codec, FALSE otherwise
1231 **
1232 *******************************************************************************/
bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER * p_peer,UINT8 * p_src_index)1233 static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index)
1234 {
1235 int index;
1236 UINT8 codec_type;
1237 FUNC_TRACE();
1238
1239 /* Configure the codec type to look for */
1240 codec_type = bta_av_co_cb.codec_cfg.id;
1241
1242
1243 for (index = 0; index < p_peer->num_sup_srcs; index++) {
1244 if (p_peer->srcs[index].codec_type == codec_type) {
1245 switch (bta_av_co_cb.codec_cfg.id) {
1246 case BTC_AV_CODEC_SBC:
1247 if (p_src_index) {
1248 *p_src_index = index;
1249 }
1250 if (0 == bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps,
1251 (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps)) {
1252 return TRUE;
1253 }
1254 break;
1255
1256 default:
1257 APPL_TRACE_ERROR("peer_src_supports_codec: unsupported codec id %d",
1258 bta_av_co_cb.codec_cfg.id);
1259 return FALSE;
1260 break;
1261 }
1262 }
1263 }
1264 return FALSE;
1265 }
1266
1267 /*******************************************************************************
1268 **
1269 ** Function bta_av_co_audio_sink_supports_config
1270 **
1271 ** Description Check if the media source supports a given configuration
1272 **
1273 ** Returns TRUE if the media source supports this config, FALSE otherwise
1274 **
1275 *******************************************************************************/
bta_av_co_audio_sink_supports_config(UINT8 codec_type,const UINT8 * p_codec_cfg)1276 static BOOLEAN bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg)
1277 {
1278 FUNC_TRACE();
1279
1280 switch (codec_type) {
1281 case BTA_AV_CODEC_SBC:
1282 if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps)) {
1283 return FALSE;
1284 }
1285 break;
1286
1287
1288 default:
1289 APPL_TRACE_ERROR("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type);
1290 return FALSE;
1291 break;
1292 }
1293 return TRUE;
1294 }
1295
1296 /*******************************************************************************
1297 **
1298 ** Function bta_av_co_audio_media_supports_config
1299 **
1300 ** Description Check if the media sink supports a given configuration
1301 **
1302 ** Returns TRUE if the media source supports this config, FALSE otherwise
1303 **
1304 *******************************************************************************/
bta_av_co_audio_media_supports_config(UINT8 codec_type,const UINT8 * p_codec_cfg)1305 static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg)
1306 {
1307 FUNC_TRACE();
1308
1309 switch (codec_type) {
1310 case BTA_AV_CODEC_SBC:
1311 if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps)) {
1312 return FALSE;
1313 }
1314 break;
1315
1316
1317 default:
1318 APPL_TRACE_ERROR("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type);
1319 return FALSE;
1320 break;
1321 }
1322 return TRUE;
1323 }
1324
1325 /*******************************************************************************
1326 **
1327 ** Function bta_av_co_audio_codec_supported
1328 **
1329 ** Description Check if all opened connections are compatible with a codec
1330 ** configuration and content protection
1331 **
1332 ** Returns TRUE if all opened devices support this codec, FALSE otherwise
1333 **
1334 *******************************************************************************/
bta_av_co_audio_codec_supported(tBTC_AV_STATUS * p_status)1335 BOOLEAN bta_av_co_audio_codec_supported(tBTC_AV_STATUS *p_status)
1336 {
1337 UINT8 index;
1338 UINT8 snk_index;
1339 tBTA_AV_CO_PEER *p_peer;
1340 tBTA_AV_CO_SINK *p_sink;
1341 UINT8 codec_cfg[AVDT_CODEC_SIZE];
1342 UINT8 num_protect = 0;
1343 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1344 BOOLEAN cp_active;
1345 #endif
1346
1347 FUNC_TRACE();
1348
1349 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported");
1350
1351 /* Check AV feeding is supported */
1352 *p_status = BTC_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
1353
1354 for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++) {
1355 p_peer = &bta_av_co_cb.peers[index];
1356 if (p_peer->opened) {
1357 if (bta_av_co_audio_peer_supports_codec(p_peer, &snk_index)) {
1358 p_sink = &p_peer->snks[snk_index];
1359
1360 /* Check that this sink is compatible with the CP */
1361 if (!bta_av_co_audio_sink_supports_cp(p_sink)) {
1362 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported sink %d of peer %d doesn't support cp",
1363 snk_index, index);
1364 *p_status = BTC_ERROR_SRV_AV_CP_NOT_SUPPORTED;
1365 return FALSE;
1366 }
1367
1368 /* Build the codec configuration for this sink */
1369 if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg)) {
1370 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1371 /* Check if this sink supports SCMS */
1372 cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
1373 #endif
1374 /* Check if this is a new configuration (new sink or new config) */
1375 if ((p_sink != p_peer->p_snk) ||
1376 (memcmp(codec_cfg, p_peer->codec_cfg, AVDT_CODEC_SIZE))
1377 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1378 || (p_peer->cp_active != cp_active)
1379 #endif
1380 ) {
1381 /* Save the new configuration */
1382 p_peer->p_snk = p_sink;
1383 memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
1384 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1385 p_peer->cp_active = cp_active;
1386 if (p_peer->cp_active) {
1387 bta_av_co_cb.cp.active = TRUE;
1388 num_protect = BTA_AV_CP_INFO_LEN;
1389 } else {
1390 bta_av_co_cb.cp.active = FALSE;
1391 }
1392 #endif
1393 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported call BTA_AvReconfig(x%x)", BTA_AV_CO_AUDIO_INDX_TO_HNDL(index));
1394 BTA_AvReconfig(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index), TRUE, p_sink->sep_info_idx,
1395 p_peer->codec_cfg, num_protect, (UINT8 *)bta_av_co_cp_scmst);
1396 }
1397 }
1398 } else {
1399 APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported index %d doesn't support codec", index);
1400 return FALSE;
1401 }
1402 }
1403 }
1404
1405 *p_status = BTC_AV_SUCCESS;
1406 return TRUE;
1407 }
1408
1409 /*******************************************************************************
1410 **
1411 ** Function bta_av_co_audio_codec_reset
1412 **
1413 ** Description Reset the current codec configuration
1414 **
1415 ** Returns void
1416 **
1417 *******************************************************************************/
bta_av_co_audio_codec_reset(void)1418 void bta_av_co_audio_codec_reset(void)
1419 {
1420 osi_mutex_global_lock();
1421 FUNC_TRACE();
1422
1423 /* Reset the current configuration to SBC */
1424 bta_av_co_cb.codec_cfg.id = BTC_AV_CODEC_SBC;
1425
1426 if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btc_av_sbc_default_config, bta_av_co_cb.codec_cfg.info) != A2D_SUCCESS) {
1427 APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed");
1428 }
1429
1430 osi_mutex_global_unlock();
1431 }
1432
1433 /*******************************************************************************
1434 **
1435 ** Function bta_av_co_audio_set_codec
1436 **
1437 ** Description Set the current codec configuration from the feeding type.
1438 ** This function is starting to modify the configuration, it
1439 ** should be protected.
1440 **
1441 ** Returns TRUE if successful, FALSE otherwise
1442 **
1443 *******************************************************************************/
bta_av_co_audio_set_codec(const tBTC_AV_MEDIA_FEEDINGS * p_feeding,tBTC_AV_STATUS * p_status)1444 BOOLEAN bta_av_co_audio_set_codec(const tBTC_AV_MEDIA_FEEDINGS *p_feeding, tBTC_AV_STATUS *p_status)
1445 {
1446 tA2D_SBC_CIE sbc_config;
1447 tBTC_AV_CODEC_INFO new_cfg;
1448
1449 FUNC_TRACE();
1450
1451 /* Check AV feeding is supported */
1452 *p_status = BTC_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
1453
1454 APPL_TRACE_DEBUG("bta_av_co_audio_set_codec cid=%d", p_feeding->format);
1455
1456 /* Supported codecs */
1457 switch (p_feeding->format) {
1458 case BTC_AV_CODEC_PCM:
1459 new_cfg.id = BTC_AV_CODEC_SBC;
1460
1461 sbc_config = btc_av_sbc_default_config;
1462 if ((p_feeding->cfg.pcm.num_channel != 1) &&
1463 (p_feeding->cfg.pcm.num_channel != 2)) {
1464 APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM channel number unsupported");
1465 return FALSE;
1466 }
1467 if ((p_feeding->cfg.pcm.bit_per_sample != 8) &&
1468 (p_feeding->cfg.pcm.bit_per_sample != 16)) {
1469 APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM sample size unsupported");
1470 return FALSE;
1471 }
1472 switch (p_feeding->cfg.pcm.sampling_freq) {
1473 case 8000:
1474 case 12000:
1475 case 16000:
1476 case 24000:
1477 case 32000:
1478 case 48000:
1479 sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
1480 break;
1481
1482 case 11025:
1483 case 22050:
1484 case 44100:
1485 sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
1486 break;
1487 default:
1488 APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM sampling frequency unsupported");
1489 return FALSE;
1490 break;
1491 }
1492 /* Build the codec config */
1493 if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &sbc_config, new_cfg.info) != A2D_SUCCESS) {
1494 APPL_TRACE_ERROR("bta_av_co_audio_set_codec A2D_BldSbcInfo failed");
1495 return FALSE;
1496 }
1497 break;
1498
1499
1500 default:
1501 APPL_TRACE_ERROR("bta_av_co_audio_set_codec Feeding format unsupported");
1502 return FALSE;
1503 break;
1504 }
1505
1506 /* The new config was correctly built */
1507 bta_av_co_cb.codec_cfg = new_cfg;
1508
1509
1510 /* Check all devices support it */
1511 *p_status = BTC_AV_SUCCESS;
1512 return bta_av_co_audio_codec_supported(p_status);
1513 }
1514
1515 /*******************************************************************************
1516 **
1517 ** Function bta_av_co_audio_get_sbc_config
1518 **
1519 ** Description Retrieves the SBC codec configuration. If the codec in use
1520 ** is not SBC, return the default SBC codec configuration.
1521 **
1522 ** Returns TRUE if codec is SBC, FALSE otherwise
1523 **
1524 *******************************************************************************/
bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE * p_sbc_config,UINT16 * p_minmtu)1525 BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_minmtu)
1526 {
1527 BOOLEAN result = FALSE;
1528 UINT8 index, jndex;
1529 tBTA_AV_CO_PEER *p_peer;
1530 tBTA_AV_CO_SINK *p_sink;
1531
1532 APPL_TRACE_EVENT("bta_av_co_cb.codec_cfg.id : codec 0x%x", bta_av_co_cb.codec_cfg.id);
1533
1534 /* Minimum MTU is by default very large */
1535 *p_minmtu = 0xFFFF;
1536
1537 osi_mutex_global_lock();
1538 if (bta_av_co_cb.codec_cfg.id == BTC_AV_CODEC_SBC) {
1539 if (A2D_ParsSbcInfo(p_sbc_config, bta_av_co_cb.codec_cfg.info, FALSE) == A2D_SUCCESS) {
1540 for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++) {
1541 p_peer = &bta_av_co_cb.peers[index];
1542 if (p_peer->opened) {
1543 if (p_peer->mtu < *p_minmtu) {
1544 *p_minmtu = p_peer->mtu;
1545 }
1546 for (jndex = 0; jndex < p_peer->num_sup_snks; jndex++) {
1547 p_sink = &p_peer->snks[jndex];
1548 if (p_sink->codec_type == A2D_MEDIA_CT_SBC) {
1549 /* Update the bitpool boundaries of the current config */
1550 p_sbc_config->min_bitpool =
1551 BTA_AV_CO_MAX(p_sink->codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
1552 p_sbc_config->min_bitpool);
1553 p_sbc_config->max_bitpool =
1554 BTA_AV_CO_MIN(p_sink->codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
1555 p_sbc_config->max_bitpool);
1556 APPL_TRACE_EVENT("bta_av_co_audio_get_sbc_config : sink bitpool min %d, max %d",
1557 p_sbc_config->min_bitpool, p_sbc_config->max_bitpool);
1558 break;
1559 }
1560 }
1561 }
1562 }
1563 result = TRUE;
1564 }
1565 }
1566
1567 if (!result) {
1568 /* Not SBC, still return the default values */
1569 *p_sbc_config = btc_av_sbc_default_config;
1570 }
1571 osi_mutex_global_unlock();
1572
1573 return result;
1574 }
1575
1576 /*******************************************************************************
1577 **
1578 ** Function bta_av_co_audio_discard_config
1579 **
1580 ** Description Discard the codec configuration of a connection
1581 **
1582 ** Returns Nothing
1583 **
1584 *******************************************************************************/
bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl)1585 void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl)
1586 {
1587 tBTA_AV_CO_PEER *p_peer;
1588
1589 FUNC_TRACE();
1590
1591 /* Find the peer info */
1592 p_peer = bta_av_co_get_peer(hndl);
1593 if (p_peer == NULL) {
1594 APPL_TRACE_ERROR("bta_av_co_audio_discard_config could not find peer entry");
1595 return;
1596 }
1597
1598 /* Reset the peer codec configuration */
1599 bta_av_co_audio_peer_reset_config(p_peer);
1600 }
1601
1602 /*******************************************************************************
1603 **
1604 ** Function bta_av_co_init
1605 **
1606 ** Description Initialization
1607 **
1608 ** Returns Nothing
1609 **
1610 *******************************************************************************/
bta_av_co_init(void)1611 void bta_av_co_init(void)
1612 {
1613 FUNC_TRACE();
1614
1615 /* Reset the control block */
1616 memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));
1617
1618 bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_NONE;
1619
1620 #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
1621 bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER);
1622 #else
1623 bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_FREE);
1624 #endif
1625
1626 /* Reset the current config */
1627 bta_av_co_audio_codec_reset();
1628 }
1629
1630
1631 /*******************************************************************************
1632 **
1633 ** Function bta_av_co_peer_cp_supported
1634 **
1635 ** Description Checks if the peer supports CP
1636 **
1637 ** Returns TRUE if the peer supports CP
1638 **
1639 *******************************************************************************/
bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl)1640 BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl)
1641 {
1642 tBTA_AV_CO_PEER *p_peer;
1643 tBTA_AV_CO_SINK *p_sink;
1644 UINT8 index;
1645
1646 FUNC_TRACE();
1647
1648 /* Find the peer info */
1649 p_peer = bta_av_co_get_peer(hndl);
1650 if (p_peer == NULL) {
1651 APPL_TRACE_ERROR("bta_av_co_peer_cp_supported could not find peer entry");
1652 return FALSE;
1653 }
1654
1655 for (index = 0; index < p_peer->num_sup_snks; index++) {
1656 p_sink = &p_peer->snks[index];
1657 if (p_sink->codec_type == A2D_MEDIA_CT_SBC) {
1658 return bta_av_co_audio_sink_has_scmst(p_sink);
1659 }
1660 }
1661 APPL_TRACE_ERROR("bta_av_co_peer_cp_supported did not find SBC sink");
1662 return FALSE;
1663 }
1664
1665
1666 /*******************************************************************************
1667 **
1668 ** Function bta_av_co_get_remote_bitpool_pref
1669 **
1670 ** Description Check if remote side did a setconfig within the limits
1671 ** of our exported bitpool range. If set we will set the
1672 ** remote preference.
1673 **
1674 ** Returns TRUE if config set, FALSE otherwize
1675 **
1676 *******************************************************************************/
1677
bta_av_co_get_remote_bitpool_pref(UINT8 * min,UINT8 * max)1678 BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max)
1679 {
1680 /* check if remote peer did a set config */
1681 if (bta_av_co_cb.codec_cfg_setconfig.id == BTC_AV_CODEC_NONE) {
1682 return FALSE;
1683 }
1684
1685 *min = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
1686 *max = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
1687
1688 return TRUE;
1689 }
1690
1691 /* the call out functions for audio stream */
1692 const tBTA_AV_CO_FUNCTS bta_av_a2d_cos = {
1693 bta_av_co_audio_init,
1694 bta_av_co_audio_disc_res,
1695 bta_av_co_audio_getconfig,
1696 bta_av_co_audio_setconfig,
1697 bta_av_co_audio_open,
1698 bta_av_co_audio_close,
1699 bta_av_co_audio_start,
1700 bta_av_co_audio_stop,
1701 bta_av_co_audio_src_data_path,
1702 bta_av_co_audio_delay
1703 };
1704
1705 #endif /* #if BTC_AV_INCLUDED */
1706