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