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