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