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 file contains functions for managing the SCO connection used in AG.
22 *
23 ******************************************************************************/
24
25#include <stddef.h>
26#include "bta_api.h"
27#include "bta_ag_api.h"
28#include "bta_ag_co.h"
29#if (BTM_SCO_HCI_INCLUDED == TRUE )
30#include "bta_dm_co.h"
31#endif
32#include "bta_ag_int.h"
33#include "btm_api.h"
34#include "gki.h"
35#include "utl.h"
36
37#ifndef BTA_AG_SCO_DEBUG
38#define BTA_AG_SCO_DEBUG FALSE
39#endif
40
41#ifndef BTA_AG_CODEC_NEGO_TIMEOUT
42#define BTA_AG_CODEC_NEGO_TIMEOUT   3000
43#endif
44
45#if BTA_AG_SCO_DEBUG == TRUE
46static char *bta_ag_sco_evt_str(UINT8 event);
47static char *bta_ag_sco_state_str(UINT8 state);
48#endif
49
50#define BTA_AG_NO_EDR_ESCO  (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
51                             BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
52                             BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
53                             BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
54
55/* sco events */
56enum
57{
58    BTA_AG_SCO_LISTEN_E,        /* listen request */
59    BTA_AG_SCO_OPEN_E,          /* open request */
60    BTA_AG_SCO_XFER_E,          /* transfer request */
61#if (BTM_WBS_INCLUDED == TRUE )
62    BTA_AG_SCO_CN_DONE_E,       /* codec negotiation done */
63    BTA_AG_SCO_REOPEN_E,        /* Retry with other codec when failed */
64#endif
65    BTA_AG_SCO_CLOSE_E,         /* close request */
66    BTA_AG_SCO_SHUTDOWN_E,      /* shutdown request */
67    BTA_AG_SCO_CONN_OPEN_E,     /* sco open */
68    BTA_AG_SCO_CONN_CLOSE_E,    /* sco closed */
69    BTA_AG_SCO_CI_DATA_E        /* SCO data ready */
70};
71
72#if (BTM_WBS_INCLUDED == TRUE )
73#define BTA_AG_NUM_CODECS   3
74#define BTA_AG_ESCO_SETTING_IDX_CVSD    0   /* eSCO setting for CVSD */
75#define BTA_AG_ESCO_SETTING_IDX_T1      1   /* eSCO setting for mSBC T1 */
76#define BTA_AG_ESCO_SETTING_IDX_T2      2   /* eSCO setting for mSBC T2 */
77
78static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
79{
80    /* CVSD */
81    {
82        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
83        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
84        0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
85        BTM_VOICE_SETTING_CVSD,             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
86       (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
87        BTM_SCO_PKT_TYPES_MASK_HV2      +
88        BTM_SCO_PKT_TYPES_MASK_HV3      +
89        BTM_SCO_PKT_TYPES_MASK_EV3      +
90        BTM_SCO_PKT_TYPES_MASK_EV4      +
91        BTM_SCO_PKT_TYPES_MASK_EV5      +
92        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
93        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
94        BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
95    },
96    /* mSBC  T1 */
97    {
98        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec), 8000        */
99        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec), 8000        */
100        8,                                  /* 8 ms                                     */
101        BTM_VOICE_SETTING_TRANS,            /* Inp Linear, Transparent, 2s Comp, 16bit  */
102       (BTM_SCO_PKT_TYPES_MASK_EV3      |   /* Packet Types : EV3 + NO_2_EV3            */
103        BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
104        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
105        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 |
106        BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 ),
107        BTM_ESCO_RETRANS_QUALITY       /* Retransmission effort                      */
108    },
109    /* mSBC T2*/
110    {
111        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec), 8000        */
112        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec), 8000        */
113        13,                                 /* 13 ms                                    */
114        BTM_VOICE_SETTING_TRANS,            /* Inp Linear, Transparent, 2s Comp, 16bit  */
115       (BTM_SCO_PKT_TYPES_MASK_EV3      |   /* Packet Types : EV3 + 2-EV3               */
116        BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
117        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
118        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
119        BTM_ESCO_RETRANS_QUALITY       /* Retransmission effort                      */
120    }
121};
122#else
123/* WBS not included, CVSD by default */
124static const tBTM_ESCO_PARAMS bta_ag_esco_params =
125{
126    BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
127    BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
128    0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
129    0x0060,                             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
130    (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
131     BTM_SCO_PKT_TYPES_MASK_HV2      +
132     BTM_SCO_PKT_TYPES_MASK_HV3      +
133     BTM_SCO_PKT_TYPES_MASK_EV3      +
134     BTM_SCO_PKT_TYPES_MASK_EV4      +
135     BTM_SCO_PKT_TYPES_MASK_EV5      +
136     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
137     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
138     BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
139};
140#endif
141
142/*******************************************************************************
143**
144** Function         bta_ag_sco_conn_cback
145**
146** Description      BTM SCO connection callback.
147**
148**
149** Returns          void
150**
151*******************************************************************************/
152static void bta_ag_sco_conn_cback(UINT16 sco_idx)
153{
154    UINT16  handle;
155    BT_HDR  *p_buf;
156    tBTA_AG_SCB *p_scb;
157
158    /* match callback to scb; first check current sco scb */
159    if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
160    {
161        handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
162    }
163    /* then check for scb connected to this peer */
164    else
165    {
166        /* Check if SLC is up */
167        handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx));
168        p_scb = bta_ag_scb_by_idx(handle);
169        if(p_scb && !p_scb->svc_conn)
170            handle = 0;
171    }
172
173    if (handle != 0)
174    {
175        if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
176        {
177            p_buf->event = BTA_AG_SCO_OPEN_EVT;
178            p_buf->layer_specific = handle;
179            bta_sys_sendmsg(p_buf);
180        }
181    }
182    /* no match found; disconnect sco, init sco variables */
183    else
184    {
185        bta_ag_cb.sco.p_curr_scb = NULL;
186        bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
187        BTM_RemoveSco(sco_idx);
188    }
189}
190
191/*******************************************************************************
192**
193** Function         bta_ag_sco_disc_cback
194**
195** Description      BTM SCO disconnection callback.
196**
197**
198** Returns          void
199**
200*******************************************************************************/
201static void bta_ag_sco_disc_cback(UINT16 sco_idx)
202{
203    BT_HDR  *p_buf;
204    UINT16  handle = 0;
205
206    APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): sco_idx: 0x%x  p_cur_scb: 0x%08x  sco.state: %d", sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
207
208    APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x  in_use: %u  sco_idx: 0x%x  sco state: %u",
209                       &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx, bta_ag_cb.scb[0].state);
210    APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): scb[1] addr: 0x%08x  in_use: %u  sco_idx: 0x%x  sco state: %u",
211                       &bta_ag_cb.scb[1], bta_ag_cb.scb[1].in_use, bta_ag_cb.scb[1].sco_idx, bta_ag_cb.scb[1].state);
212
213    /* match callback to scb */
214    if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
215    {
216        /* We only care about callbacks for the active SCO */
217        if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx)
218        {
219            if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF)
220                return;
221        }
222        handle  = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
223    }
224
225    if (handle != 0)
226    {
227#if (BTM_SCO_HCI_INCLUDED == TRUE )
228        tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE);
229        APPL_TRACE_DEBUG("bta_ag_sco_disc_cback sco close config status = %d", status);
230        /* SCO clean up here */
231        bta_dm_sco_co_close();
232#endif
233
234#if (BTM_WBS_INCLUDED == TRUE )
235        /* Restore settings */
236        if(bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC)
237        {
238            /* set_sco_codec(BTM_SCO_CODEC_NONE); we should get a close */
239            BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
240
241            /* If SCO open was initiated by AG and failed for mSBC, then attempt
242            mSBC with T1 settings i.e. 'Safe Settings'. If this fails, then switch to CVSD */
243            if (bta_ag_sco_is_opening (bta_ag_cb.sco.p_curr_scb))
244            {
245                if (bta_ag_cb.sco.p_curr_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2)
246                {
247                     APPL_TRACE_DEBUG("Fallback to mSBC T1 settings");
248                     bta_ag_cb.sco.p_curr_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T1;
249                }
250                else
251                {
252                    APPL_TRACE_DEBUG("Fallback to CVSD settings");
253                    bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE;
254                }
255            }
256        }
257
258        bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
259#endif
260
261        if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
262        {
263            p_buf->event = BTA_AG_SCO_CLOSE_EVT;
264            p_buf->layer_specific = handle;
265            bta_sys_sendmsg(p_buf);
266        }
267    }
268    /* no match found */
269    else
270    {
271        APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback");
272
273        /* sco could be closed after scb dealloc'ed */
274        if (bta_ag_cb.sco.p_curr_scb != NULL)
275        {
276            bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
277            bta_ag_cb.sco.p_curr_scb = NULL;
278            bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
279        }
280    }
281}
282#if (BTM_SCO_HCI_INCLUDED == TRUE )
283/*******************************************************************************
284**
285** Function         bta_ag_sco_read_cback
286**
287** Description      Callback function is the callback function for incoming
288**                  SCO data over HCI.
289**
290** Returns          void
291**
292*******************************************************************************/
293static void bta_ag_sco_read_cback (UINT16 sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status)
294{
295    if (status != BTM_SCO_DATA_CORRECT)
296    {
297        APPL_TRACE_DEBUG("bta_ag_sco_read_cback: status(%d)", status);
298    }
299
300    /* Callout function must free the data. */
301    bta_dm_sco_co_in_data (p_data, status);
302}
303#endif
304/*******************************************************************************
305**
306** Function         bta_ag_remove_sco
307**
308** Description      Removes the specified SCO from the system.
309**                  If only_active is TRUE, then SCO is only removed if connected
310**
311** Returns          BOOLEAN   - TRUE if Sco removal was started
312**
313*******************************************************************************/
314static BOOLEAN bta_ag_remove_sco(tBTA_AG_SCB *p_scb, BOOLEAN only_active)
315{
316    BOOLEAN     removed_started = FALSE;
317    tBTM_STATUS	status;
318
319    if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
320    {
321        if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx)
322        {
323            status = BTM_RemoveSco(p_scb->sco_idx);
324
325            APPL_TRACE_DEBUG("ag remove sco: inx 0x%04x, status:0x%x", p_scb->sco_idx, status);
326
327            if (status == BTM_CMD_STARTED)
328            {
329                /* Sco is connected; set current control block */
330                bta_ag_cb.sco.p_curr_scb = p_scb;
331
332                removed_started = TRUE;
333            }
334            /* If no connection reset the sco handle */
335            else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
336            {
337                p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
338            }
339        }
340    }
341    return removed_started;
342}
343
344
345/*******************************************************************************
346**
347** Function         bta_ag_esco_connreq_cback
348**
349** Description      BTM eSCO connection requests and eSCO change requests
350**                  Only the connection requests are processed by BTA.
351**
352** Returns          void
353**
354*******************************************************************************/
355static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
356{
357    tBTA_AG_SCB         *p_scb;
358    UINT16               handle;
359    UINT16               sco_inx = p_data->conn_evt.sco_inx;
360
361    /* Only process connection requests */
362    if (event == BTM_ESCO_CONN_REQ_EVT)
363    {
364        if ((handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_inx))) != 0 &&
365            ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) && p_scb->svc_conn)
366        {
367            p_scb->sco_idx = sco_inx;
368
369            /* If no other SCO active, allow this one */
370            if (!bta_ag_cb.sco.p_curr_scb)
371            {
372                APPL_TRACE_EVENT("bta_ag_esco_connreq_cback: Accept Conn Request (sco_inx 0x%04x)", sco_inx);
373                bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
374
375                bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST;
376                bta_ag_cb.sco.p_curr_scb = p_scb;
377                bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
378            }
379            else    /* Begin a transfer: Close current SCO before responding */
380            {
381                APPL_TRACE_DEBUG("bta_ag_esco_connreq_cback: Begin XFER");
382                bta_ag_cb.sco.p_xfer_scb = p_scb;
383                bta_ag_cb.sco.conn_data = p_data->conn_evt;
384                bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST;
385
386                if (!bta_ag_remove_sco(bta_ag_cb.sco.p_curr_scb, TRUE))
387                {
388                    APPL_TRACE_ERROR("bta_ag_esco_connreq_cback: Nothing to remove so accept Conn Request (sco_inx 0x%04x)", sco_inx);
389                    bta_ag_cb.sco.p_xfer_scb = NULL;
390                    bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST;
391
392                    bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
393                }
394            }
395        }
396        /* If error occurred send reject response immediately */
397        else
398        {
399            APPL_TRACE_WARNING("no scb for bta_ag_esco_connreq_cback or no resources");
400            BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL);
401        }
402    }
403    /* Received a change in the esco link */
404    else if (event == BTM_ESCO_CHG_EVT)
405    {
406        APPL_TRACE_EVENT("eSCO change event (inx %d): rtrans %d, rxlen %d, txlen %d, txint %d",
407            p_data->chg_evt.sco_inx,
408            p_data->chg_evt.retrans_window, p_data->chg_evt.rx_pkt_len,
409            p_data->chg_evt.tx_pkt_len, p_data->chg_evt.tx_interval);
410    }
411}
412
413/*******************************************************************************
414**
415** Function         bta_ag_cback_sco
416**
417** Description      Call application callback function with SCO event.
418**
419**
420** Returns          void
421**
422*******************************************************************************/
423static void bta_ag_cback_sco(tBTA_AG_SCB *p_scb, UINT8 event)
424{
425    tBTA_AG_HDR    sco;
426
427    sco.handle = bta_ag_scb_to_idx(p_scb);
428    sco.app_id = p_scb->app_id;
429
430    /* call close cback */
431    (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &sco);
432}
433
434/*******************************************************************************
435**
436** Function         bta_ag_create_sco
437**
438** Description
439**
440**
441** Returns          void
442**
443*******************************************************************************/
444static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
445{
446    tBTM_STATUS       status;
447    UINT8            *p_bd_addr = NULL;
448    tBTM_ESCO_PARAMS params;
449#if (BTM_WBS_INCLUDED == TRUE )
450    tBTA_AG_PEER_CODEC  esco_codec = BTM_SCO_CODEC_CVSD;
451    int codec_index = 0;
452#endif
453#if (BTM_SCO_HCI_INCLUDED == TRUE )
454    tBTM_SCO_ROUTE_TYPE sco_route;
455    tBTA_CODEC_INFO     codec_info = {BTA_SCO_CODEC_PCM};
456    UINT32              pcm_sample_rate;
457#endif
458
459    /* Make sure this sco handle is not already in use */
460    if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
461    {
462        APPL_TRACE_WARNING("bta_ag_create_sco: Index 0x%04x Already In Use!",
463                             p_scb->sco_idx);
464        return;
465    }
466
467#if (BTM_WBS_INCLUDED == TRUE )
468    if ((p_scb->sco_codec == BTM_SCO_CODEC_MSBC) &&
469        !p_scb->codec_fallback &&
470        !p_scb->retry_with_sco_only)
471        esco_codec = BTM_SCO_CODEC_MSBC;
472
473    if (p_scb->codec_fallback)
474    {
475        p_scb->codec_fallback = FALSE;
476
477        /* Force AG to send +BCS for the next audio connection. */
478        p_scb->codec_updated = TRUE;
479    }
480
481    /* If WBS included, use CVSD by default, index is 0 for CVSD by initialization */
482    /* If eSCO codec is mSBC, index is T2 or T1 */
483    if (esco_codec == BTM_SCO_CODEC_MSBC)
484    {
485        if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2)
486        {
487            codec_index = BTA_AG_ESCO_SETTING_IDX_T2;
488        }
489        else
490        {
491            codec_index = BTA_AG_ESCO_SETTING_IDX_T1;
492        }
493    }
494
495    params = bta_ag_esco_params[codec_index];
496#else
497    /* When WBS is not included, use CVSD by default */
498    params = bta_ag_esco_params;
499#endif
500
501    if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */
502        params = bta_ag_cb.sco.params;
503
504    if(!bta_ag_cb.sco.param_updated)
505    {
506#if (BTM_WBS_INCLUDED == TRUE)
507        if (esco_codec == BTM_SCO_CODEC_CVSD)   /* For CVSD */
508#endif
509        {
510            /* Use the application packet types (5 slot EV packets not allowed) */
511            params.packet_types = p_bta_ag_cfg->sco_pkt_types     |
512                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
513                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
514        }
515    }
516
517    /* if initiating set current scb and peer bd addr */
518    if (is_orig)
519    {
520        /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
521        /* Need to find out from SIG if HSP can use eSCO; for now use SCO */
522        if (p_scb->conn_service == BTA_AG_HFP && p_scb->peer_version >= HFP_VERSION_1_5 && !p_scb->retry_with_sco_only)
523        {
524
525            BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
526            /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
527            if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
528               ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_AG_NO_EDR_ESCO))
529            {
530#if (BTM_WBS_INCLUDED == TRUE )
531                if (esco_codec != BTA_AG_CODEC_MSBC)
532                {
533                    p_scb->retry_with_sco_only = TRUE;
534                    APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
535                }
536                else    /* Do not use SCO when using mSBC */
537                {
538                    p_scb->retry_with_sco_only = FALSE;
539                    APPL_TRACE_API("Setting retry_with_sco_only to FALSE");
540                }
541#else
542                p_scb->retry_with_sco_only = TRUE;
543                APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
544#endif
545            }
546        }
547        else
548        {
549            if(p_scb->retry_with_sco_only)
550                APPL_TRACE_API("retrying with SCO only");
551            p_scb->retry_with_sco_only = FALSE;
552
553            BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
554        }
555
556        bta_ag_cb.sco.p_curr_scb = p_scb;
557
558        /* tell sys to stop av if any */
559        bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
560
561#if (BTM_WBS_INCLUDED == TRUE )
562        /* Allow any platform specific pre-SCO set up to take place */
563        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP,
564                esco_codec);
565
566        /* This setting may not be necessary */
567        /* To be verified with stable 2049 boards */
568        if (esco_codec == BTA_AG_CODEC_MSBC)
569            BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS);
570        else
571            BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
572        /* save the current codec because sco_codec can be updated while SCO is open. */
573        p_scb->inuse_codec = esco_codec;
574#else
575        /* Allow any platform specific pre-SCO set up to take place */
576        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP);
577#endif
578
579#if (BTM_SCO_HCI_INCLUDED == TRUE )
580#if (BTM_WBS_INCLUDED == TRUE)
581        if (esco_codec == BTA_AG_CODEC_MSBC)
582            pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_16K;
583        else
584#endif
585            pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
586
587        sco_route = bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id);
588#endif
589
590
591#if (BTM_SCO_HCI_INCLUDED == TRUE )
592        /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
593        BTM_ConfigScoPath(sco_route, bta_ag_sco_read_cback, NULL, TRUE);
594#endif
595        bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
596    }
597    else
598        p_scb->retry_with_sco_only = FALSE;
599
600    p_bd_addr = p_scb->peer_addr;
601
602    status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
603                           &p_scb->sco_idx, bta_ag_sco_conn_cback,
604                           bta_ag_sco_disc_cback);
605    if (status == BTM_CMD_STARTED)
606    {
607        if (!is_orig)
608        {
609            BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
610        }
611        else    /* Initiating the connection, set the current sco handle */
612        {
613            bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
614        }
615    }
616
617    APPL_TRACE_API("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
618                      is_orig, p_scb->sco_idx, status, params.packet_types);
619}
620
621#if (BTM_WBS_INCLUDED == TRUE )
622/*******************************************************************************
623**
624** Function         bta_ag_attempt_msbc_safe_settings
625**
626** Description    Checks if ESCO connection needs to be attempted using mSBC T1(safe) settings
627**
628**
629** Returns          TRUE if T1 settings has to be used, FALSE otherwise
630**
631*******************************************************************************/
632BOOLEAN bta_ag_attempt_msbc_safe_settings(tBTA_AG_SCB *p_scb)
633{
634    if (p_scb->svc_conn && p_scb->sco_codec == BTM_SCO_CODEC_MSBC &&
635        p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1)
636        return TRUE;
637    else
638        return FALSE;
639}
640
641/*******************************************************************************
642**
643** Function         bta_ag_cn_timer_cback
644**
645** Description
646**
647**
648** Returns          void
649**
650*******************************************************************************/
651static void bta_ag_cn_timer_cback (TIMER_LIST_ENT *p_tle)
652{
653    tBTA_AG_SCB *p_scb;
654
655    if (p_tle)
656    {
657        p_scb = (tBTA_AG_SCB *)p_tle->param;
658
659        if (p_scb)
660        {
661            /* Announce that codec negotiation failed. */
662            bta_ag_sco_codec_nego(p_scb, FALSE);
663
664            /* call app callback */
665            bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
666        }
667    }
668}
669
670/*******************************************************************************
671**
672** Function         bta_ag_codec_negotiate
673**
674** Description      Initiate codec negotiation by sending AT command.
675**                  If not necessary, skip negotiation.
676**
677** Returns          void
678**
679*******************************************************************************/
680void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb)
681{
682    bta_ag_cb.sco.p_curr_scb = p_scb;
683
684    if ((p_scb->codec_updated || p_scb->codec_fallback ||
685        bta_ag_attempt_msbc_safe_settings(p_scb)) &&
686       (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC))
687    {
688        /* Change the power mode to Active until sco open is completed. */
689        bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
690
691        /* Send +BCS to the peer */
692        bta_ag_send_bcs(p_scb, NULL);
693
694        /* Start timer to handle timeout */
695        p_scb->cn_timer.p_cback = (TIMER_CBACK*)&bta_ag_cn_timer_cback;
696        p_scb->cn_timer.param = (INT32)p_scb;
697        bta_sys_start_timer(&p_scb->cn_timer, 0, BTA_AG_CODEC_NEGO_TIMEOUT);
698    }
699    else
700    {
701        /* use same codec type as previous SCO connection, skip codec negotiation */
702        APPL_TRACE_DEBUG("use same codec type as previous SCO connection,skip codec negotiation");
703        bta_ag_sco_codec_nego(p_scb, TRUE);
704    }
705}
706#endif /* (BTM_WBS_INCLUDED == TRUE ) */
707
708/*******************************************************************************
709**
710** Function         bta_ag_sco_event
711**
712** Description
713**
714**
715** Returns          void
716**
717*******************************************************************************/
718static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event)
719{
720    tBTA_AG_SCO_CB *p_sco = &bta_ag_cb.sco;
721#if (BTM_WBS_INCLUDED == TRUE )
722    tBTA_AG_SCB *p_cn_scb = NULL;   /* For codec negotiation */
723#endif
724#if (BTM_SCO_HCI_INCLUDED == TRUE )
725    BT_HDR  *p_buf;
726#endif
727#if BTA_AG_SCO_DEBUG == TRUE
728    UINT8   in_state = p_sco->state;
729
730    APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)",
731                        p_scb->sco_idx,
732                        p_sco->state, bta_ag_sco_state_str(p_sco->state),
733                        event, bta_ag_sco_evt_str(event));
734#else
735    APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d, Event %d",
736                      p_scb->sco_idx, p_sco->state, event);
737#endif
738
739#if (BTM_SCO_HCI_INCLUDED == TRUE )
740    if (event == BTA_AG_SCO_CI_DATA_E)
741    {
742        while (TRUE)
743        {
744            bta_dm_sco_co_out_data(&p_buf);
745            if (p_buf)
746            {
747                if (p_sco->state == BTA_AG_SCO_OPEN_ST)
748                    BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf);
749                else
750                    GKI_freebuf(p_buf);
751            }
752            else
753                break;
754        }
755
756        return;
757    }
758#endif
759
760    switch (p_sco->state)
761    {
762        case BTA_AG_SCO_SHUTDOWN_ST:
763            switch (event)
764            {
765                case BTA_AG_SCO_LISTEN_E:
766                    /* create sco listen connection */
767                    bta_ag_create_sco(p_scb, FALSE);
768                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
769                    break;
770
771                default:
772                    APPL_TRACE_WARNING("BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d", event);
773                    break;
774            }
775            break;
776
777        case BTA_AG_SCO_LISTEN_ST:
778            switch (event)
779            {
780                case BTA_AG_SCO_LISTEN_E:
781                    /* create sco listen connection (Additional channel) */
782                    bta_ag_create_sco(p_scb, FALSE);
783                    break;
784
785                case BTA_AG_SCO_OPEN_E:
786                    /* remove listening connection */
787                    bta_ag_remove_sco(p_scb, FALSE);
788
789#if (BTM_WBS_INCLUDED == TRUE )
790                    /* start codec negotiation */
791                    p_sco->state = BTA_AG_SCO_CODEC_ST;
792                    p_cn_scb = p_scb;
793#else
794                    /* create sco connection to peer */
795                    bta_ag_create_sco(p_scb, TRUE);
796                    p_sco->state = BTA_AG_SCO_OPENING_ST;
797#endif
798                    break;
799
800                case BTA_AG_SCO_SHUTDOWN_E:
801                    /* remove listening connection */
802                    bta_ag_remove_sco(p_scb, FALSE);
803
804                    if (p_scb == p_sco->p_curr_scb)
805                        p_sco->p_curr_scb = NULL;
806
807                    /* If last SCO instance then finish shutting down */
808                    if (!bta_ag_other_scb_open(p_scb))
809                    {
810                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
811                    }
812                    break;
813
814                case BTA_AG_SCO_CLOSE_E:
815                    /* remove listening connection */
816                    /* Ignore the event. We need to keep listening SCO for the active SLC */
817                    APPL_TRACE_WARNING("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
818                    break;
819
820                case BTA_AG_SCO_CONN_CLOSE_E:
821                    /* sco failed; create sco listen connection */
822                    bta_ag_create_sco(p_scb, FALSE);
823                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
824                    break;
825
826                default:
827                    APPL_TRACE_WARNING("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
828                    break;
829            }
830            break;
831
832#if (BTM_WBS_INCLUDED == TRUE )
833        case BTA_AG_SCO_CODEC_ST:
834            switch (event)
835            {
836                case BTA_AG_SCO_LISTEN_E:
837                    /* create sco listen connection (Additional channel) */
838                    bta_ag_create_sco(p_scb, FALSE);
839                    break;
840
841                case BTA_AG_SCO_CN_DONE_E:
842                    /* create sco connection to peer */
843                    bta_ag_create_sco(p_scb, TRUE);
844                    p_sco->state = BTA_AG_SCO_OPENING_ST;
845                    break;
846
847                case BTA_AG_SCO_XFER_E:
848                    /* save xfer scb */
849                    p_sco->p_xfer_scb = p_scb;
850                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
851                    break;
852
853                case BTA_AG_SCO_SHUTDOWN_E:
854                    /* remove listening connection */
855                    bta_ag_remove_sco(p_scb, FALSE);
856
857                    if (p_scb == p_sco->p_curr_scb)
858                        p_sco->p_curr_scb = NULL;
859
860                    /* If last SCO instance then finish shutting down */
861                    if (!bta_ag_other_scb_open(p_scb))
862                    {
863                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
864                    }
865                    break;
866
867                case BTA_AG_SCO_CLOSE_E:
868                    /* sco open is not started yet. just go back to listening */
869                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
870                    break;
871
872                case BTA_AG_SCO_CONN_CLOSE_E:
873                    /* sco failed; create sco listen connection */
874                    bta_ag_create_sco(p_scb, FALSE);
875                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
876                    break;
877
878                default:
879                    APPL_TRACE_WARNING("BTA_AG_SCO_CODEC_ST: Ignoring event %d", event);
880                    break;
881            }
882            break;
883#endif
884
885        case BTA_AG_SCO_OPENING_ST:
886            switch (event)
887            {
888                case BTA_AG_SCO_LISTEN_E:
889                    /* second headset has now joined */
890                    /* create sco listen connection (Additional channel) */
891                    if (p_scb != p_sco->p_curr_scb)
892                    {
893                        bta_ag_create_sco(p_scb, FALSE);
894                    }
895                    break;
896
897#if (BTM_WBS_INCLUDED == TRUE)
898                case BTA_AG_SCO_REOPEN_E:
899                    /* start codec negotiation */
900                    p_sco->state = BTA_AG_SCO_CODEC_ST;
901                    p_cn_scb = p_scb;
902                    break;
903#endif
904
905                case BTA_AG_SCO_XFER_E:
906                    /* save xfer scb */
907                    p_sco->p_xfer_scb = p_scb;
908                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
909                    break;
910
911                case BTA_AG_SCO_CLOSE_E:
912                    p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
913                    break;
914
915                case BTA_AG_SCO_SHUTDOWN_E:
916                    /* If not opening scb, just close it */
917                    if (p_scb != p_sco->p_curr_scb)
918                    {
919                        /* remove listening connection */
920                        bta_ag_remove_sco(p_scb, FALSE);
921                    }
922                    else
923                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
924
925                    break;
926
927                case BTA_AG_SCO_CONN_OPEN_E:
928                    p_sco->state = BTA_AG_SCO_OPEN_ST;
929                    break;
930
931                case BTA_AG_SCO_CONN_CLOSE_E:
932                    /* sco failed; create sco listen connection */
933                    bta_ag_create_sco(p_scb, FALSE);
934                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
935                    break;
936
937                default:
938                    APPL_TRACE_WARNING("BTA_AG_SCO_OPENING_ST: Ignoring event %d", event);
939                    break;
940            }
941            break;
942
943        case BTA_AG_SCO_OPEN_CL_ST:
944            switch (event)
945            {
946                case BTA_AG_SCO_XFER_E:
947                    /* save xfer scb */
948                    p_sco->p_xfer_scb = p_scb;
949
950                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
951                    break;
952
953                case BTA_AG_SCO_OPEN_E:
954                    p_sco->state = BTA_AG_SCO_OPENING_ST;
955                    break;
956
957                case BTA_AG_SCO_SHUTDOWN_E:
958                    /* If not opening scb, just close it */
959                    if (p_scb != p_sco->p_curr_scb)
960                    {
961                        /* remove listening connection */
962                        bta_ag_remove_sco(p_scb, FALSE);
963                    }
964                    else
965                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
966
967                    break;
968
969                case BTA_AG_SCO_CONN_OPEN_E:
970                    /* close sco connection */
971                    bta_ag_remove_sco(p_scb, TRUE);
972
973                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
974                    break;
975
976                case BTA_AG_SCO_CONN_CLOSE_E:
977                    /* sco failed; create sco listen connection */
978
979                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
980                    break;
981
982                default:
983                    APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d", event);
984                    break;
985            }
986            break;
987
988        case BTA_AG_SCO_OPEN_XFER_ST:
989            switch (event)
990            {
991                case BTA_AG_SCO_CLOSE_E:
992                    /* close sco connection */
993                    bta_ag_remove_sco(p_scb, TRUE);
994
995                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
996                    break;
997
998                case BTA_AG_SCO_SHUTDOWN_E:
999                    /* remove all connection */
1000                    bta_ag_remove_sco(p_scb, FALSE);
1001                    p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1002
1003                    break;
1004
1005                case BTA_AG_SCO_CONN_CLOSE_E:
1006                    /* closed sco; place in listen mode and
1007                       accept the transferred connection */
1008                    bta_ag_create_sco(p_scb, FALSE);    /* Back into listen mode */
1009
1010                    /* Accept sco connection with xfer scb */
1011                    bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
1012                    p_sco->state = BTA_AG_SCO_OPENING_ST;
1013                    p_sco->p_curr_scb = p_sco->p_xfer_scb;
1014                    p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
1015                    p_sco->p_xfer_scb = NULL;
1016                     break;
1017
1018                default:
1019                    APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d", event);
1020                    break;
1021            }
1022            break;
1023
1024        case BTA_AG_SCO_OPEN_ST:
1025            switch (event)
1026            {
1027                case BTA_AG_SCO_LISTEN_E:
1028                    /* second headset has now joined */
1029                    /* create sco listen connection (Additional channel) */
1030                    if (p_scb != p_sco->p_curr_scb)
1031                    {
1032                        bta_ag_create_sco(p_scb, FALSE);
1033                    }
1034                    break;
1035
1036                case BTA_AG_SCO_XFER_E:
1037                    /* close current sco connection */
1038                    bta_ag_remove_sco(p_sco->p_curr_scb, TRUE);
1039
1040                    /* save xfer scb */
1041                    p_sco->p_xfer_scb = p_scb;
1042
1043                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
1044                    break;
1045
1046                case BTA_AG_SCO_CLOSE_E:
1047                    /* close sco connection if active */
1048                    if (bta_ag_remove_sco(p_scb, TRUE))
1049                    {
1050                        p_sco->state = BTA_AG_SCO_CLOSING_ST;
1051                    }
1052                    break;
1053
1054                case BTA_AG_SCO_SHUTDOWN_E:
1055                    /* remove all listening connections */
1056                    bta_ag_remove_sco(p_scb, FALSE);
1057
1058                    /* If SCO was active on this scb, close it */
1059                    if (p_scb == p_sco->p_curr_scb)
1060                    {
1061                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1062                    }
1063                    break;
1064
1065                case BTA_AG_SCO_CONN_CLOSE_E:
1066                    /* peer closed sco; create sco listen connection */
1067                    bta_ag_create_sco(p_scb, FALSE);
1068                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
1069                    break;
1070
1071                default:
1072                    APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_ST: Ignoring event %d", event);
1073                    break;
1074            }
1075            break;
1076
1077        case BTA_AG_SCO_CLOSING_ST:
1078            switch (event)
1079            {
1080                case BTA_AG_SCO_LISTEN_E:
1081                    /* create sco listen connection (Additional channel) */
1082                    if (p_scb != p_sco->p_curr_scb)
1083                    {
1084                        bta_ag_create_sco(p_scb, FALSE);
1085                    }
1086                    break;
1087
1088                case BTA_AG_SCO_OPEN_E:
1089                    p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
1090                    break;
1091
1092                case BTA_AG_SCO_XFER_E:
1093                    /* save xfer scb */
1094                    p_sco->p_xfer_scb = p_scb;
1095
1096                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
1097                    break;
1098
1099                case BTA_AG_SCO_SHUTDOWN_E:
1100                    /* If not closing scb, just close it */
1101                    if (p_scb != p_sco->p_curr_scb)
1102                    {
1103                        /* remove listening connection */
1104                        bta_ag_remove_sco(p_scb, FALSE);
1105                    }
1106                    else
1107                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1108
1109                    break;
1110
1111                case BTA_AG_SCO_CONN_CLOSE_E:
1112                    /* peer closed sco; create sco listen connection */
1113                    bta_ag_create_sco(p_scb, FALSE);
1114
1115                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
1116                    break;
1117
1118                default:
1119                    APPL_TRACE_WARNING("BTA_AG_SCO_CLOSING_ST: Ignoring event %d", event);
1120                    break;
1121            }
1122            break;
1123
1124        case BTA_AG_SCO_CLOSE_OP_ST:
1125            switch (event)
1126            {
1127                case BTA_AG_SCO_CLOSE_E:
1128                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
1129                    break;
1130
1131                case BTA_AG_SCO_SHUTDOWN_E:
1132                    p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1133                    break;
1134
1135                case BTA_AG_SCO_CONN_CLOSE_E:
1136#if (BTM_WBS_INCLUDED == TRUE )
1137                    /* start codec negotiation */
1138                    p_sco->state = BTA_AG_SCO_CODEC_ST;
1139                    p_cn_scb = p_scb;
1140#else
1141                    /* open sco connection */
1142                    bta_ag_create_sco(p_scb, TRUE);
1143                    p_sco->state = BTA_AG_SCO_OPENING_ST;
1144#endif
1145                    break;
1146
1147                case BTA_AG_SCO_LISTEN_E:
1148                    /* create sco listen connection (Additional channel) */
1149                    if (p_scb != p_sco->p_curr_scb)
1150                    {
1151                        bta_ag_create_sco(p_scb, FALSE);
1152                    }
1153                    break;
1154
1155                default:
1156                    APPL_TRACE_WARNING("BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d", event);
1157                    break;
1158            }
1159            break;
1160
1161        case BTA_AG_SCO_CLOSE_XFER_ST:
1162            switch (event)
1163            {
1164                case BTA_AG_SCO_CONN_OPEN_E:
1165                    /* close sco connection so headset can be transferred
1166                       Probably entered this state from "opening state" */
1167                    bta_ag_remove_sco(p_scb, TRUE);
1168                    break;
1169
1170                case BTA_AG_SCO_CLOSE_E:
1171                    /* clear xfer scb */
1172                    p_sco->p_xfer_scb = NULL;
1173
1174                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
1175                    break;
1176
1177                case BTA_AG_SCO_SHUTDOWN_E:
1178                    /* clear xfer scb */
1179                    p_sco->p_xfer_scb = NULL;
1180
1181                    p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1182                    break;
1183
1184                case BTA_AG_SCO_CONN_CLOSE_E:
1185                    /* closed sco; place old sco in listen mode,
1186                       take current sco out of listen, and
1187                       create originating sco for current */
1188                    bta_ag_create_sco(p_scb, FALSE);
1189                    bta_ag_remove_sco(p_sco->p_xfer_scb, FALSE);
1190
1191#if (BTM_WBS_INCLUDED == TRUE )
1192                    /* start codec negotiation */
1193                    p_sco->state = BTA_AG_SCO_CODEC_ST;
1194                    p_cn_scb = p_sco->p_xfer_scb;
1195                    p_sco->p_xfer_scb = NULL;
1196#else
1197                    /* create sco connection to peer */
1198                    bta_ag_create_sco(p_sco->p_xfer_scb, TRUE);
1199                    p_sco->p_xfer_scb = NULL;
1200                    p_sco->state = BTA_AG_SCO_OPENING_ST;
1201#endif
1202                    break;
1203
1204                default:
1205                    APPL_TRACE_WARNING("BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d", event);
1206                    break;
1207            }
1208            break;
1209
1210        case BTA_AG_SCO_SHUTTING_ST:
1211            switch (event)
1212            {
1213                case BTA_AG_SCO_CONN_OPEN_E:
1214                    /* close sco connection; wait for conn close event */
1215                    bta_ag_remove_sco(p_scb, TRUE);
1216                    break;
1217
1218                case BTA_AG_SCO_CONN_CLOSE_E:
1219                    /* If last SCO instance then finish shutting down */
1220                    if (!bta_ag_other_scb_open(p_scb))
1221                    {
1222                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1223                    }
1224                    else    /* Other instance is still listening */
1225                    {
1226                        p_sco->state = BTA_AG_SCO_LISTEN_ST;
1227                    }
1228
1229                    /* If SCO closed for other HS which is not being disconnected,
1230                       then create listen sco connection for it as scb still open */
1231                    if (bta_ag_scb_open(p_scb))
1232                    {
1233                        bta_ag_create_sco(p_scb, FALSE);
1234                        p_sco->state = BTA_AG_SCO_LISTEN_ST;
1235                    }
1236
1237                    if (p_scb == p_sco->p_curr_scb)
1238                    {
1239                        p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1240                        p_sco->p_curr_scb = NULL;
1241                    }
1242                    break;
1243
1244                case BTA_AG_SCO_LISTEN_E:
1245                    /* create sco listen connection (Additional channel) */
1246                    if (p_scb != p_sco->p_curr_scb)
1247                    {
1248                        bta_ag_create_sco(p_scb, FALSE);
1249                    }
1250                    break;
1251
1252                case BTA_AG_SCO_SHUTDOWN_E:
1253                    if (!bta_ag_other_scb_open(p_scb))
1254                    {
1255                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1256                    }
1257                    else    /* Other instance is still listening */
1258                    {
1259                        p_sco->state = BTA_AG_SCO_LISTEN_ST;
1260                    }
1261
1262                    if (p_scb == p_sco->p_curr_scb)
1263                    {
1264                        p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1265                        p_sco->p_curr_scb = NULL;
1266                    }
1267                    break;
1268
1269                default:
1270                    APPL_TRACE_WARNING("BTA_AG_SCO_SHUTTING_ST: Ignoring event %d", event);
1271                    break;
1272            }
1273            break;
1274
1275        default:
1276            break;
1277    }
1278#if BTA_AG_SCO_DEBUG == TRUE
1279    if (p_sco->state != in_state)
1280    {
1281        APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
1282                      bta_ag_sco_state_str(in_state),
1283                      bta_ag_sco_state_str(p_sco->state),
1284                      bta_ag_sco_evt_str(event));
1285    }
1286#endif
1287
1288#if (BTM_WBS_INCLUDED == TRUE )
1289    if (p_cn_scb)
1290    {
1291        bta_ag_codec_negotiate(p_cn_scb);
1292    }
1293#endif
1294}
1295
1296/*******************************************************************************
1297**
1298** Function         bta_ag_sco_is_open
1299**
1300** Description      Check if sco is open for this scb.
1301**
1302**
1303** Returns          TRUE if sco open for this scb, FALSE otherwise.
1304**
1305*******************************************************************************/
1306BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb)
1307{
1308    return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
1309            (bta_ag_cb.sco.p_curr_scb == p_scb));
1310}
1311
1312/*******************************************************************************
1313**
1314** Function         bta_ag_sco_is_opening
1315**
1316** Description      Check if sco is in Opening state.
1317**
1318**
1319** Returns          TRUE if sco is in Opening state for this scb, FALSE otherwise.
1320**
1321*******************************************************************************/
1322BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb)
1323{
1324#if (BTM_WBS_INCLUDED == TRUE )
1325    return (((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) ||
1326            (bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST)) &&
1327            (bta_ag_cb.sco.p_curr_scb == p_scb));
1328#else
1329    return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
1330            (bta_ag_cb.sco.p_curr_scb == p_scb));
1331#endif
1332}
1333
1334/*******************************************************************************
1335**
1336** Function         bta_ag_sco_listen
1337**
1338** Description
1339**
1340**
1341** Returns          void
1342**
1343*******************************************************************************/
1344void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1345{
1346    UNUSED(p_data);
1347    bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
1348}
1349
1350/*******************************************************************************
1351**
1352** Function         bta_ag_sco_open
1353**
1354** Description
1355**
1356**
1357** Returns          void
1358**
1359*******************************************************************************/
1360void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1361{
1362    UINT8 event;
1363    UNUSED(p_data);
1364
1365    /* if another scb using sco, this is a transfer */
1366    if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb)
1367    {
1368        event = BTA_AG_SCO_XFER_E;
1369    }
1370    /* else it is an open */
1371    else
1372    {
1373        event = BTA_AG_SCO_OPEN_E;
1374    }
1375
1376    bta_ag_sco_event(p_scb, event);
1377}
1378
1379/*******************************************************************************
1380**
1381** Function         bta_ag_sco_close
1382**
1383** Description
1384**
1385**
1386** Returns          void
1387**
1388*******************************************************************************/
1389void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1390{
1391    UNUSED(p_data);
1392
1393    /* if scb is in use */
1394#if (BTM_WBS_INCLUDED == TRUE )
1395    /* sco_idx is not allocated in SCO_CODEC_ST, we still need to move to listening state. */
1396    if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) || (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
1397#else
1398    if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
1399#endif
1400    {
1401        APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
1402        bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1403    }
1404}
1405
1406#if (BTM_WBS_INCLUDED == TRUE )
1407
1408/*******************************************************************************
1409**
1410** Function         bta_ag_sco_codec_nego
1411**
1412** Description
1413**
1414**
1415** Returns          void
1416**
1417*******************************************************************************/
1418void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result)
1419{
1420    if(result == TRUE)
1421    {
1422        /* Subsequent sco connection will skip codec negotiation */
1423        p_scb->codec_updated = FALSE;
1424
1425        bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
1426    }
1427    else    /* codec negotiation failed */
1428        bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1429}
1430#endif
1431
1432/*******************************************************************************
1433**
1434** Function         bta_ag_sco_shutdown
1435**
1436** Description
1437**
1438**
1439** Returns          void
1440**
1441*******************************************************************************/
1442void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1443{
1444    UNUSED(p_data);
1445
1446    bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
1447}
1448
1449/*******************************************************************************
1450**
1451** Function         bta_ag_sco_conn_open
1452**
1453** Description
1454**
1455**
1456** Returns          void
1457**
1458*******************************************************************************/
1459void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1460{
1461    UNUSED(p_data);
1462
1463    bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
1464
1465    bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1466
1467#if (BTM_WBS_INCLUDED == TRUE)
1468    bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON,
1469                          p_scb->inuse_codec);
1470#else
1471    bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON);
1472#endif
1473
1474#if (BTM_SCO_HCI_INCLUDED == TRUE )
1475    /* open SCO codec if SCO is routed through transport */
1476    bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT);
1477#endif
1478
1479    /* call app callback */
1480    bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
1481
1482    p_scb->retry_with_sco_only = FALSE;
1483#if (BTM_WBS_INCLUDED == TRUE)
1484    /* reset to mSBC T2 settings as the preferred */
1485    p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1486#endif
1487}
1488
1489/*******************************************************************************
1490**
1491** Function         bta_ag_sco_conn_close
1492**
1493** Description
1494**
1495**
1496** Returns          void
1497**
1498*******************************************************************************/
1499void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1500{
1501    UINT16 handle = bta_ag_scb_to_idx(p_scb);
1502    UNUSED(p_data);
1503
1504    /* clear current scb */
1505    bta_ag_cb.sco.p_curr_scb = NULL;
1506    p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1507
1508#if (BTM_WBS_INCLUDED == TRUE)
1509    /* codec_fallback is set when AG is initiator and connection failed for mSBC. */
1510    /* OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */
1511    if ((p_scb->codec_fallback && p_scb->svc_conn) ||
1512         bta_ag_attempt_msbc_safe_settings(p_scb))
1513    {
1514        bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
1515    }
1516    else if (p_scb->retry_with_sco_only && p_scb->svc_conn)
1517    {
1518        /* retry_with_sco_only is set when AG is initiator and connection failed for eSCO */
1519        bta_ag_create_sco(p_scb, TRUE);
1520    }
1521#else
1522    /* retry_with_sco_only, will be set only when AG is initiator
1523    ** and AG is first trying to establish an eSCO connection */
1524    if (p_scb->retry_with_sco_only && p_scb->svc_conn)
1525    {
1526        bta_ag_create_sco(p_scb, TRUE);
1527    }
1528#endif
1529    else
1530    {
1531        sco_state_t sco_state = bta_ag_cb.sco.p_xfer_scb ? SCO_STATE_OFF_TRANSFER : SCO_STATE_OFF;
1532#if (BTM_WBS_INCLUDED == TRUE)
1533        /* Indicate if the closing of audio is because of transfer */
1534        bta_ag_co_audio_state(handle, p_scb->app_id, sco_state, p_scb->inuse_codec);
1535#else
1536        /* Indicate if the closing of audio is because of transfer */
1537        bta_ag_co_audio_state(handle, p_scb->app_id, sco_state);
1538#endif
1539        bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
1540
1541        bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1542
1543        /* if av got suspended by this call, let it resume. */
1544        /* In case call stays alive regardless of sco, av should not be affected. */
1545        if(((p_scb->call_ind == BTA_AG_CALL_INACTIVE) && (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
1546            || (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END))
1547        {
1548            bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1549        }
1550
1551        /* call app callback */
1552        bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
1553#if (BTM_WBS_INCLUDED == TRUE)
1554        p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1555#endif
1556    }
1557    p_scb->retry_with_sco_only = FALSE;
1558}
1559
1560/*******************************************************************************
1561**
1562** Function         bta_ag_sco_conn_rsp
1563**
1564** Description      Process the SCO connection request
1565**
1566**
1567** Returns          void
1568**
1569*******************************************************************************/
1570void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
1571{
1572    tBTM_ESCO_PARAMS    resp;
1573    UINT8               hci_status = HCI_SUCCESS;
1574#if (BTM_SCO_HCI_INCLUDED == TRUE )
1575    tBTA_CODEC_INFO     codec_info = {BTA_SCO_CODEC_PCM};
1576    UINT32              pcm_sample_rate;
1577#endif
1578
1579    if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST     ||
1580        bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
1581        bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST)
1582    {
1583        /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */
1584        if (bta_ag_cb.sco.param_updated)
1585        {
1586            resp = bta_ag_cb.sco.params;
1587        }
1588        else
1589        {
1590            resp.rx_bw = BTM_64KBITS_RATE;
1591            resp.tx_bw = BTM_64KBITS_RATE;
1592            resp.max_latency = 10;
1593            resp.voice_contfmt = 0x60;
1594            resp.retrans_effort = BTM_ESCO_RETRANS_POWER;
1595
1596            if (p_data->link_type == BTM_LINK_TYPE_SCO)
1597            {
1598                resp.packet_types = (BTM_SCO_LINK_ONLY_MASK          |
1599                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
1600                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
1601                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
1602                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
1603            }
1604            else    /* Allow controller to use all types available except 5-slot EDR */
1605            {
1606                resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
1607                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
1608                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
1609            }
1610        }
1611
1612        /* tell sys to stop av if any */
1613        bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1614
1615#if (BTM_WBS_INCLUDED == FALSE )
1616        /* Allow any platform specific pre-SCO set up to take place */
1617        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP);
1618#else
1619        /* When HS initiated SCO, it cannot be WBS. */
1620        /* Allow any platform specific pre-SCO set up to take place */
1621        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP,
1622                              BTA_AG_CODEC_CVSD);
1623#endif
1624
1625#if (BTM_SCO_HCI_INCLUDED == TRUE )
1626        pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
1627
1628        /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
1629        BTM_ConfigScoPath(bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id),
1630            bta_ag_sco_read_cback, NULL, TRUE);
1631#endif
1632    }
1633    else
1634        hci_status = HCI_ERR_HOST_REJECT_DEVICE;
1635
1636#if (BTM_WBS_INCLUDED == TRUE )
1637    /* If SCO open was initiated from HS, it must be CVSD */
1638    p_scb->inuse_codec = BTA_AG_CODEC_NONE;
1639#endif
1640
1641    BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
1642}
1643
1644/*******************************************************************************
1645**
1646** Function         bta_ag_ci_sco_data
1647**
1648** Description      Process the SCO data ready callin event
1649**
1650**
1651** Returns          void
1652**
1653*******************************************************************************/
1654void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1655{
1656    UNUSED(p_scb);
1657    UNUSED(p_data);
1658
1659#if (BTM_SCO_HCI_INCLUDED == TRUE )
1660    bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
1661#endif
1662}
1663
1664/*******************************************************************************
1665**
1666** Function         bta_ag_set_esco_param
1667**
1668** Description      Update esco parameters from script wrapper.
1669**
1670**
1671** Returns          void
1672**
1673*******************************************************************************/
1674void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param)
1675{
1676    if(set_reset == FALSE)    /* reset the parameters to default */
1677    {
1678        bta_ag_cb.sco.param_updated = FALSE;
1679        APPL_TRACE_DEBUG("bta_ag_set_esco_param : Resetting ESCO parameters to default");
1680    }
1681    else
1682    {
1683        bta_ag_cb.sco.param_updated = TRUE;
1684        bta_ag_cb.sco.params = *param;
1685        APPL_TRACE_DEBUG("bta_ag_set_esco_param : Setting ESCO parameters");
1686    }
1687}
1688
1689/*******************************************************************************
1690**  Debugging functions
1691*******************************************************************************/
1692
1693#if BTA_AG_SCO_DEBUG == TRUE
1694static char *bta_ag_sco_evt_str(UINT8 event)
1695{
1696    switch (event)
1697    {
1698    case BTA_AG_SCO_LISTEN_E:
1699        return "Listen Request";
1700    case BTA_AG_SCO_OPEN_E:
1701        return "Open Request";
1702    case BTA_AG_SCO_XFER_E:
1703        return "Transfer Request";
1704#if (BTM_WBS_INCLUDED == TRUE )
1705    case BTA_AG_SCO_CN_DONE_E:
1706        return "Codec Negotiation Done";
1707    case BTA_AG_SCO_REOPEN_E:
1708        return "Reopen Request";
1709#endif
1710    case BTA_AG_SCO_CLOSE_E:
1711        return "Close Request";
1712    case BTA_AG_SCO_SHUTDOWN_E:
1713        return "Shutdown Request";
1714    case BTA_AG_SCO_CONN_OPEN_E:
1715        return "Opened";
1716    case BTA_AG_SCO_CONN_CLOSE_E:
1717        return "Closed";
1718    case BTA_AG_SCO_CI_DATA_E  :
1719        return "Sco Data";
1720    default:
1721        return "Unknown SCO Event";
1722    }
1723}
1724
1725static char *bta_ag_sco_state_str(UINT8 state)
1726{
1727    switch (state)
1728    {
1729    case BTA_AG_SCO_SHUTDOWN_ST:
1730        return "Shutdown";
1731    case BTA_AG_SCO_LISTEN_ST:
1732        return "Listening";
1733#if (BTM_WBS_INCLUDED == TRUE )
1734    case BTA_AG_SCO_CODEC_ST:
1735        return "Codec Negotiation";
1736#endif
1737    case BTA_AG_SCO_OPENING_ST:
1738        return "Opening";
1739    case BTA_AG_SCO_OPEN_CL_ST:
1740        return "Open while closing";
1741    case BTA_AG_SCO_OPEN_XFER_ST:
1742        return "Opening while Transferring";
1743    case BTA_AG_SCO_OPEN_ST:
1744        return "Open";
1745    case BTA_AG_SCO_CLOSING_ST:
1746        return "Closing";
1747    case BTA_AG_SCO_CLOSE_OP_ST:
1748        return "Close while Opening";
1749    case BTA_AG_SCO_CLOSE_XFER_ST:
1750        return "Close while Transferring";
1751    case BTA_AG_SCO_SHUTTING_ST:
1752        return "Shutting Down";
1753    default:
1754        return "Unknown SCO State";
1755    }
1756}
1757
1758#endif
1759