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