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