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