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