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