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