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