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