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