bta_ag_sco.c revision 5b675bc41986a159023c51b561e81939f0632f95
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                        APPL_TRACE_DEBUG0("create sco listen connection if scb still open");
1234                        bta_ag_create_sco(p_scb, FALSE);
1235                        p_sco->state = BTA_AG_SCO_LISTEN_ST;
1236                    }
1237
1238                    if (p_scb == p_sco->p_curr_scb)
1239                    {
1240                        p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1241                        p_sco->p_curr_scb = NULL;
1242                    }
1243                    break;
1244
1245                case BTA_AG_SCO_LISTEN_E:
1246                    /* create sco listen connection (Additional channel) */
1247                    if (p_scb != p_sco->p_curr_scb)
1248                    {
1249                        bta_ag_create_sco(p_scb, FALSE);
1250                    }
1251                    break;
1252
1253                case BTA_AG_SCO_SHUTDOWN_E:
1254                    if (!bta_ag_other_scb_open(p_scb))
1255                    {
1256                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1257                    }
1258                    else    /* Other instance is still listening */
1259                    {
1260                        p_sco->state = BTA_AG_SCO_LISTEN_ST;
1261                    }
1262
1263                    if (p_scb == p_sco->p_curr_scb)
1264                    {
1265                        p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1266                        p_sco->p_curr_scb = NULL;
1267                    }
1268                    break;
1269
1270                default:
1271                    APPL_TRACE_WARNING("BTA_AG_SCO_SHUTTING_ST: Ignoring event %d", event);
1272                    break;
1273            }
1274            break;
1275
1276        default:
1277            break;
1278    }
1279#if BTA_AG_SCO_DEBUG == TRUE
1280    if (p_sco->state != in_state)
1281    {
1282        APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
1283                      bta_ag_sco_state_str(in_state),
1284                      bta_ag_sco_state_str(p_sco->state),
1285                      bta_ag_sco_evt_str(event));
1286    }
1287#endif
1288
1289#if (BTM_WBS_INCLUDED == TRUE )
1290    if (p_cn_scb)
1291    {
1292        bta_ag_codec_negotiate(p_cn_scb);
1293    }
1294#endif
1295}
1296
1297/*******************************************************************************
1298**
1299** Function         bta_ag_sco_is_open
1300**
1301** Description      Check if sco is open for this scb.
1302**
1303**
1304** Returns          TRUE if sco open for this scb, FALSE otherwise.
1305**
1306*******************************************************************************/
1307BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb)
1308{
1309    return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
1310            (bta_ag_cb.sco.p_curr_scb == p_scb));
1311}
1312
1313/*******************************************************************************
1314**
1315** Function         bta_ag_sco_is_opening
1316**
1317** Description      Check if sco is in Opening state.
1318**
1319**
1320** Returns          TRUE if sco is in Opening state for this scb, FALSE otherwise.
1321**
1322*******************************************************************************/
1323BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb)
1324{
1325#if (BTM_WBS_INCLUDED == TRUE )
1326    return (((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) ||
1327            (bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST)) &&
1328            (bta_ag_cb.sco.p_curr_scb == p_scb));
1329#else
1330    return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
1331            (bta_ag_cb.sco.p_curr_scb == p_scb));
1332#endif
1333}
1334
1335/*******************************************************************************
1336**
1337** Function         bta_ag_sco_listen
1338**
1339** Description
1340**
1341**
1342** Returns          void
1343**
1344*******************************************************************************/
1345void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1346{
1347    UNUSED(p_data);
1348    bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
1349}
1350
1351/*******************************************************************************
1352**
1353** Function         bta_ag_sco_open
1354**
1355** Description
1356**
1357**
1358** Returns          void
1359**
1360*******************************************************************************/
1361void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1362{
1363    UINT8 event;
1364    UNUSED(p_data);
1365
1366    /* if another scb using sco, this is a transfer */
1367    if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb)
1368    {
1369        event = BTA_AG_SCO_XFER_E;
1370    }
1371    /* else it is an open */
1372    else
1373    {
1374        event = BTA_AG_SCO_OPEN_E;
1375    }
1376
1377    bta_ag_sco_event(p_scb, event);
1378}
1379
1380/*******************************************************************************
1381**
1382** Function         bta_ag_sco_close
1383**
1384** Description
1385**
1386**
1387** Returns          void
1388**
1389*******************************************************************************/
1390void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1391{
1392    UNUSED(p_data);
1393
1394    /* if scb is in use */
1395#if (BTM_WBS_INCLUDED == TRUE )
1396    /* sco_idx is not allocated in SCO_CODEC_ST, we still need to move to listening state. */
1397    if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) || (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
1398#else
1399    if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
1400#endif
1401    {
1402        APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
1403        bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1404    }
1405}
1406
1407#if (BTM_WBS_INCLUDED == TRUE )
1408
1409/*******************************************************************************
1410**
1411** Function         bta_ag_sco_codec_nego
1412**
1413** Description
1414**
1415**
1416** Returns          void
1417**
1418*******************************************************************************/
1419void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result)
1420{
1421    if(result == TRUE)
1422    {
1423        /* Subsequent sco connection will skip codec negotiation */
1424        p_scb->codec_updated = FALSE;
1425
1426        bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
1427    }
1428    else    /* codec negotiation failed */
1429        bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1430}
1431#endif
1432
1433/*******************************************************************************
1434**
1435** Function         bta_ag_sco_shutdown
1436**
1437** Description
1438**
1439**
1440** Returns          void
1441**
1442*******************************************************************************/
1443void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1444{
1445    UNUSED(p_data);
1446
1447    bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
1448}
1449
1450/*******************************************************************************
1451**
1452** Function         bta_ag_sco_conn_open
1453**
1454** Description
1455**
1456**
1457** Returns          void
1458**
1459*******************************************************************************/
1460void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1461{
1462    UNUSED(p_data);
1463
1464    bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
1465
1466    bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1467
1468#if (BTM_WBS_INCLUDED == TRUE)
1469    bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON,
1470                          p_scb->inuse_codec);
1471#else
1472    bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON);
1473#endif
1474
1475#if (BTM_SCO_HCI_INCLUDED == TRUE )
1476    /* open SCO codec if SCO is routed through transport */
1477    bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT);
1478#endif
1479
1480    /* call app callback */
1481    bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
1482
1483    p_scb->retry_with_sco_only = FALSE;
1484#if (BTM_WBS_INCLUDED == TRUE)
1485    /* reset to mSBC T2 settings as the preferred */
1486    p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1487#endif
1488}
1489
1490/*******************************************************************************
1491**
1492** Function         bta_ag_sco_conn_close
1493**
1494** Description
1495**
1496**
1497** Returns          void
1498**
1499*******************************************************************************/
1500void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1501{
1502    UINT16 handle = bta_ag_scb_to_idx(p_scb);
1503    UNUSED(p_data);
1504
1505    /* clear current scb */
1506    bta_ag_cb.sco.p_curr_scb = NULL;
1507    p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1508
1509#if (BTM_WBS_INCLUDED == TRUE)
1510    /* codec_fallback is set when AG is initiator and connection failed for mSBC. */
1511    /* OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */
1512    if ((p_scb->codec_fallback && p_scb->svc_conn) ||
1513         bta_ag_attempt_msbc_safe_settings(p_scb))
1514    {
1515        bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
1516    }
1517    else if (p_scb->retry_with_sco_only && p_scb->svc_conn)
1518    {
1519        /* retry_with_sco_only is set when AG is initiator and connection failed for eSCO */
1520        bta_ag_create_sco(p_scb, TRUE);
1521    }
1522#else
1523    /* retry_with_sco_only, will be set only when AG is initiator
1524    ** and AG is first trying to establish an eSCO connection */
1525    if (p_scb->retry_with_sco_only && p_scb->svc_conn)
1526    {
1527        bta_ag_create_sco(p_scb, TRUE);
1528    }
1529#endif
1530    else
1531    {
1532        sco_state_t sco_state = bta_ag_cb.sco.p_xfer_scb ? SCO_STATE_OFF_TRANSFER : SCO_STATE_OFF;
1533#if (BTM_WBS_INCLUDED == TRUE)
1534        /* Indicate if the closing of audio is because of transfer */
1535        bta_ag_co_audio_state(handle, p_scb->app_id, sco_state, p_scb->inuse_codec);
1536#else
1537        /* Indicate if the closing of audio is because of transfer */
1538        bta_ag_co_audio_state(handle, p_scb->app_id, sco_state);
1539#endif
1540        bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
1541
1542        bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1543
1544        /* if av got suspended by this call, let it resume. */
1545        /* In case call stays alive regardless of sco, av should not be affected. */
1546        if(((p_scb->call_ind == BTA_AG_CALL_INACTIVE) && (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
1547            || (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END))
1548        {
1549            bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1550        }
1551
1552        /* call app callback */
1553        bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
1554#if (BTM_WBS_INCLUDED == TRUE)
1555        p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1556#endif
1557    }
1558    p_scb->retry_with_sco_only = FALSE;
1559}
1560
1561/*******************************************************************************
1562**
1563** Function         bta_ag_sco_conn_rsp
1564**
1565** Description      Process the SCO connection request
1566**
1567**
1568** Returns          void
1569**
1570*******************************************************************************/
1571void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
1572{
1573    tBTM_ESCO_PARAMS    resp;
1574    UINT8               hci_status = HCI_SUCCESS;
1575#if (BTM_SCO_HCI_INCLUDED == TRUE )
1576    tBTA_CODEC_INFO     codec_info = {BTA_SCO_CODEC_PCM};
1577    UINT32              pcm_sample_rate;
1578#endif
1579
1580    if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST     ||
1581        bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
1582        bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST)
1583    {
1584        /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */
1585        if (bta_ag_cb.sco.param_updated)
1586        {
1587            resp = bta_ag_cb.sco.params;
1588        }
1589        else
1590        {
1591            resp.rx_bw = BTM_64KBITS_RATE;
1592            resp.tx_bw = BTM_64KBITS_RATE;
1593            resp.max_latency = 10;
1594            resp.voice_contfmt = 0x60;
1595            resp.retrans_effort = BTM_ESCO_RETRANS_POWER;
1596
1597            if (p_data->link_type == BTM_LINK_TYPE_SCO)
1598            {
1599                resp.packet_types = (BTM_SCO_LINK_ONLY_MASK          |
1600                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
1601                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
1602                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
1603                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
1604            }
1605            else    /* Allow controller to use all types available except 5-slot EDR */
1606            {
1607                resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
1608                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
1609                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
1610            }
1611        }
1612
1613        /* tell sys to stop av if any */
1614        bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1615
1616#if (BTM_WBS_INCLUDED == FALSE )
1617        /* Allow any platform specific pre-SCO set up to take place */
1618        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP);
1619#else
1620        /* When HS initiated SCO, it cannot be WBS. */
1621        /* Allow any platform specific pre-SCO set up to take place */
1622        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP,
1623                              BTA_AG_CODEC_CVSD);
1624#endif
1625
1626#if (BTM_SCO_HCI_INCLUDED == TRUE )
1627        pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
1628
1629        /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
1630        BTM_ConfigScoPath(bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id),
1631            bta_ag_sco_read_cback, NULL, TRUE);
1632#endif
1633    }
1634    else
1635        hci_status = HCI_ERR_HOST_REJECT_DEVICE;
1636
1637#if (BTM_WBS_INCLUDED == TRUE )
1638    /* If SCO open was initiated from HS, it must be CVSD */
1639    p_scb->inuse_codec = BTA_AG_CODEC_NONE;
1640#endif
1641
1642    BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
1643}
1644
1645/*******************************************************************************
1646**
1647** Function         bta_ag_ci_sco_data
1648**
1649** Description      Process the SCO data ready callin event
1650**
1651**
1652** Returns          void
1653**
1654*******************************************************************************/
1655void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
1656{
1657    UNUSED(p_scb);
1658    UNUSED(p_data);
1659
1660#if (BTM_SCO_HCI_INCLUDED == TRUE )
1661    bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
1662#endif
1663}
1664
1665/*******************************************************************************
1666**
1667** Function         bta_ag_set_esco_param
1668**
1669** Description      Update esco parameters from script wrapper.
1670**
1671**
1672** Returns          void
1673**
1674*******************************************************************************/
1675void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param)
1676{
1677    if(set_reset == FALSE)    /* reset the parameters to default */
1678    {
1679        bta_ag_cb.sco.param_updated = FALSE;
1680        APPL_TRACE_DEBUG("bta_ag_set_esco_param : Resetting ESCO parameters to default");
1681    }
1682    else
1683    {
1684        bta_ag_cb.sco.param_updated = TRUE;
1685        bta_ag_cb.sco.params = *param;
1686        APPL_TRACE_DEBUG("bta_ag_set_esco_param : Setting ESCO parameters");
1687    }
1688}
1689
1690/*******************************************************************************
1691**  Debugging functions
1692*******************************************************************************/
1693
1694#if BTA_AG_SCO_DEBUG == TRUE
1695static char *bta_ag_sco_evt_str(UINT8 event)
1696{
1697    switch (event)
1698    {
1699    case BTA_AG_SCO_LISTEN_E:
1700        return "Listen Request";
1701    case BTA_AG_SCO_OPEN_E:
1702        return "Open Request";
1703    case BTA_AG_SCO_XFER_E:
1704        return "Transfer Request";
1705#if (BTM_WBS_INCLUDED == TRUE )
1706    case BTA_AG_SCO_CN_DONE_E:
1707        return "Codec Negotiation Done";
1708    case BTA_AG_SCO_REOPEN_E:
1709        return "Reopen Request";
1710#endif
1711    case BTA_AG_SCO_CLOSE_E:
1712        return "Close Request";
1713    case BTA_AG_SCO_SHUTDOWN_E:
1714        return "Shutdown Request";
1715    case BTA_AG_SCO_CONN_OPEN_E:
1716        return "Opened";
1717    case BTA_AG_SCO_CONN_CLOSE_E:
1718        return "Closed";
1719    case BTA_AG_SCO_CI_DATA_E  :
1720        return "Sco Data";
1721    default:
1722        return "Unknown SCO Event";
1723    }
1724}
1725
1726static char *bta_ag_sco_state_str(UINT8 state)
1727{
1728    switch (state)
1729    {
1730    case BTA_AG_SCO_SHUTDOWN_ST:
1731        return "Shutdown";
1732    case BTA_AG_SCO_LISTEN_ST:
1733        return "Listening";
1734#if (BTM_WBS_INCLUDED == TRUE )
1735    case BTA_AG_SCO_CODEC_ST:
1736        return "Codec Negotiation";
1737#endif
1738    case BTA_AG_SCO_OPENING_ST:
1739        return "Opening";
1740    case BTA_AG_SCO_OPEN_CL_ST:
1741        return "Open while closing";
1742    case BTA_AG_SCO_OPEN_XFER_ST:
1743        return "Opening while Transferring";
1744    case BTA_AG_SCO_OPEN_ST:
1745        return "Open";
1746    case BTA_AG_SCO_CLOSING_ST:
1747        return "Closing";
1748    case BTA_AG_SCO_CLOSE_OP_ST:
1749        return "Close while Opening";
1750    case BTA_AG_SCO_CLOSE_XFER_ST:
1751        return "Close while Transferring";
1752    case BTA_AG_SCO_SHUTTING_ST:
1753        return "Shutting Down";
1754    default:
1755        return "Unknown SCO State";
1756    }
1757}
1758
1759#endif
1760