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