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