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