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(¶ms);
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, ¶ms);
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