bta_ag_sco.cc revision c752e135d66f80c0b2efc35292ab8ddfd8227d61
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    tBTM_STATUS status = BTM_CreateSco(
431        &p_scb->peer_addr, false, params.packet_types, &p_scb->sco_idx,
432        bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
433    if (status == BTM_CMD_STARTED)
434      BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
435
436    APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
437                   __func__, is_orig, p_scb->sco_idx, status,
438                   params.packet_types);
439  }
440  APPL_TRACE_DEBUG(
441      "%s: AFTER codec_updated=%d, codec_fallback=%d, "
442      "sco_codec=%d, peer_codec=%d, msbc_settings=%d",
443      __func__, p_scb->codec_updated, p_scb->codec_fallback, p_scb->sco_codec,
444      p_scb->peer_codecs, p_scb->codec_msbc_settings);
445}
446
447/*******************************************************************************
448 *
449 * Function         bta_ag_create_pending_sco
450 *
451 * Description      This Function is called after the pre-SCO vendor setup is
452 *                  done for the BTA to continue and send the HCI Commands for
453 *                  creating/accepting SCO connection with peer based on the
454 *                  is_local parameter.
455 *
456 * Returns          void
457 *
458 ******************************************************************************/
459static void bta_ag_create_pending_sco(tBTA_AG_SCB* p_scb, bool is_local) {
460  tBTA_AG_PEER_CODEC esco_codec = p_scb->inuse_codec;
461  enh_esco_params_t params;
462  bta_ag_cb.sco.p_curr_scb = p_scb;
463  bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
464
465  /* Local device requested SCO connection to peer */
466  if (is_local) {
467    if (esco_codec == BTA_AG_CODEC_MSBC) {
468      if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) {
469        params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T2);
470      } else
471        params = esco_parameters_for_codec(ESCO_CODEC_MSBC_T1);
472    } else {
473      params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
474      if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
475          (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
476        params.max_latency_ms = 10;
477        params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
478      }
479    }
480
481    /* Bypass voice settings if enhanced SCO setup command is supported */
482    if (!(controller_get_interface()
483              ->supports_enhanced_setup_synchronous_connection())) {
484      if (esco_codec == BTA_AG_CODEC_MSBC)
485        BTM_WriteVoiceSettings(BTM_VOICE_SETTING_TRANS);
486      else
487        BTM_WriteVoiceSettings(BTM_VOICE_SETTING_CVSD);
488    }
489
490#if (BTM_SCO_HCI_INCLUDED == TRUE)
491    /* initialize SCO setup, no voice setting for AG, data rate <==> sample
492     * rate */
493    BTM_ConfigScoPath(params.input_data_path, bta_ag_sco_read_cback, NULL,
494                      TRUE);
495#endif
496
497    tBTM_STATUS status = BTM_CreateSco(
498        &p_scb->peer_addr, true, params.packet_types, &p_scb->sco_idx,
499        bta_ag_sco_conn_cback, bta_ag_sco_disc_cback);
500    if (status == BTM_CMD_STARTED) {
501      /* Initiating the connection, set the current sco handle */
502      bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
503    }
504  } else {
505    /* Local device accepted SCO connection from peer */
506    params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
507    if ((!(p_scb->features & BTA_AG_FEAT_ESCO)) ||
508        (!(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO))) {
509      params.max_latency_ms = 10;
510      params.retransmission_effort = ESCO_RETRANSMISSION_POWER;
511    }
512
513    BTM_EScoConnRsp(p_scb->sco_idx, HCI_SUCCESS, &params);
514  }
515}
516
517/*******************************************************************************
518 *
519 * Function         bta_ag_codec_negotiation_timer_cback
520 *
521 * Description
522 *
523 *
524 * Returns          void
525 *
526 ******************************************************************************/
527static void bta_ag_codec_negotiation_timer_cback(void* data) {
528  APPL_TRACE_DEBUG("%s", __func__);
529  tBTA_AG_SCB* p_scb = (tBTA_AG_SCB*)data;
530
531  /* Announce that codec negotiation failed. */
532  bta_ag_sco_codec_nego(p_scb, false);
533
534  /* call app callback */
535  bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
536}
537
538/*******************************************************************************
539 *
540 * Function         bta_ag_codec_negotiate
541 *
542 * Description      Initiate codec negotiation by sending AT command.
543 *                  If not necessary, skip negotiation.
544 *
545 * Returns          void
546 *
547 ******************************************************************************/
548void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb) {
549  APPL_TRACE_DEBUG("%s", __func__);
550  bta_ag_cb.sco.p_curr_scb = p_scb;
551
552  if ((p_scb->codec_updated || p_scb->codec_fallback) &&
553      (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
554    /* Change the power mode to Active until SCO open is completed. */
555    bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
556
557    /* Send +BCS to the peer */
558    bta_ag_send_bcs(p_scb, NULL);
559
560    /* Start timer to handle timeout */
561    alarm_set_on_queue(
562        p_scb->codec_negotiation_timer, BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS,
563        bta_ag_codec_negotiation_timer_cback, p_scb, btu_bta_alarm_queue);
564  } else {
565    /* use same codec type as previous SCO connection, skip codec negotiation */
566    APPL_TRACE_DEBUG(
567        "use same codec type as previous SCO connection,skip codec "
568        "negotiation");
569    bta_ag_sco_codec_nego(p_scb, true);
570  }
571}
572
573/*******************************************************************************
574 *
575 * Function         bta_ag_sco_event
576 *
577 * Description
578 *
579 *
580 * Returns          void
581 *
582 ******************************************************************************/
583static void bta_ag_sco_event(tBTA_AG_SCB* p_scb, uint8_t event) {
584  tBTA_AG_SCO_CB* p_sco = &bta_ag_cb.sco;
585#if (BTM_SCO_HCI_INCLUDED == TRUE)
586  BT_HDR* p_buf;
587#endif
588
589#if (BTA_AG_SCO_DEBUG == TRUE)
590  uint8_t in_state = p_sco->state;
591
592  if (event != BTA_AG_SCO_CI_DATA_E) {
593    APPL_TRACE_EVENT("%s: SCO Index 0x%04x, State %d (%s), Event %d (%s)",
594                     __func__, p_scb->sco_idx, p_sco->state,
595                     bta_ag_sco_state_str(p_sco->state), event,
596                     bta_ag_sco_evt_str(event));
597  }
598#else
599  if (event != BTA_AG_SCO_CI_DATA_E) {
600    APPL_TRACE_EVENT("%s: SCO Index 0x%04x, State %d, Event %d", __func__,
601                     p_scb->sco_idx, p_sco->state, event);
602  }
603#endif
604
605#if (BTM_SCO_HCI_INCLUDED == TRUE)
606  if (event == BTA_AG_SCO_CI_DATA_E) {
607    while (true) {
608      bta_dm_sco_co_out_data(&p_buf);
609      if (p_buf) {
610        if (p_sco->state == BTA_AG_SCO_OPEN_ST)
611          BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf);
612        else
613          osi_free(p_buf);
614      } else
615        break;
616    }
617
618    return;
619  }
620#endif
621
622  switch (p_sco->state) {
623    case BTA_AG_SCO_SHUTDOWN_ST:
624      switch (event) {
625        case BTA_AG_SCO_LISTEN_E:
626          /* create sco listen connection */
627          bta_ag_create_sco(p_scb, false);
628          p_sco->state = BTA_AG_SCO_LISTEN_ST;
629          break;
630
631        default:
632          APPL_TRACE_WARNING("%s: BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d",
633                             __func__, event);
634          break;
635      }
636      break;
637
638    case BTA_AG_SCO_LISTEN_ST:
639      switch (event) {
640        case BTA_AG_SCO_LISTEN_E:
641          /* create sco listen connection (Additional channel) */
642          bta_ag_create_sco(p_scb, false);
643          break;
644
645        case BTA_AG_SCO_OPEN_E:
646          /* remove listening connection */
647          bta_ag_remove_sco(p_scb, false);
648
649          /* start codec negotiation */
650          p_sco->state = BTA_AG_SCO_CODEC_ST;
651          bta_ag_codec_negotiate(p_scb);
652          break;
653
654        case BTA_AG_SCO_SHUTDOWN_E:
655          /* remove listening connection */
656          bta_ag_remove_sco(p_scb, false);
657
658          if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = NULL;
659
660          /* If last SCO instance then finish shutting down */
661          if (!bta_ag_other_scb_open(p_scb)) {
662            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
663          }
664          break;
665
666        case BTA_AG_SCO_CLOSE_E:
667          /* remove listening connection */
668          /* Ignore the event. Keep listening SCO for the active SLC
669           */
670          APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %d",
671                             __func__, event);
672          break;
673
674        case BTA_AG_SCO_CONN_CLOSE_E:
675          /* sco failed; create sco listen connection */
676          bta_ag_create_sco(p_scb, false);
677          p_sco->state = BTA_AG_SCO_LISTEN_ST;
678          break;
679
680        default:
681          APPL_TRACE_WARNING("%s: BTA_AG_SCO_LISTEN_ST: Ignoring event %d",
682                             __func__, event);
683          break;
684      }
685      break;
686
687    case BTA_AG_SCO_CODEC_ST:
688      switch (event) {
689        case BTA_AG_SCO_LISTEN_E:
690          /* create sco listen connection (Additional channel) */
691          bta_ag_create_sco(p_scb, false);
692          break;
693
694        case BTA_AG_SCO_CN_DONE_E:
695          /* create sco connection to peer */
696          bta_ag_create_sco(p_scb, true);
697          p_sco->state = BTA_AG_SCO_OPENING_ST;
698          break;
699
700        case BTA_AG_SCO_XFER_E:
701          /* save xfer scb */
702          p_sco->p_xfer_scb = p_scb;
703          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
704          break;
705
706        case BTA_AG_SCO_SHUTDOWN_E:
707          /* remove listening connection */
708          bta_ag_remove_sco(p_scb, false);
709
710          if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = NULL;
711
712          /* If last SCO instance then finish shutting down */
713          if (!bta_ag_other_scb_open(p_scb)) {
714            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
715          }
716          break;
717
718        case BTA_AG_SCO_CLOSE_E:
719          /* sco open is not started yet. just go back to listening */
720          p_sco->state = BTA_AG_SCO_LISTEN_ST;
721          break;
722
723        case BTA_AG_SCO_CONN_CLOSE_E:
724          /* sco failed; create sco listen connection */
725          bta_ag_create_sco(p_scb, false);
726          p_sco->state = BTA_AG_SCO_LISTEN_ST;
727          break;
728
729        default:
730          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CODEC_ST: Ignoring event %d",
731                             __func__, event);
732          break;
733      }
734      break;
735
736    case BTA_AG_SCO_OPENING_ST:
737      switch (event) {
738        case BTA_AG_SCO_LISTEN_E:
739          /* second headset has now joined */
740          /* create sco listen connection (Additional channel) */
741          if (p_scb != p_sco->p_curr_scb) {
742            bta_ag_create_sco(p_scb, false);
743          }
744          break;
745
746        case BTA_AG_SCO_REOPEN_E:
747          /* start codec negotiation */
748          p_sco->state = BTA_AG_SCO_CODEC_ST;
749          bta_ag_codec_negotiate(p_scb);
750          break;
751
752        case BTA_AG_SCO_XFER_E:
753          /* save xfer scb */
754          p_sco->p_xfer_scb = p_scb;
755          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
756          break;
757
758        case BTA_AG_SCO_CLOSE_E:
759          p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
760          break;
761
762        case BTA_AG_SCO_SHUTDOWN_E:
763          /* If not opening scb, just close it */
764          if (p_scb != p_sco->p_curr_scb) {
765            /* remove listening connection */
766            bta_ag_remove_sco(p_scb, false);
767          } else
768            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
769
770          break;
771
772        case BTA_AG_SCO_CONN_OPEN_E:
773          p_sco->state = BTA_AG_SCO_OPEN_ST;
774          break;
775
776        case BTA_AG_SCO_CONN_CLOSE_E:
777          /* sco failed; create sco listen connection */
778          bta_ag_create_sco(p_scb, false);
779          p_sco->state = BTA_AG_SCO_LISTEN_ST;
780          break;
781
782        default:
783          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPENING_ST: Ignoring event %d",
784                             __func__, event);
785          break;
786      }
787      break;
788
789    case BTA_AG_SCO_OPEN_CL_ST:
790      switch (event) {
791        case BTA_AG_SCO_XFER_E:
792          /* save xfer scb */
793          p_sco->p_xfer_scb = p_scb;
794
795          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
796          break;
797
798        case BTA_AG_SCO_OPEN_E:
799          p_sco->state = BTA_AG_SCO_OPENING_ST;
800          break;
801
802        case BTA_AG_SCO_SHUTDOWN_E:
803          /* If not opening scb, just close it */
804          if (p_scb != p_sco->p_curr_scb) {
805            /* remove listening connection */
806            bta_ag_remove_sco(p_scb, false);
807          } else
808            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
809
810          break;
811
812        case BTA_AG_SCO_CONN_OPEN_E:
813          /* close sco connection */
814          bta_ag_remove_sco(p_scb, true);
815
816          p_sco->state = BTA_AG_SCO_CLOSING_ST;
817          break;
818
819        case BTA_AG_SCO_CONN_CLOSE_E:
820          /* sco failed; create sco listen connection */
821
822          p_sco->state = BTA_AG_SCO_LISTEN_ST;
823          break;
824
825        default:
826          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d",
827                             __func__, event);
828          break;
829      }
830      break;
831
832    case BTA_AG_SCO_OPEN_XFER_ST:
833      switch (event) {
834        case BTA_AG_SCO_CLOSE_E:
835          /* close sco connection */
836          bta_ag_remove_sco(p_scb, true);
837
838          p_sco->state = BTA_AG_SCO_CLOSING_ST;
839          break;
840
841        case BTA_AG_SCO_SHUTDOWN_E:
842          /* remove all connection */
843          bta_ag_remove_sco(p_scb, false);
844          p_sco->state = BTA_AG_SCO_SHUTTING_ST;
845
846          break;
847
848        case BTA_AG_SCO_CONN_CLOSE_E:
849          /* closed sco; place in listen mode and
850             accept the transferred connection */
851          bta_ag_create_sco(p_scb, false); /* Back into listen mode */
852
853          /* Accept sco connection with xfer scb */
854          bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
855          p_sco->state = BTA_AG_SCO_OPENING_ST;
856          p_sco->p_curr_scb = p_sco->p_xfer_scb;
857          p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
858          p_sco->p_xfer_scb = NULL;
859          break;
860
861        default:
862          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d",
863                             __func__, event);
864          break;
865      }
866      break;
867
868    case BTA_AG_SCO_OPEN_ST:
869      switch (event) {
870        case BTA_AG_SCO_LISTEN_E:
871          /* second headset has now joined */
872          /* create sco listen connection (Additional channel) */
873          if (p_scb != p_sco->p_curr_scb) {
874            bta_ag_create_sco(p_scb, false);
875          }
876          break;
877
878        case BTA_AG_SCO_XFER_E:
879          /* close current sco connection */
880          bta_ag_remove_sco(p_sco->p_curr_scb, true);
881
882          /* save xfer scb */
883          p_sco->p_xfer_scb = p_scb;
884
885          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
886          break;
887
888        case BTA_AG_SCO_CLOSE_E:
889          /* close sco connection if active */
890          if (bta_ag_remove_sco(p_scb, true)) {
891            p_sco->state = BTA_AG_SCO_CLOSING_ST;
892          }
893          break;
894
895        case BTA_AG_SCO_SHUTDOWN_E:
896          /* remove all listening connections */
897          bta_ag_remove_sco(p_scb, false);
898
899          /* If SCO was active on this scb, close it */
900          if (p_scb == p_sco->p_curr_scb) {
901            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
902          }
903          break;
904
905        case BTA_AG_SCO_CONN_CLOSE_E:
906          /* peer closed sco; create sco listen connection */
907          bta_ag_create_sco(p_scb, false);
908          p_sco->state = BTA_AG_SCO_LISTEN_ST;
909          break;
910
911        default:
912          APPL_TRACE_WARNING("%s: BTA_AG_SCO_OPEN_ST: Ignoring event %d",
913                             __func__, event);
914          break;
915      }
916      break;
917
918    case BTA_AG_SCO_CLOSING_ST:
919      switch (event) {
920        case BTA_AG_SCO_LISTEN_E:
921          /* create sco listen connection (Additional channel) */
922          if (p_scb != p_sco->p_curr_scb) {
923            bta_ag_create_sco(p_scb, false);
924          }
925          break;
926
927        case BTA_AG_SCO_OPEN_E:
928          p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
929          break;
930
931        case BTA_AG_SCO_XFER_E:
932          /* save xfer scb */
933          p_sco->p_xfer_scb = p_scb;
934
935          p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
936          break;
937
938        case BTA_AG_SCO_SHUTDOWN_E:
939          /* If not closing scb, just close it */
940          if (p_scb != p_sco->p_curr_scb) {
941            /* remove listening connection */
942            bta_ag_remove_sco(p_scb, false);
943          } else
944            p_sco->state = BTA_AG_SCO_SHUTTING_ST;
945
946          break;
947
948        case BTA_AG_SCO_CONN_CLOSE_E:
949          /* peer closed sco; create sco listen connection */
950          bta_ag_create_sco(p_scb, false);
951
952          p_sco->state = BTA_AG_SCO_LISTEN_ST;
953          break;
954
955        default:
956          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSING_ST: Ignoring event %d",
957                             __func__, event);
958          break;
959      }
960      break;
961
962    case BTA_AG_SCO_CLOSE_OP_ST:
963      switch (event) {
964        case BTA_AG_SCO_CLOSE_E:
965          p_sco->state = BTA_AG_SCO_CLOSING_ST;
966          break;
967
968        case BTA_AG_SCO_SHUTDOWN_E:
969          p_sco->state = BTA_AG_SCO_SHUTTING_ST;
970          break;
971
972        case BTA_AG_SCO_CONN_CLOSE_E:
973          /* start codec negotiation */
974          p_sco->state = BTA_AG_SCO_CODEC_ST;
975          bta_ag_codec_negotiate(p_scb);
976          break;
977
978        case BTA_AG_SCO_LISTEN_E:
979          /* create sco listen connection (Additional channel) */
980          if (p_scb != p_sco->p_curr_scb) {
981            bta_ag_create_sco(p_scb, false);
982          }
983          break;
984
985        default:
986          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d",
987                             __func__, event);
988          break;
989      }
990      break;
991
992    case BTA_AG_SCO_CLOSE_XFER_ST:
993      switch (event) {
994        case BTA_AG_SCO_CONN_OPEN_E:
995          /* close sco connection so headset can be transferred
996             Probably entered this state from "opening state" */
997          bta_ag_remove_sco(p_scb, true);
998          break;
999
1000        case BTA_AG_SCO_CLOSE_E:
1001          /* clear xfer scb */
1002          p_sco->p_xfer_scb = NULL;
1003
1004          p_sco->state = BTA_AG_SCO_CLOSING_ST;
1005          break;
1006
1007        case BTA_AG_SCO_SHUTDOWN_E:
1008          /* clear xfer scb */
1009          p_sco->p_xfer_scb = NULL;
1010
1011          p_sco->state = BTA_AG_SCO_SHUTTING_ST;
1012          break;
1013
1014        case BTA_AG_SCO_CONN_CLOSE_E: {
1015          /* closed sco; place old sco in listen mode,
1016             take current sco out of listen, and
1017             create originating sco for current */
1018          bta_ag_create_sco(p_scb, false);
1019          bta_ag_remove_sco(p_sco->p_xfer_scb, false);
1020
1021          /* start codec negotiation */
1022          p_sco->state = BTA_AG_SCO_CODEC_ST;
1023          tBTA_AG_SCB* p_cn_scb = p_sco->p_xfer_scb;
1024          p_sco->p_xfer_scb = NULL;
1025          bta_ag_codec_negotiate(p_cn_scb);
1026          break;
1027        }
1028
1029        default:
1030          APPL_TRACE_WARNING("%s: BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d",
1031                             __func__, event);
1032          break;
1033      }
1034      break;
1035
1036    case BTA_AG_SCO_SHUTTING_ST:
1037      switch (event) {
1038        case BTA_AG_SCO_CONN_OPEN_E:
1039          /* close sco connection; wait for conn close event */
1040          bta_ag_remove_sco(p_scb, true);
1041          break;
1042
1043        case BTA_AG_SCO_CONN_CLOSE_E:
1044          /* If last SCO instance then finish shutting down */
1045          if (!bta_ag_other_scb_open(p_scb)) {
1046            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1047          } else /* Other instance is still listening */
1048          {
1049            p_sco->state = BTA_AG_SCO_LISTEN_ST;
1050          }
1051
1052          /* If SCO closed for other HS which is not being disconnected,
1053             then create listen sco connection for it as scb still open */
1054          if (bta_ag_scb_open(p_scb)) {
1055            bta_ag_create_sco(p_scb, false);
1056            p_sco->state = BTA_AG_SCO_LISTEN_ST;
1057          }
1058
1059          if (p_scb == p_sco->p_curr_scb) {
1060            p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1061            p_sco->p_curr_scb = NULL;
1062          }
1063          break;
1064
1065        case BTA_AG_SCO_LISTEN_E:
1066          /* create sco listen connection (Additional channel) */
1067          if (p_scb != p_sco->p_curr_scb) {
1068            bta_ag_create_sco(p_scb, false);
1069          }
1070          break;
1071
1072        case BTA_AG_SCO_SHUTDOWN_E:
1073          if (!bta_ag_other_scb_open(p_scb)) {
1074            p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
1075          } else /* Other instance is still listening */
1076          {
1077            p_sco->state = BTA_AG_SCO_LISTEN_ST;
1078          }
1079
1080          if (p_scb == p_sco->p_curr_scb) {
1081            p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1082            p_sco->p_curr_scb = NULL;
1083          }
1084          break;
1085
1086        default:
1087          APPL_TRACE_WARNING("%s: BTA_AG_SCO_SHUTTING_ST: Ignoring event %d",
1088                             __func__, event);
1089          break;
1090      }
1091      break;
1092
1093    default:
1094      break;
1095  }
1096#if (BTA_AG_SCO_DEBUG == TRUE)
1097  if (p_sco->state != in_state) {
1098    APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
1099                     bta_ag_sco_state_str(in_state),
1100                     bta_ag_sco_state_str(p_sco->state),
1101                     bta_ag_sco_evt_str(event));
1102  }
1103#endif
1104}
1105
1106/*******************************************************************************
1107 *
1108 * Function         bta_ag_sco_is_open
1109 *
1110 * Description      Check if sco is open for this scb.
1111 *
1112 *
1113 * Returns          true if sco open for this scb, false otherwise.
1114 *
1115 ******************************************************************************/
1116bool bta_ag_sco_is_open(tBTA_AG_SCB* p_scb) {
1117  return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
1118          (bta_ag_cb.sco.p_curr_scb == p_scb));
1119}
1120
1121/*******************************************************************************
1122 *
1123 * Function         bta_ag_sco_is_opening
1124 *
1125 * Description      Check if sco is in Opening state.
1126 *
1127 *
1128 * Returns          true if sco is in Opening state for this scb, false
1129 *                  otherwise.
1130 *
1131 ******************************************************************************/
1132bool bta_ag_sco_is_opening(tBTA_AG_SCB* p_scb) {
1133  return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
1134          (bta_ag_cb.sco.p_curr_scb == p_scb));
1135}
1136
1137/*******************************************************************************
1138 *
1139 * Function         bta_ag_sco_listen
1140 *
1141 * Description
1142 *
1143 *
1144 * Returns          void
1145 *
1146 ******************************************************************************/
1147void bta_ag_sco_listen(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1148  bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
1149}
1150
1151/*******************************************************************************
1152 *
1153 * Function         bta_ag_sco_open
1154 *
1155 * Description
1156 *
1157 *
1158 * Returns          void
1159 *
1160 ******************************************************************************/
1161void bta_ag_sco_open(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1162  uint8_t event;
1163
1164  if (!sco_allowed) {
1165    APPL_TRACE_DEBUG("%s not opening sco, by policy", __func__);
1166    return;
1167  }
1168
1169  /* if another scb using sco, this is a transfer */
1170  if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb) {
1171    event = BTA_AG_SCO_XFER_E;
1172  }
1173  /* else it is an open */
1174  else {
1175    event = BTA_AG_SCO_OPEN_E;
1176  }
1177
1178  bta_ag_sco_event(p_scb, event);
1179}
1180
1181/*******************************************************************************
1182 *
1183 * Function         bta_ag_sco_close
1184 *
1185 * Description
1186 *
1187 *
1188 * Returns          void
1189 *
1190 ******************************************************************************/
1191void bta_ag_sco_close(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1192/* if scb is in use */
1193  /* sco_idx is not allocated in SCO_CODEC_ST, still need to move to listen
1194   * state. */
1195  if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) ||
1196      (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
1197  {
1198    APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
1199    bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1200  }
1201}
1202
1203/*******************************************************************************
1204 *
1205 * Function         bta_ag_sco_codec_nego
1206 *
1207 * Description      Handles result of eSCO codec negotiation
1208 *
1209 *
1210 * Returns          void
1211 *
1212 ******************************************************************************/
1213void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result) {
1214  if (result == true) {
1215    /* Subsequent SCO connection will skip codec negotiation */
1216    APPL_TRACE_DEBUG("%s: Succeeded for index 0x%04x", __func__,
1217                     p_scb->sco_idx);
1218    p_scb->codec_updated = false;
1219    bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
1220  } else {
1221    /* codec negotiation failed */
1222    APPL_TRACE_ERROR("%s: Failed for index 0x%04x", __func__, p_scb->sco_idx);
1223    bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
1224  }
1225}
1226
1227/*******************************************************************************
1228 *
1229 * Function         bta_ag_sco_shutdown
1230 *
1231 * Description
1232 *
1233 *
1234 * Returns          void
1235 *
1236 ******************************************************************************/
1237void bta_ag_sco_shutdown(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
1238  bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
1239}
1240
1241/*******************************************************************************
1242 *
1243 * Function         bta_ag_sco_conn_open
1244 *
1245 * Description
1246 *
1247 *
1248 * Returns          void
1249 *
1250 ******************************************************************************/
1251void bta_ag_sco_conn_open(tBTA_AG_SCB* p_scb,
1252                          UNUSED_ATTR tBTA_AG_DATA* p_data) {
1253  bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
1254
1255  bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1256
1257#if (BTM_SCO_HCI_INCLUDED == TRUE)
1258  /* open SCO codec if SCO is routed through transport */
1259  bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE,
1260                     BTA_AG_CI_SCO_DATA_EVT);
1261#endif
1262
1263  /* call app callback */
1264  bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
1265
1266  /* reset to mSBC T2 settings as the preferred */
1267  p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1268}
1269
1270/*******************************************************************************
1271 *
1272 * Function         bta_ag_sco_conn_close
1273 *
1274 * Description
1275 *
1276 *
1277 * Returns          void
1278 *
1279 ******************************************************************************/
1280void bta_ag_sco_conn_close(tBTA_AG_SCB* p_scb,
1281                           UNUSED_ATTR tBTA_AG_DATA* p_data) {
1282  /* clear current scb */
1283  bta_ag_cb.sco.p_curr_scb = NULL;
1284  p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
1285
1286  /* codec_fallback is set when AG is initiator and connection failed for mSBC.
1287   * OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */
1288  if (p_scb->svc_conn &&
1289      (p_scb->codec_fallback ||
1290       (p_scb->sco_codec == BTM_SCO_CODEC_MSBC &&
1291        p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1))) {
1292    bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
1293  } else {
1294    /* Indicate if the closing of audio is because of transfer */
1295    bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
1296
1297    bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1298
1299    /* if av got suspended by this call, let it resume. */
1300    /* In case call stays alive regardless of sco, av should not be affected. */
1301    if (((p_scb->call_ind == BTA_AG_CALL_INACTIVE) &&
1302         (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE)) ||
1303        (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)) {
1304      bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1305    }
1306
1307    /* call app callback */
1308    bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
1309    p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
1310  }
1311}
1312
1313/*******************************************************************************
1314 *
1315 * Function         bta_ag_sco_conn_rsp
1316 *
1317 * Description      Process the SCO connection request
1318 *
1319 *
1320 * Returns          void
1321 *
1322 ******************************************************************************/
1323void bta_ag_sco_conn_rsp(tBTA_AG_SCB* p_scb,
1324                         tBTM_ESCO_CONN_REQ_EVT_DATA* p_data) {
1325  bta_ag_cb.sco.is_local = false;
1326
1327  APPL_TRACE_DEBUG("%s: eSCO %d, state %d", __func__,
1328                   controller_get_interface()
1329                       ->supports_enhanced_setup_synchronous_connection(),
1330                   bta_ag_cb.sco.state);
1331
1332  if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST ||
1333      bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
1334      bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST) {
1335    /* tell sys to stop av if any */
1336    bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
1337    /* When HS initiated SCO, it cannot be WBS. */
1338#if (BTM_SCO_HCI_INCLUDED == TRUE)
1339    /* Configure the transport being used */
1340    BTM_ConfigScoPath(resp.input_data_path, bta_ag_sco_read_cback, NULL, TRUE);
1341#endif
1342  }
1343
1344  /* If SCO open was initiated from HS, it must be CVSD */
1345  p_scb->inuse_codec = BTA_AG_CODEC_NONE;
1346  /* Send pending commands to create SCO connection to peer */
1347  bta_ag_create_pending_sco(p_scb, bta_ag_cb.sco.is_local);
1348}
1349
1350/*******************************************************************************
1351 *
1352 * Function         bta_ag_ci_sco_data
1353 *
1354 * Description      Process the SCO data ready callin event
1355 *
1356 *
1357 * Returns          void
1358 *
1359 ******************************************************************************/
1360void bta_ag_ci_sco_data(UNUSED_ATTR tBTA_AG_SCB* p_scb,
1361                        UNUSED_ATTR tBTA_AG_DATA* p_data) {
1362#if (BTM_SCO_HCI_INCLUDED == TRUE)
1363  bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
1364#endif
1365}
1366
1367void bta_ag_set_sco_allowed(tBTA_AG_DATA* p_data) {
1368  sco_allowed = ((tBTA_AG_API_SET_SCO_ALLOWED*)p_data)->value;
1369  APPL_TRACE_DEBUG(sco_allowed ? "sco now allowed" : "sco now not allowed");
1370}
1371
1372/*******************************************************************************
1373 *  Debugging functions
1374 ******************************************************************************/
1375
1376#if (BTA_AG_SCO_DEBUG == TRUE)
1377static char* bta_ag_sco_evt_str(uint8_t event) {
1378  switch (event) {
1379    case BTA_AG_SCO_LISTEN_E:
1380      return "Listen Request";
1381    case BTA_AG_SCO_OPEN_E:
1382      return "Open Request";
1383    case BTA_AG_SCO_XFER_E:
1384      return "Transfer Request";
1385    case BTA_AG_SCO_CN_DONE_E:
1386      return "Codec Negotiation Done";
1387    case BTA_AG_SCO_REOPEN_E:
1388      return "Reopen Request";
1389    case BTA_AG_SCO_CLOSE_E:
1390      return "Close Request";
1391    case BTA_AG_SCO_SHUTDOWN_E:
1392      return "Shutdown Request";
1393    case BTA_AG_SCO_CONN_OPEN_E:
1394      return "Opened";
1395    case BTA_AG_SCO_CONN_CLOSE_E:
1396      return "Closed";
1397    case BTA_AG_SCO_CI_DATA_E:
1398      return "Sco Data";
1399    default:
1400      return "Unknown SCO Event";
1401  }
1402}
1403
1404static char* bta_ag_sco_state_str(uint8_t state) {
1405  switch (state) {
1406    case BTA_AG_SCO_SHUTDOWN_ST:
1407      return "Shutdown";
1408    case BTA_AG_SCO_LISTEN_ST:
1409      return "Listening";
1410    case BTA_AG_SCO_CODEC_ST:
1411      return "Codec Negotiation";
1412    case BTA_AG_SCO_OPENING_ST:
1413      return "Opening";
1414    case BTA_AG_SCO_OPEN_CL_ST:
1415      return "Open while closing";
1416    case BTA_AG_SCO_OPEN_XFER_ST:
1417      return "Opening while Transferring";
1418    case BTA_AG_SCO_OPEN_ST:
1419      return "Open";
1420    case BTA_AG_SCO_CLOSING_ST:
1421      return "Closing";
1422    case BTA_AG_SCO_CLOSE_OP_ST:
1423      return "Close while Opening";
1424    case BTA_AG_SCO_CLOSE_XFER_ST:
1425      return "Close while Transferring";
1426    case BTA_AG_SCO_SHUTTING_ST:
1427      return "Shutting Down";
1428    default:
1429      return "Unknown SCO State";
1430  }
1431}
1432
1433#endif /* (BTA_AG_SCO_DEBUG) */
1434