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