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 "bt_common.h"
28#include "bta_ag_api.h"
29#include "bta_ag_co.h"
30#include "bta_ag_int.h"
31#include "bta_api.h"
32#if (BTM_SCO_HCI_INCLUDED == TRUE)
33#include "bta_dm_co.h"
34#endif
35#include "btm_api.h"
36#include "device/include/controller.h"
37#include "device/include/esco_parameters.h"
38#include "osi/include/osi.h"
39#include "utl.h"
40
41#ifndef BTA_AG_SCO_DEBUG
42#define BTA_AG_SCO_DEBUG FALSE
43#endif
44
45/* Codec negotiation timeout */
46#ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS
47#define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000) /* 3 seconds */
48#endif
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
55static bool sco_allowed = true;
56
57#define BTA_AG_NO_EDR_ESCO                                       \
58  (ESCO_PKT_TYPES_MASK_NO_2_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV3 | \
59   ESCO_PKT_TYPES_MASK_NO_2_EV5 | ESCO_PKT_TYPES_MASK_NO_3_EV5)
60
61/* sco events */
62enum {
63  BTA_AG_SCO_LISTEN_E,       /* listen request */
64  BTA_AG_SCO_OPEN_E,         /* open request */
65  BTA_AG_SCO_XFER_E,         /* transfer request */
66  BTA_AG_SCO_CN_DONE_E, /* codec negotiation done */
67  BTA_AG_SCO_REOPEN_E,  /* Retry with other codec when failed */
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
75static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local);
76
77/*******************************************************************************
78 *
79 * Function         bta_ag_sco_conn_cback
80 *
81 * Description      BTM SCO connection callback.
82 *
83 *
84 * Returns          void
85 *
86 ******************************************************************************/
87static void bta_ag_sco_conn_cback(uint16_t sco_idx) {
88  uint16_t handle;
89  tBTA_AG_SCB* p_scb;
90
91  /* match callback to scb; first check current sco scb */
92  if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use) {
93    handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
94  }
95  /* then check for scb connected to this peer */
96  else {
97    /* Check if SLC is up */
98    handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx));
99    p_scb = bta_ag_scb_by_idx(handle);
100    if (p_scb && !p_scb->svc_conn) handle = 0;
101  }
102
103  if (handle != 0) {
104    BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
105    p_buf->event = BTA_AG_SCO_OPEN_EVT;
106    p_buf->layer_specific = handle;
107    bta_sys_sendmsg(p_buf);
108  } else {
109    /* no match found; disconnect sco, init sco variables */
110    bta_ag_cb.sco.p_curr_scb = NULL;
111    bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
112    BTM_RemoveSco(sco_idx);
113  }
114}
115
116/*******************************************************************************
117 *
118 * Function         bta_ag_sco_disc_cback
119 *
120 * Description      BTM SCO disconnection callback.
121 *
122 *
123 * Returns          void
124 *
125 ******************************************************************************/
126static void bta_ag_sco_disc_cback(uint16_t sco_idx) {
127  uint16_t handle = 0;
128
129  APPL_TRACE_DEBUG(
130      "bta_ag_sco_disc_cback(): sco_idx: 0x%x  p_cur_scb: 0x%08x  sco.state: "
131      "%d",
132      sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
133
134  APPL_TRACE_DEBUG(
135      "bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x  in_use: %u  sco_idx: 0x%x "
136      " sco state: %u",
137      &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx,
138      bta_ag_cb.scb[0].state);
139  APPL_TRACE_DEBUG(
140      "bta_ag_sco_disc_cback(): scb[1] addr: 0x%08x  in_use: %u  sco_idx: 0x%x "
141      " sco state: %u",
142      &bta_ag_cb.scb[1], bta_ag_cb.scb[1].in_use, bta_ag_cb.scb[1].sco_idx,
143      bta_ag_cb.scb[1].state);
144
145  /* match callback to scb */
146  if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use) {
147    /* We only care about callbacks for the active SCO */
148    if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx) {
149      if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF) return;
150    }
151    handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
152  }
153
154  if (handle != 0) {
155#if (BTM_SCO_HCI_INCLUDED == TRUE)
156
157    tBTM_STATUS status =
158        BTM_ConfigScoPath(ESCO_DATA_PATH_PCM, NULL, NULL, true);
159    APPL_TRACE_DEBUG("%s: sco close config status = %d", __func__, status);
160    /* SCO clean up here */
161    bta_dm_sco_co_close();
162#endif
163
164    /* Restore settings */
165    if (bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC) {
166      /* Bypass vendor specific and voice settings if enhanced eSCO supported */
167      if (!(controller_get_interface()
168                ->supports_enhanced_setup_synchronous_connection())) {
169        BTM_WriteVoiceSettings(BTM_VOICE_SETTING_CVSD);
170      }
171
172      /* If SCO open was initiated by AG and failed for mSBC T2, try mSBC T1
173       * 'Safe setting' first. If T1 also fails, try CVSD */
174      if (bta_ag_sco_is_opening(bta_ag_cb.sco.p_curr_scb)) {
175        bta_ag_cb.sco.p_curr_scb->state = BTA_AG_SCO_CODEC_ST;
176        if (bta_ag_cb.sco.p_curr_scb->codec_msbc_settings ==
177            BTA_AG_SCO_MSBC_SETTINGS_T2) {
178          APPL_TRACE_WARNING(
179              "%s: eSCO/SCO failed to open, falling back to mSBC T1 settings",
180              __func__);
181          bta_ag_cb.sco.p_curr_scb->codec_msbc_settings =
182              BTA_AG_SCO_MSBC_SETTINGS_T1;
183        } else {
184          APPL_TRACE_WARNING(
185              "%s: eSCO/SCO failed to open, falling back to CVSD", __func__);
186          bta_ag_cb.sco.p_curr_scb->codec_fallback = true;
187        }
188      }
189    } else if (bta_ag_sco_is_opening(bta_ag_cb.sco.p_curr_scb)) {
190      APPL_TRACE_ERROR("%s: eSCO/SCO failed to open, no more fall back",
191                       __func__);
192    }
193
194    bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
195
196    BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
197    p_buf->event = BTA_AG_SCO_CLOSE_EVT;
198    p_buf->layer_specific = handle;
199    bta_sys_sendmsg(p_buf);
200  } else {
201    /* no match found */
202    APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback");
203
204    /* sco could be closed after scb dealloc'ed */
205    if (bta_ag_cb.sco.p_curr_scb != NULL) {
206      bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
207      bta_ag_cb.sco.p_curr_scb = NULL;
208      bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
209    }
210  }
211}
212#if (BTM_SCO_HCI_INCLUDED == TRUE)
213/*******************************************************************************
214 *
215 * Function         bta_ag_sco_read_cback
216 *
217 * Description      Callback function is the callback function for incoming
218 *                  SCO data over HCI.
219 *
220 * Returns          void
221 *
222 ******************************************************************************/
223static void bta_ag_sco_read_cback(uint16_t sco_inx, BT_HDR* p_data,
224                                  tBTM_SCO_DATA_FLAG status) {
225  if (status != BTM_SCO_DATA_CORRECT) {
226    APPL_TRACE_DEBUG("%s: status %d", __func__, status);
227  }
228
229  /* Callout function must free the data. */
230  bta_dm_sco_co_in_data(p_data, status);
231}
232#endif
233/*******************************************************************************
234 *
235 * Function         bta_ag_remove_sco
236 *
237 * Description      Removes the specified SCO from the system.
238 *                  If only_active is true, then SCO is only removed if
239 *                  connected
240 *
241 * Returns          bool   - true if SCO removal was started
242 *
243 ******************************************************************************/
244static bool bta_ag_remove_sco(tBTA_AG_SCB* p_scb, bool only_active) {
245  if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) {
246    if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx) {
247      tBTM_STATUS status = BTM_RemoveSco(p_scb->sco_idx);
248      APPL_TRACE_DEBUG("%s: SCO index 0x%04x, status %d", __func__,
249                       p_scb->sco_idx, status);
250      if (status == BTM_CMD_STARTED) {
251        /* SCO is connected; set current control block */
252        bta_ag_cb.sco.p_curr_scb = p_scb;
253        return true;
254      } else if ((status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR)) {
255        /* If no connection reset the SCO handle */
256        p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
257      }
258    }
259  }
260  return false;
261}
262
263/*******************************************************************************
264 *
265 * Function         bta_ag_esco_connreq_cback
266 *
267 * Description      BTM eSCO connection requests and eSCO change requests
268 *                  Only the connection requests are processed by BTA.
269 *
270 * Returns          void
271 *
272 ******************************************************************************/
273static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event,
274                                      tBTM_ESCO_EVT_DATA* p_data) {
275  tBTA_AG_SCB* p_scb;
276  uint16_t handle;
277  uint16_t sco_inx = p_data->conn_evt.sco_inx;
278
279  /* Only process connection requests */
280  if (event == BTM_ESCO_CONN_REQ_EVT) {
281    if ((handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_inx))) != 0 &&
282        ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) && p_scb->svc_conn) {
283      p_scb->sco_idx = sco_inx;
284
285      /* If no other SCO active, allow this one */
286      if (!bta_ag_cb.sco.p_curr_scb) {
287        APPL_TRACE_EVENT("%s: Accept Conn Request (sco_inx 0x%04x)", __func__,
288                         sco_inx);
289        bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
290
291        bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST;
292        bta_ag_cb.sco.p_curr_scb = p_scb;
293        bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
294      } else {
295        /* Begin a transfer: Close current SCO before responding */
296        APPL_TRACE_DEBUG("bta_ag_esco_connreq_cback: Begin XFER");
297        bta_ag_cb.sco.p_xfer_scb = p_scb;
298        bta_ag_cb.sco.conn_data = p_data->conn_evt;
299        bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST;
300
301        if (!bta_ag_remove_sco(bta_ag_cb.sco.p_curr_scb, true)) {
302          APPL_TRACE_ERROR(
303              "%s: Nothing to remove,so accept Conn Request(sco_inx 0x%04x)",
304              __func__, sco_inx);
305          bta_ag_cb.sco.p_xfer_scb = NULL;
306          bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST;
307
308          bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
309        }
310      }
311    } else {
312      /* If error occurred send reject response immediately */
313      APPL_TRACE_WARNING(
314          "no scb for bta_ag_esco_connreq_cback or no resources");
315      BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES,
316                      (enh_esco_params_t*)NULL);
317    }
318  } else if (event == BTM_ESCO_CHG_EVT) {
319    /* Received a change in the esco link */
320    APPL_TRACE_EVENT(
321        "%s: eSCO change event (inx %d): rtrans %d, "
322        "rxlen %d, txlen %d, txint %d",
323        __func__, p_data->chg_evt.sco_inx, p_data->chg_evt.retrans_window,
324        p_data->chg_evt.rx_pkt_len, p_data->chg_evt.tx_pkt_len,
325        p_data->chg_evt.tx_interval);
326  }
327}
328
329/*******************************************************************************
330 *
331 * Function         bta_ag_cback_sco
332 *
333 * Description      Call application callback function with SCO event.
334 *
335 *
336 * Returns          void
337 *
338 ******************************************************************************/
339static void bta_ag_cback_sco(tBTA_AG_SCB* p_scb, uint8_t event) {
340  tBTA_AG_HDR sco;
341
342  sco.handle = bta_ag_scb_to_idx(p_scb);
343  sco.app_id = p_scb->app_id;
344
345  /* call close cback */
346  (*bta_ag_cb.p_cback)(event, (tBTA_AG*)&sco);
347}
348
349/*******************************************************************************
350 *
351 * Function         bta_ag_create_sco
352 *
353 * Description      Create a SCO connection for a given control block
354 *                  p_scb : Pointer to the target AG control block
355 *                  is_orig : Whether to initiate or listen for SCO connection
356 *
357 * Returns          void
358 *
359 ******************************************************************************/
360static void bta_ag_create_sco(tBTA_AG_SCB* p_scb, bool is_orig) {
361  APPL_TRACE_DEBUG(
362      "%s: BEFORE codec_updated=%d, codec_fallback=%d, "
363      "sco_codec=%d, peer_codec=%d, msbc_settings=%d",
364      __func__, p_scb->codec_updated, p_scb->codec_fallback, p_scb->sco_codec,
365      p_scb->peer_codecs, p_scb->codec_msbc_settings);
366  tBTA_AG_PEER_CODEC esco_codec = BTA_AG_CODEC_CVSD;
367
368  /* Make sure this SCO handle is not already in use */
369  if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) {
370    APPL_TRACE_ERROR("%s: Index 0x%04x already in use!", __func__,
371                     p_scb->sco_idx);
372    return;
373  }
374
375  if ((p_scb->sco_codec == BTA_AG_CODEC_MSBC) && !p_scb->codec_fallback)
376    esco_codec = BTA_AG_CODEC_MSBC;
377
378  if (p_scb->codec_fallback) {
379    p_scb->codec_fallback = false;
380    /* Force AG to send +BCS for the next audio connection. */
381    p_scb->codec_updated = true;
382    /* Reset mSBC settings to T2 for the next audio connection */
383    p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
384  }
385
386  esco_codec_t codec_index = ESCO_CODEC_CVSD;
387  /* If WBS included, use CVSD by default, index is 0 for CVSD by
388   * initialization. If eSCO codec is mSBC, index is T2 or T1 */
389  if (esco_codec == BTA_AG_CODEC_MSBC) {
390    if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) {
391      codec_index = ESCO_CODEC_MSBC_T2;
392    } else {
393      codec_index = ESCO_CODEC_MSBC_T1;
394    }
395  }
396
397  /* Initialize eSCO parameters */
398  enh_esco_params_t params = esco_parameters_for_codec(codec_index);
399  /* For CVSD */
400  if (esco_codec == BTM_SCO_CODEC_CVSD) {
401    /* Use the applicable packet types
402      (3-EV3 not allowed due to errata 2363) */
403    params.packet_types =
404        p_bta_ag_cfg->sco_pkt_types | ESCO_PKT_TYPES_MASK_NO_3_EV3;
405    if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
406        (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
407      params.max_latency_ms = 10;
408      params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
409    }
410  }
411
412  /* If initiating, setup parameters to start SCO/eSCO connection */
413  if (is_orig) {
414    bta_ag_cb.sco.is_local = true;
415    /* Set eSCO Mode */
416    BTM_SetEScoMode(&params);
417    bta_ag_cb.sco.p_curr_scb = p_scb;
418    /* save the current codec as sco_codec can be updated while SCO is open. */
419    p_scb->inuse_codec = esco_codec;
420
421    /* tell sys to stop av if any */
422    bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
423
424    /* Send pending commands to create SCO connection to peer */
425    bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
426  } else {
427    /* Not initiating, go to listen mode */
428    tBTM_STATUS status = BTM_CreateSco(
429        &p_scb->peer_addr, false, params.packet_types, &p_scb->sco_idx,
430        bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
431    if (status == BTM_CMD_STARTED)
432      BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
433
434    APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
435                   __func__, is_orig, p_scb->sco_idx, status,
436                   params.packet_types);
437  }
438  APPL_TRACE_DEBUG(
439      "%s: AFTER codec_updated=%d, codec_fallback=%d, "
440      "sco_codec=%d, peer_codec=%d, msbc_settings=%d",
441      __func__, p_scb->codec_updated, p_scb->codec_fallback, p_scb->sco_codec,
442      p_scb->peer_codecs, p_scb->codec_msbc_settings);
443}
444
445/*******************************************************************************
446 *
447 * Function         bta_ag_create_pending_sco
448 *
449 * Description      This Function is called after the pre-SCO vendor setup is
450 *                  done for the BTA to continue and send the HCI Commands for
451 *                  creating/accepting SCO connection with peer based on the
452 *                  is_local parameter.
453 *
454 * Returns          void
455 *
456 ******************************************************************************/
457static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local) {
458  tBTA_AG_PEER_CODEC esco_codec = p_scb->inuse_codec;
459  enh_esco_params_t params;
460  bta_ag_cb.sco.p_curr_scb = p_scb;
461  bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
462
463  /* Local device requested SCO connection to peer */
464  if (is_local) {
465    if (esco_codec == BTA_AG_CODEC_MSBC) {
466      if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) {
467        params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T2);
468      } else
469        params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T1);
470    } else {
471      params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
472      if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
473          (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
474        params.max_latency_ms = 10;
475        params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
476      }
477    }
478
479    /* Bypass voice settings if enhanced SCO setup command is supported */
480    if (!(controller_get_interface()
481              ->supports_enhanced_setup_synchronous_connection())) {
482      if (esco_codec == BTA_AG_CODEC_MSBC)
483        BTM_WriteVoiceSettings(BTM_VOICE_SETTING_TRANS);
484      else
485        BTM_WriteVoiceSettings(BTM_VOICE_SETTING_CVSD);
486    }
487
488#if (BTM_SCO_HCI_INCLUDED == TRUE)
489    /* initialize SCO setup, no voice setting for AG, data rate <==> sample
490     * rate */
491    BTM_ConfigScoPath(params.input_data_path, bta_ag_sco_read_cback, NULL,
492                      TRUE);
493#endif
494
495    tBTM_STATUS status = BTM_CreateSco(
496        &p_scb->peer_addr, true, params.packet_types, &p_scb->sco_idx,
497        bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
498    if (status == BTM_CMD_STARTED) {
499      /* Initiating the connection, set the current sco handle */
500      bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
501    }
502  } else {
503    /* Local device accepted SCO connection from peer */
504    params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
505    if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
506        (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
507      params.max_latency_ms = 10;
508      params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
509    }
510
511    BTM_EScoConnRsp(p_scb->sco_idx, HCI_SUCCESS, &params);
512  }
513}
514
515/*******************************************************************************
516 *
517 * Function         bta_ag_codec_negotiation_timer_cback
518 *
519 * Description
520 *
521 *
522 * Returns          void
523 *
524 ******************************************************************************/
525static void bta_ag_codec_negotiation_timer_cback(void* data) {
526  APPL_TRACE_DEBUG("%s", __func__);
527  tBTA_AG_SCB* p_scb = (tBTA_AG_SCB*)data;
528
529  /* Announce that codec negotiation failed. */
530  bta_ag_sco_codec_nego(p_scb, false);
531
532  /* call app callback */
533  bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
534}
535
536/*******************************************************************************
537 *
538 * Function         bta_ag_codec_negotiate
539 *
540 * Description      Initiate codec negotiation by sending AT command.
541 *                  If not necessary, skip negotiation.
542 *
543 * Returns          void
544 *
545 ******************************************************************************/
546void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb) {
547  APPL_TRACE_DEBUG("%s", __func__);
548  bta_ag_cb.sco.p_curr_scb = p_scb;
549
550  if ((p_scb->codec_updated || p_scb->codec_fallback) &&
551      (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
552    /* Change the power mode to Active until SCO open is completed. */
553    bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
554
555    /* Send +BCS to the peer */
556    bta_ag_send_bcs(p_scb, NULL);
557
558    /* Start timer to handle timeout */
559    alarm_set_on_mloop(p_scb->codec_negotiation_timer,
560                       BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS,
561                       bta_ag_codec_negotiation_timer_cback, p_scb);
562  } else {
563    /* use same codec type as previous SCO connection, skip codec negotiation */
564    APPL_TRACE_DEBUG(
565        "use same codec type as previous SCO connection,skip codec "
566        "negotiation");
567    bta_ag_sco_codec_nego(p_scb, true);
568  }
569}
570
571/*******************************************************************************
572 *
573 * Function         bta_ag_sco_event
574 *
575 * Description
576 *
577 *
578 * Returns          void
579 *
580 ******************************************************************************/
581static void bta_ag_sco_event(tBTA_AG_SCB* p_scb, uint8_t event) {
582  tBTA_AG_SCO_CB* p_sco = &bta_ag_cb.sco;
583#if (BTM_SCO_HCI_INCLUDED == TRUE)
584  BT_HDR* p_buf;
585#endif
586
587#if (BTA_AG_SCO_DEBUG == TRUE)
588  uint8_t in_state = p_sco->state;
589
590  if (event != BTA_AG_SCO_CI_DATA_E) {
591    APPL_TRACE_EVENT("%s: SCO Index 0x%04x, State %d (%s), Event %d (%s)",
592                     __func__, p_scb->sco_idx, p_sco->state,
593                     bta_ag_sco_state_str(p_sco->state), event,
594                     bta_ag_sco_evt_str(event));
595  }
596#else
597  if (event != BTA_AG_SCO_CI_DATA_E) {
598    APPL_TRACE_EVENT("%s: SCO Index 0x%04x, State %d, Event %d", __func__,
599                     p_scb->sco_idx, p_sco->state, event);
600  }
601#endif
602
603#if (BTM_SCO_HCI_INCLUDED == TRUE)
604  if (event == BTA_AG_SCO_CI_DATA_E) {
605    while (true) {
606      bta_dm_sco_co_out_data(&p_buf);
607      if (p_buf) {
608        if (p_sco->state == BTA_AG_SCO_OPEN_ST)
609          BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf);
610        else
611          osi_free(p_buf);
612      } else
613        break;
614    }
615
616    return;
617  }
618#endif
619
620  switch (p_sco->state) {
621    case BTA_AG_SCO_SHUTDOWN_ST:
622      switch (event) {
623        case BTA_AG_SCO_LISTEN_E:
624          /* create sco listen connection */
625          bta_ag_create_sco(p_scb, false);
626          p_sco->state = BTA_AG_SCO_LISTEN_ST;
627          break;
628
629        default:
630          APPL_TRACE_WARNING("%s: BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d",
631                             __func__, event);
632          break;
633      }
634      break;
635
636    case BTA_AG_SCO_LISTEN_ST:
637      switch (event) {
638        case BTA_AG_SCO_LISTEN_E:
639          /* create sco listen connection (Additional channel) */
640          bta_ag_create_sco(p_scb, false);
641          break;
642
643        case BTA_AG_SCO_OPEN_E:
644          /* remove listening connection */
645          bta_ag_remove_sco(p_scb, false);
646
647          /* start codec negotiation */
648          p_sco->state = BTA_AG_SCO_CODEC_ST;
649          bta_ag_codec_negotiate(p_scb);
650          break;
651
652        case BTA_AG_SCO_SHUTDOWN_E:
653          /* remove listening connection */
654          bta_ag_remove_sco(p_scb, false);
655
656          if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = NULL;
657
658          /* If last SCO instance then finish shutting down */
659          if (!bta_ag_other_scb_open(p_scb)) {
660            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
661          }
662          break;
663
664        case BTA_AG_SCO_CLOSE_E:
665          /* remove listening connection */
666          /* Ignore the event. Keep listening SCO for the active SLC
667           */
668          APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %d",
669                             __func__, event);
670          break;
671
672        case BTA_AG_SCO_CONN_CLOSE_E:
673          /* sco failed; create sco listen connection */
674          bta_ag_create_sco(p_scb, false);
675          p_sco->state = BTA_AG_SCO_LISTEN_ST;
676          break;
677
678        default:
679          APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %d",
680                             __func__, event);
681          break;
682      }
683      break;
684
685    case BTA_AG_SCO_CODEC_ST:
686      switch (event) {
687        case BTA_AG_SCO_LISTEN_E:
688          /* create sco listen connection (Additional channel) */
689          bta_ag_create_sco(p_scb, false);
690          break;
691
692        case BTA_AG_SCO_CN_DONE_E:
693          /* create sco connection to peer */
694          bta_ag_create_sco(p_scb, true);
695          p_sco->state = BTA_AG_SCO_OPENING_ST;
696          break;
697
698        case BTA_AG_SCO_XFER_E:
699          /* save xfer scb */
700          p_sco->p_xfer_scb = p_scb;
701          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
702          break;
703
704        case BTA_AG_SCO_SHUTDOWN_E:
705          /* remove listening connection */
706          bta_ag_remove_sco(p_scb, false);
707
708          if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = NULL;
709
710          /* If last SCO instance then finish shutting down */
711          if (!bta_ag_other_scb_open(p_scb)) {
712            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
713          }
714          break;
715
716        case BTA_AG_SCO_CLOSE_E:
717          /* sco open is not started yet. just go back to listening */
718          p_sco->state = BTA_AG_SCO_LISTEN_ST;
719          break;
720
721        case BTA_AG_SCO_CONN_CLOSE_E:
722          /* sco failed; create sco listen connection */
723          bta_ag_create_sco(p_scb, false);
724          p_sco->state = BTA_AG_SCO_LISTEN_ST;
725          break;
726
727        default:
728          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CODEC_ST: Ignoring event %d",
729                             __func__, event);
730          break;
731      }
732      break;
733
734    case BTA_AG_SCO_OPENING_ST:
735      switch (event) {
736        case BTA_AG_SCO_LISTEN_E:
737          /* second headset has now joined */
738          /* create sco listen connection (Additional channel) */
739          if (p_scb != p_sco->p_curr_scb) {
740            bta_ag_create_sco(p_scb, false);
741          }
742          break;
743
744        case BTA_AG_SCO_REOPEN_E:
745          /* start codec negotiation */
746          p_sco->state = BTA_AG_SCO_CODEC_ST;
747          bta_ag_codec_negotiate(p_scb);
748          break;
749
750        case BTA_AG_SCO_XFER_E:
751          /* save xfer scb */
752          p_sco->p_xfer_scb = p_scb;
753          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
754          break;
755
756        case BTA_AG_SCO_CLOSE_E:
757          p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
758          break;
759
760        case BTA_AG_SCO_SHUTDOWN_E:
761          /* If not opening scb, just close it */
762          if (p_scb != p_sco->p_curr_scb) {
763            /* remove listening connection */
764            bta_ag_remove_sco(p_scb, false);
765          } else
766            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
767
768          break;
769
770        case BTA_AG_SCO_CONN_OPEN_E:
771          p_sco->state = BTA_AG_SCO_OPEN_ST;
772          break;
773
774        case BTA_AG_SCO_CONN_CLOSE_E:
775          /* sco failed; create sco listen connection */
776          bta_ag_create_sco(p_scb, false);
777          p_sco->state = BTA_AG_SCO_LISTEN_ST;
778          break;
779
780        default:
781          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPENING_ST: Ignoring event %d",
782                             __func__, event);
783          break;
784      }
785      break;
786
787    case BTA_AG_SCO_OPEN_CL_ST:
788      switch (event) {
789        case BTA_AG_SCO_XFER_E:
790          /* save xfer scb */
791          p_sco->p_xfer_scb = p_scb;
792
793          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
794          break;
795
796        case BTA_AG_SCO_OPEN_E:
797          p_sco->state = BTA_AG_SCO_OPENING_ST;
798          break;
799
800        case BTA_AG_SCO_SHUTDOWN_E:
801          /* If not opening scb, just close it */
802          if (p_scb != p_sco->p_curr_scb) {
803            /* remove listening connection */
804            bta_ag_remove_sco(p_scb, false);
805          } else
806            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
807
808          break;
809
810        case BTA_AG_SCO_CONN_OPEN_E:
811          /* close sco connection */
812          bta_ag_remove_sco(p_scb, true);
813
814          p_sco->state = BTA_AG_SCO_CLOSING_ST;
815          break;
816
817        case BTA_AG_SCO_CONN_CLOSE_E:
818          /* sco failed; create sco listen connection */
819
820          p_sco->state = BTA_AG_SCO_LISTEN_ST;
821          break;
822
823        default:
824          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d",
825                             __func__, event);
826          break;
827      }
828      break;
829
830    case BTA_AG_SCO_OPEN_XFER_ST:
831      switch (event) {
832        case BTA_AG_SCO_CLOSE_E:
833          /* close sco connection */
834          bta_ag_remove_sco(p_scb, true);
835
836          p_sco->state = BTA_AG_SCO_CLOSING_ST;
837          break;
838
839        case BTA_AG_SCO_SHUTDOWN_E:
840          /* remove all connection */
841          bta_ag_remove_sco(p_scb, false);
842          p_sco->state = BTA_AG_SCO_SHUTTING_ST;
843
844          break;
845
846        case BTA_AG_SCO_CONN_CLOSE_E:
847          /* closed sco; place in listen mode and
848             accept the transferred connection */
849          bta_ag_create_sco(p_scb, false); /* Back into listen mode */
850
851          /* Accept sco connection with xfer scb */
852          bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
853          p_sco->state = BTA_AG_SCO_OPENING_ST;
854          p_sco->p_curr_scb = p_sco->p_xfer_scb;
855          p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
856          p_sco->p_xfer_scb = NULL;
857          break;
858
859        default:
860          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d",
861                             __func__, event);
862          break;
863      }
864      break;
865
866    case BTA_AG_SCO_OPEN_ST:
867      switch (event) {
868        case BTA_AG_SCO_LISTEN_E:
869          /* second headset has now joined */
870          /* create sco listen connection (Additional channel) */
871          if (p_scb != p_sco->p_curr_scb) {
872            bta_ag_create_sco(p_scb, false);
873          }
874          break;
875
876        case BTA_AG_SCO_XFER_E:
877          /* close current sco connection */
878          bta_ag_remove_sco(p_sco->p_curr_scb, true);
879
880          /* save xfer scb */
881          p_sco->p_xfer_scb = p_scb;
882
883          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
884          break;
885
886        case BTA_AG_SCO_CLOSE_E:
887          /* close sco connection if active */
888          if (bta_ag_remove_sco(p_scb, true)) {
889            p_sco->state = BTA_AG_SCO_CLOSING_ST;
890          }
891          break;
892
893        case BTA_AG_SCO_SHUTDOWN_E:
894          /* remove all listening connections */
895          bta_ag_remove_sco(p_scb, false);
896
897          /* If SCO was active on this scb, close it */
898          if (p_scb == p_sco->p_curr_scb) {
899            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
900          }
901          break;
902
903        case BTA_AG_SCO_CONN_CLOSE_E:
904          /* peer closed sco; create sco listen connection */
905          bta_ag_create_sco(p_scb, false);
906          p_sco->state = BTA_AG_SCO_LISTEN_ST;
907          break;
908
909        default:
910          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_ST: Ignoring event %d",
911                             __func__, event);
912          break;
913      }
914      break;
915
916    case BTA_AG_SCO_CLOSING_ST:
917      switch (event) {
918        case BTA_AG_SCO_LISTEN_E:
919          /* create sco listen connection (Additional channel) */
920          if (p_scb != p_sco->p_curr_scb) {
921            bta_ag_create_sco(p_scb, false);
922          }
923          break;
924
925        case BTA_AG_SCO_OPEN_E:
926          p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
927          break;
928
929        case BTA_AG_SCO_XFER_E:
930          /* save xfer scb */
931          p_sco->p_xfer_scb = p_scb;
932
933          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
934          break;
935
936        case BTA_AG_SCO_SHUTDOWN_E:
937          /* If not closing scb, just close it */
938          if (p_scb != p_sco->p_curr_scb) {
939            /* remove listening connection */
940            bta_ag_remove_sco(p_scb, false);
941          } else
942            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
943
944          break;
945
946        case BTA_AG_SCO_CONN_CLOSE_E:
947          /* peer closed sco; create sco listen connection */
948          bta_ag_create_sco(p_scb, false);
949
950          p_sco->state = BTA_AG_SCO_LISTEN_ST;
951          break;
952
953        default:
954          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSING_ST: Ignoring event %d",
955                             __func__, event);
956          break;
957      }
958      break;
959
960    case BTA_AG_SCO_CLOSE_OP_ST:
961      switch (event) {
962        case BTA_AG_SCO_CLOSE_E:
963          p_sco->state = BTA_AG_SCO_CLOSING_ST;
964          break;
965
966        case BTA_AG_SCO_SHUTDOWN_E:
967          p_sco->state = BTA_AG_SCO_SHUTTING_ST;
968          break;
969
970        case BTA_AG_SCO_CONN_CLOSE_E:
971          /* start codec negotiation */
972          p_sco->state = BTA_AG_SCO_CODEC_ST;
973          bta_ag_codec_negotiate(p_scb);
974          break;
975
976        case BTA_AG_SCO_LISTEN_E:
977          /* create sco listen connection (Additional channel) */
978          if (p_scb != p_sco->p_curr_scb) {
979            bta_ag_create_sco(p_scb, false);
980          }
981          break;
982
983        default:
984          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d",
985                             __func__, event);
986          break;
987      }
988      break;
989
990    case BTA_AG_SCO_CLOSE_XFER_ST:
991      switch (event) {
992        case BTA_AG_SCO_CONN_OPEN_E:
993          /* close sco connection so headset can be transferred
994             Probably entered this state from "opening state" */
995          bta_ag_remove_sco(p_scb, true);
996          break;
997
998        case BTA_AG_SCO_CLOSE_E:
999          /* clear xfer scb */
1000          p_sco->p_xfer_scb = NULL;
1001
1002          p_sco->state = BTA_AG_SCO_CLOSING_ST;
1003          break;
1004
1005        case BTA_AG_SCO_SHUTDOWN_E:
1006          /* clear xfer scb */
1007          p_sco->p_xfer_scb = NULL;
1008
1009          p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1010          break;
1011
1012        case BTA_AG_SCO_CONN_CLOSE_E: {
1013          /* closed sco; place old sco in listen mode,
1014             take current sco out of listen, and
1015             create originating sco for current */
1016          bta_ag_create_sco(p_scb, false);
1017          bta_ag_remove_sco(p_sco->p_xfer_scb, false);
1018
1019          /* start codec negotiation */
1020          p_sco->state = BTA_AG_SCO_CODEC_ST;
1021          tBTA_AG_SCB* p_cn_scb = p_sco->p_xfer_scb;
1022          p_sco->p_xfer_scb = NULL;
1023          bta_ag_codec_negotiate(p_cn_scb);
1024          break;
1025        }
1026
1027        default:
1028          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d",
1029                             __func__, event);
1030          break;
1031      }
1032      break;
1033
1034    case BTA_AG_SCO_SHUTTING_ST:
1035      switch (event) {
1036        case BTA_AG_SCO_CONN_OPEN_E:
1037          /* close sco connection; wait for conn close event */
1038          bta_ag_remove_sco(p_scb, true);
1039          break;
1040
1041        case BTA_AG_SCO_CONN_CLOSE_E:
1042          /* If last SCO instance then finish shutting down */
1043          if (!bta_ag_other_scb_open(p_scb)) {
1044            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1045          } else /* Other instance is still listening */
1046          {
1047            p_sco->state = BTA_AG_SCO_LISTEN_ST;
1048          }
1049
1050          /* If SCO closed for other HS which is not being disconnected,
1051             then create listen sco connection for it as scb still open */
1052          if (bta_ag_scb_open(p_scb)) {
1053            bta_ag_create_sco(p_scb, false);
1054            p_sco->state = BTA_AG_SCO_LISTEN_ST;
1055          }
1056
1057          if (p_scb == p_sco->p_curr_scb) {
1058            p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1059            p_sco->p_curr_scb = NULL;
1060          }
1061          break;
1062
1063        case BTA_AG_SCO_LISTEN_E:
1064          /* create sco listen connection (Additional channel) */
1065          if (p_scb != p_sco->p_curr_scb) {
1066            bta_ag_create_sco(p_scb, false);
1067          }
1068          break;
1069
1070        case BTA_AG_SCO_SHUTDOWN_E:
1071          if (!bta_ag_other_scb_open(p_scb)) {
1072            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1073          } else /* Other instance is still listening */
1074          {
1075            p_sco->state = BTA_AG_SCO_LISTEN_ST;
1076          }
1077
1078          if (p_scb == p_sco->p_curr_scb) {
1079            p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1080            p_sco->p_curr_scb = NULL;
1081          }
1082          break;
1083
1084        default:
1085          APPL_TRACE_WARNING("%s: BTA_AG_SCO_SHUTTING_ST: Ignoring event %d",
1086                             __func__, event);
1087          break;
1088      }
1089      break;
1090
1091    default:
1092      break;
1093  }
1094#if (BTA_AG_SCO_DEBUG == TRUE)
1095  if (p_sco->state != in_state) {
1096    APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
1097                     bta_ag_sco_state_str(in_state),
1098                     bta_ag_sco_state_str(p_sco->state),
1099                     bta_ag_sco_evt_str(event));
1100  }
1101#endif
1102}
1103
1104/*******************************************************************************
1105 *
1106 * Function         bta_ag_sco_is_open
1107 *
1108 * Description      Check if sco is open for this scb.
1109 *
1110 *
1111 * Returns          true if sco open for this scb, false otherwise.
1112 *
1113 ******************************************************************************/
1114bool bta_ag_sco_is_open(tBTA_AG_SCB* p_scb) {
1115  return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
1116          (bta_ag_cb.sco.p_curr_scb == p_scb));
1117}
1118
1119/*******************************************************************************
1120 *
1121 * Function         bta_ag_sco_is_opening
1122 *
1123 * Description      Check if sco is in Opening state.
1124 *
1125 *
1126 * Returns          true if sco is in Opening state for this scb, false
1127 *                  otherwise.
1128 *
1129 ******************************************************************************/
1130bool bta_ag_sco_is_opening(tBTA_AG_SCB* p_scb) {
1131  return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
1132          (bta_ag_cb.sco.p_curr_scb == p_scb));
1133}
1134
1135/*******************************************************************************
1136 *
1137 * Function         bta_ag_sco_listen
1138 *
1139 * Description
1140 *
1141 *
1142 * Returns          void
1143 *
1144 ******************************************************************************/
1145void bta_ag_sco_listen(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1146  bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
1147}
1148
1149/*******************************************************************************
1150 *
1151 * Function         bta_ag_sco_open
1152 *
1153 * Description
1154 *
1155 *
1156 * Returns          void
1157 *
1158 ******************************************************************************/
1159void bta_ag_sco_open(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1160  uint8_t event;
1161
1162  if (!sco_allowed) {
1163    APPL_TRACE_DEBUG("%s not opening sco, by policy", __func__);
1164    return;
1165  }
1166
1167  /* if another scb using sco, this is a transfer */
1168  if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb) {
1169    event = BTA_AG_SCO_XFER_E;
1170  }
1171  /* else it is an open */
1172  else {
1173    event = BTA_AG_SCO_OPEN_E;
1174  }
1175
1176  bta_ag_sco_event(p_scb, event);
1177}
1178
1179/*******************************************************************************
1180 *
1181 * Function         bta_ag_sco_close
1182 *
1183 * Description
1184 *
1185 *
1186 * Returns          void
1187 *
1188 ******************************************************************************/
1189void bta_ag_sco_close(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1190/* if scb is in use */
1191  /* sco_idx is not allocated in SCO_CODEC_ST, still need to move to listen
1192   * state. */
1193  if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) ||
1194      (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
1195  {
1196    APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
1197    bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1198  }
1199}
1200
1201/*******************************************************************************
1202 *
1203 * Function         bta_ag_sco_codec_nego
1204 *
1205 * Description      Handles result of eSCO codec negotiation
1206 *
1207 *
1208 * Returns          void
1209 *
1210 ******************************************************************************/
1211void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result) {
1212  if (result == true) {
1213    /* Subsequent SCO connection will skip codec negotiation */
1214    APPL_TRACE_DEBUG("%s: Succeeded for index 0x%04x", __func__,
1215                     p_scb->sco_idx);
1216    p_scb->codec_updated = false;
1217    bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
1218  } else {
1219    /* codec negotiation failed */
1220    APPL_TRACE_ERROR("%s: Failed for index 0x%04x", __func__, p_scb->sco_idx);
1221    bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1222  }
1223}
1224
1225/*******************************************************************************
1226 *
1227 * Function         bta_ag_sco_shutdown
1228 *
1229 * Description
1230 *
1231 *
1232 * Returns          void
1233 *
1234 ******************************************************************************/
1235void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1236  bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
1237}
1238
1239/*******************************************************************************
1240 *
1241 * Function         bta_ag_sco_conn_open
1242 *
1243 * Description
1244 *
1245 *
1246 * Returns          void
1247 *
1248 ******************************************************************************/
1249void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb,
1250                          UNUSED_ATTR tBTA_AG_DATA* p_data) {
1251  bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
1252
1253  bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1254
1255#if (BTM_SCO_HCI_INCLUDED == TRUE)
1256  /* open SCO codec if SCO is routed through transport */
1257  bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE,
1258                     BTA_AG_CI_SCO_DATA_EVT);
1259#endif
1260
1261  /* call app callback */
1262  bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
1263
1264  /* reset to mSBC T2 settings as the preferred */
1265  p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1266}
1267
1268/*******************************************************************************
1269 *
1270 * Function         bta_ag_sco_conn_close
1271 *
1272 * Description
1273 *
1274 *
1275 * Returns          void
1276 *
1277 ******************************************************************************/
1278void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb,
1279                           UNUSED_ATTR tBTA_AG_DATA* p_data) {
1280  /* clear current scb */
1281  bta_ag_cb.sco.p_curr_scb = NULL;
1282  p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1283
1284  /* codec_fallback is set when AG is initiator and connection failed for mSBC.
1285   * OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */
1286  if (p_scb->svc_conn &&
1287      (p_scb->codec_fallback ||
1288       (p_scb->sco_codec == BTM_SCO_CODEC_MSBC &&
1289        p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1))) {
1290    bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
1291  } else {
1292    /* Indicate if the closing of audio is because of transfer */
1293    bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
1294
1295    bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1296
1297    /* if av got suspended by this call, let it resume. */
1298    /* In case call stays alive regardless of sco, av should not be affected. */
1299    if (((p_scb->call_ind == BTA_AG_CALL_INACTIVE) &&
1300         (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE)) ||
1301        (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)) {
1302      bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1303    }
1304
1305    /* call app callback */
1306    bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
1307    p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1308  }
1309}
1310
1311/*******************************************************************************
1312 *
1313 * Function         bta_ag_sco_conn_rsp
1314 *
1315 * Description      Process the SCO connection request
1316 *
1317 *
1318 * Returns          void
1319 *
1320 ******************************************************************************/
1321void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb,
1322                         tBTM_ESCO_CONN_REQ_EVT_DATA* p_data) {
1323  bta_ag_cb.sco.is_local = false;
1324
1325  APPL_TRACE_DEBUG("%s: eSCO %d, state %d", __func__,
1326                   controller_get_interface()
1327                       ->supports_enhanced_setup_synchronous_connection(),
1328                   bta_ag_cb.sco.state);
1329
1330  if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST ||
1331      bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
1332      bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST) {
1333    /* tell sys to stop av if any */
1334    bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1335    /* When HS initiated SCO, it cannot be WBS. */
1336#if (BTM_SCO_HCI_INCLUDED == TRUE)
1337    /* Configure the transport being used */
1338    BTM_ConfigScoPath(resp.input_data_path, bta_ag_sco_read_cback, NULL, TRUE);
1339#endif
1340  }
1341
1342  /* If SCO open was initiated from HS, it must be CVSD */
1343  p_scb->inuse_codec = BTA_AG_CODEC_NONE;
1344  /* Send pending commands to create SCO connection to peer */
1345  bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
1346}
1347
1348/*******************************************************************************
1349 *
1350 * Function         bta_ag_ci_sco_data
1351 *
1352 * Description      Process the SCO data ready callin event
1353 *
1354 *
1355 * Returns          void
1356 *
1357 ******************************************************************************/
1358void bta_ag_ci_sco_data(UNUSED_ATTR tBTA_AG_SCB* p_scb,
1359                        UNUSED_ATTR tBTA_AG_DATA* p_data) {
1360#if (BTM_SCO_HCI_INCLUDED == TRUE)
1361  bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
1362#endif
1363}
1364
1365void bta_ag_set_sco_allowed(tBTA_AG_DATA* p_data) {
1366  sco_allowed = ((tBTA_AG_API_SET_SCO_ALLOWED*)p_data)->value;
1367  APPL_TRACE_DEBUG(sco_allowed ? "sco now allowed" : "sco now not allowed");
1368}
1369
1370/*******************************************************************************
1371 *  Debugging functions
1372 ******************************************************************************/
1373
1374#if (BTA_AG_SCO_DEBUG == TRUE)
1375static char* bta_ag_sco_evt_str(uint8_t event) {
1376  switch (event) {
1377    case BTA_AG_SCO_LISTEN_E:
1378      return "Listen Request";
1379    case BTA_AG_SCO_OPEN_E:
1380      return "Open Request";
1381    case BTA_AG_SCO_XFER_E:
1382      return "Transfer Request";
1383    case BTA_AG_SCO_CN_DONE_E:
1384      return "Codec Negotiation Done";
1385    case BTA_AG_SCO_REOPEN_E:
1386      return "Reopen Request";
1387    case BTA_AG_SCO_CLOSE_E:
1388      return "Close Request";
1389    case BTA_AG_SCO_SHUTDOWN_E:
1390      return "Shutdown Request";
1391    case BTA_AG_SCO_CONN_OPEN_E:
1392      return "Opened";
1393    case BTA_AG_SCO_CONN_CLOSE_E:
1394      return "Closed";
1395    case BTA_AG_SCO_CI_DATA_E:
1396      return "Sco Data";
1397    default:
1398      return "Unknown SCO Event";
1399  }
1400}
1401
1402static char* bta_ag_sco_state_str(uint8_t state) {
1403  switch (state) {
1404    case BTA_AG_SCO_SHUTDOWN_ST:
1405      return "Shutdown";
1406    case BTA_AG_SCO_LISTEN_ST:
1407      return "Listening";
1408    case BTA_AG_SCO_CODEC_ST:
1409      return "Codec Negotiation";
1410    case BTA_AG_SCO_OPENING_ST:
1411      return "Opening";
1412    case BTA_AG_SCO_OPEN_CL_ST:
1413      return "Open while closing";
1414    case BTA_AG_SCO_OPEN_XFER_ST:
1415      return "Opening while Transferring";
1416    case BTA_AG_SCO_OPEN_ST:
1417      return "Open";
1418    case BTA_AG_SCO_CLOSING_ST:
1419      return "Closing";
1420    case BTA_AG_SCO_CLOSE_OP_ST:
1421      return "Close while Opening";
1422    case BTA_AG_SCO_CLOSE_XFER_ST:
1423      return "Close while Transferring";
1424    case BTA_AG_SCO_SHUTTING_ST:
1425      return "Shutting Down";
1426    default:
1427      return "Unknown SCO State";
1428  }
1429}
1430
1431#endif /* (BTA_AG_SCO_DEBUG) */
1432