bta_ag_sco.cc revision d7ffd64accbd50a27289a388856e56244ccbb5da
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#include "bta_api.h" 27#include "bta_ag_api.h" 28#include "bta_ag_co.h" 29#if (BTM_SCO_HCI_INCLUDED == TRUE) 30#include "bta_dm_co.h" 31#endif 32#include "bta_ag_int.h" 33#include "btm_api.h" 34#include "bt_common.h" 35#include "osi/include/osi.h" 36#include "utl.h" 37 38#ifndef BTA_AG_SCO_DEBUG 39#define BTA_AG_SCO_DEBUG FALSE 40#endif 41 42/* Codec negotiation timeout */ 43#ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS 44#define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000) /* 3 seconds */ 45#endif 46 47extern fixed_queue_t *btu_bta_alarm_queue; 48 49#if (BTA_AG_SCO_DEBUG == TRUE) 50static char *bta_ag_sco_evt_str(uint8_t event); 51static char *bta_ag_sco_state_str(uint8_t state); 52#endif 53 54#define BTA_AG_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \ 55 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \ 56 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \ 57 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5) 58 59/* sco events */ 60enum 61{ 62 BTA_AG_SCO_LISTEN_E, /* listen request */ 63 BTA_AG_SCO_OPEN_E, /* open request */ 64 BTA_AG_SCO_XFER_E, /* transfer request */ 65#if (BTM_WBS_INCLUDED == TRUE) 66 BTA_AG_SCO_CN_DONE_E, /* codec negotiation done */ 67 BTA_AG_SCO_REOPEN_E, /* Retry with other codec when failed */ 68#endif 69 BTA_AG_SCO_CLOSE_E, /* close request */ 70 BTA_AG_SCO_SHUTDOWN_E, /* shutdown request */ 71 BTA_AG_SCO_CONN_OPEN_E, /* sco open */ 72 BTA_AG_SCO_CONN_CLOSE_E, /* sco closed */ 73 BTA_AG_SCO_CI_DATA_E /* SCO data ready */ 74}; 75 76#if (BTM_WBS_INCLUDED == TRUE) 77#define BTA_AG_NUM_CODECS 3 78#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */ 79#define BTA_AG_ESCO_SETTING_IDX_T1 1 /* eSCO setting for mSBC T1 */ 80#define BTA_AG_ESCO_SETTING_IDX_T2 2 /* eSCO setting for mSBC T2 */ 81 82static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] = 83{ 84 /* CVSD */ 85 { 86 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */ 87 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */ 88 0x000c, /* 12 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */ 89 BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */ 90 (BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */ 91 BTM_SCO_PKT_TYPES_MASK_HV2 + 92 BTM_SCO_PKT_TYPES_MASK_HV3 + 93 BTM_SCO_PKT_TYPES_MASK_EV3 + 94 BTM_SCO_PKT_TYPES_MASK_EV4 + 95 BTM_SCO_PKT_TYPES_MASK_EV5 + 96 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 + 97 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), 98 BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */ 99 }, 100 /* mSBC T1 */ 101 { 102 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec), 8000 */ 103 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec), 8000 */ 104 8, /* 8 ms */ 105 BTM_VOICE_SETTING_TRANS, /* Inp Linear, Transparent, 2s Comp, 16bit */ 106 (BTM_SCO_PKT_TYPES_MASK_EV3 | /* Packet Types : EV3 + NO_2_EV3 */ 107 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | 108 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 109 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 | 110 BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 ), 111 BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */ 112 }, 113 /* mSBC T2*/ 114 { 115 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec), 8000 */ 116 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec), 8000 */ 117 13, /* 13 ms */ 118 BTM_VOICE_SETTING_TRANS, /* Inp Linear, Transparent, 2s Comp, 16bit */ 119 (BTM_SCO_PKT_TYPES_MASK_EV3 | /* Packet Types : EV3 + 2-EV3 */ 120 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | 121 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 122 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), 123 BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */ 124 } 125}; 126#else 127/* WBS not included, CVSD by default */ 128static const tBTM_ESCO_PARAMS bta_ag_esco_params = 129{ 130 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */ 131 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */ 132 0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */ 133 0x0060, /* Inp Linear, Air CVSD, 2s Comp, 16bit */ 134 (BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */ 135 BTM_SCO_PKT_TYPES_MASK_HV2 + 136 BTM_SCO_PKT_TYPES_MASK_HV3 + 137 BTM_SCO_PKT_TYPES_MASK_EV3 + 138 BTM_SCO_PKT_TYPES_MASK_EV4 + 139 BTM_SCO_PKT_TYPES_MASK_EV5 + 140 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 + 141 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), 142 BTM_ESCO_RETRANS_POWER /* Retransmission effort */ 143}; 144#endif 145 146/******************************************************************************* 147** 148** Function bta_ag_sco_conn_cback 149** 150** Description BTM SCO connection callback. 151** 152** 153** Returns void 154** 155*******************************************************************************/ 156static void bta_ag_sco_conn_cback(uint16_t sco_idx) 157{ 158 uint16_t handle; 159 tBTA_AG_SCB *p_scb; 160 161 /* match callback to scb; first check current sco scb */ 162 if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use) 163 { 164 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb); 165 } 166 /* then check for scb connected to this peer */ 167 else 168 { 169 /* Check if SLC is up */ 170 handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx)); 171 p_scb = bta_ag_scb_by_idx(handle); 172 if(p_scb && !p_scb->svc_conn) 173 handle = 0; 174 } 175 176 if (handle != 0) { 177 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR)); 178 p_buf->event = BTA_AG_SCO_OPEN_EVT; 179 p_buf->layer_specific = handle; 180 bta_sys_sendmsg(p_buf); 181 } else { 182 /* no match found; disconnect sco, init sco variables */ 183 bta_ag_cb.sco.p_curr_scb = NULL; 184 bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST; 185 BTM_RemoveSco(sco_idx); 186 } 187} 188 189/******************************************************************************* 190** 191** Function bta_ag_sco_disc_cback 192** 193** Description BTM SCO disconnection callback. 194** 195** 196** Returns void 197** 198*******************************************************************************/ 199static void bta_ag_sco_disc_cback(uint16_t sco_idx) 200{ 201 uint16_t handle = 0; 202 203 APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): sco_idx: 0x%x p_cur_scb: 0x%08x sco.state: %d", sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state); 204 205 APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x in_use: %u sco_idx: 0x%x sco state: %u", 206 &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx, bta_ag_cb.scb[0].state); 207 APPL_TRACE_DEBUG ("bta_ag_sco_disc_cback(): scb[1] addr: 0x%08x in_use: %u sco_idx: 0x%x sco state: %u", 208 &bta_ag_cb.scb[1], bta_ag_cb.scb[1].in_use, bta_ag_cb.scb[1].sco_idx, bta_ag_cb.scb[1].state); 209 210 /* match callback to scb */ 211 if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use) 212 { 213 /* We only care about callbacks for the active SCO */ 214 if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx) 215 { 216 if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF) 217 return; 218 } 219 handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb); 220 } 221 222 if (handle != 0) 223 { 224#if (BTM_SCO_HCI_INCLUDED == TRUE) 225 tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, true); 226 APPL_TRACE_DEBUG("bta_ag_sco_disc_cback sco close config status = %d", status); 227 /* SCO clean up here */ 228 bta_dm_sco_co_close(); 229#endif 230 231#if (BTM_WBS_INCLUDED == TRUE) 232 /* Restore settings */ 233 if(bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC) 234 { 235 /* set_sco_codec(BTM_SCO_CODEC_NONE); we should get a close */ 236 BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD); 237 238 /* If SCO open was initiated by AG and failed for mSBC, then attempt 239 mSBC with T1 settings i.e. 'Safe Settings'. If this fails, then switch to CVSD */ 240 if (bta_ag_sco_is_opening (bta_ag_cb.sco.p_curr_scb)) 241 { 242 if (bta_ag_cb.sco.p_curr_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) 243 { 244 APPL_TRACE_DEBUG("Fallback to mSBC T1 settings"); 245 bta_ag_cb.sco.p_curr_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T1; 246 } 247 else 248 { 249 APPL_TRACE_DEBUG("Fallback to CVSD settings"); 250 bta_ag_cb.sco.p_curr_scb->codec_fallback = true; 251 } 252 } 253 } 254 255 bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE; 256#endif 257 258 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR)); 259 p_buf->event = BTA_AG_SCO_CLOSE_EVT; 260 p_buf->layer_specific = handle; 261 bta_sys_sendmsg(p_buf); 262 } else { 263 /* no match found */ 264 APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback"); 265 266 /* sco could be closed after scb dealloc'ed */ 267 if (bta_ag_cb.sco.p_curr_scb != NULL) 268 { 269 bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX; 270 bta_ag_cb.sco.p_curr_scb = NULL; 271 bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST; 272 } 273 } 274} 275#if (BTM_SCO_HCI_INCLUDED == TRUE) 276/******************************************************************************* 277** 278** Function bta_ag_sco_read_cback 279** 280** Description Callback function is the callback function for incoming 281** SCO data over HCI. 282** 283** Returns void 284** 285*******************************************************************************/ 286static void bta_ag_sco_read_cback (uint16_t sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status) 287{ 288 if (status != BTM_SCO_DATA_CORRECT) 289 { 290 APPL_TRACE_DEBUG("bta_ag_sco_read_cback: status(%d)", status); 291 } 292 293 /* Callout function must free the data. */ 294 bta_dm_sco_co_in_data (p_data, status); 295} 296#endif 297/******************************************************************************* 298** 299** Function bta_ag_remove_sco 300** 301** Description Removes the specified SCO from the system. 302** If only_active is true, then SCO is only removed if connected 303** 304** Returns bool - true if Sco removal was started 305** 306*******************************************************************************/ 307static bool bta_ag_remove_sco(tBTA_AG_SCB *p_scb, bool only_active) 308{ 309 bool removed_started = false; 310 tBTM_STATUS status; 311 312 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) 313 { 314 if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx) 315 { 316 status = BTM_RemoveSco(p_scb->sco_idx); 317 318 APPL_TRACE_DEBUG("ag remove sco: inx 0x%04x, status:0x%x", p_scb->sco_idx, status); 319 320 if (status == BTM_CMD_STARTED) 321 { 322 /* Sco is connected; set current control block */ 323 bta_ag_cb.sco.p_curr_scb = p_scb; 324 325 removed_started = true; 326 } 327 /* If no connection reset the sco handle */ 328 else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) 329 { 330 p_scb->sco_idx = BTM_INVALID_SCO_INDEX; 331 } 332 } 333 } 334 return removed_started; 335} 336 337 338/******************************************************************************* 339** 340** Function bta_ag_esco_connreq_cback 341** 342** Description BTM eSCO connection requests and eSCO change requests 343** Only the connection requests are processed by BTA. 344** 345** Returns void 346** 347*******************************************************************************/ 348static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) 349{ 350 tBTA_AG_SCB *p_scb; 351 uint16_t handle; 352 uint16_t sco_inx = p_data->conn_evt.sco_inx; 353 354 /* Only process connection requests */ 355 if (event == BTM_ESCO_CONN_REQ_EVT) 356 { 357 if ((handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_inx))) != 0 && 358 ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) && p_scb->svc_conn) 359 { 360 p_scb->sco_idx = sco_inx; 361 362 /* If no other SCO active, allow this one */ 363 if (!bta_ag_cb.sco.p_curr_scb) 364 { 365 APPL_TRACE_EVENT("bta_ag_esco_connreq_cback: Accept Conn Request (sco_inx 0x%04x)", sco_inx); 366 bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt); 367 368 bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST; 369 bta_ag_cb.sco.p_curr_scb = p_scb; 370 bta_ag_cb.sco.cur_idx = p_scb->sco_idx; 371 } 372 else /* Begin a transfer: Close current SCO before responding */ 373 { 374 APPL_TRACE_DEBUG("bta_ag_esco_connreq_cback: Begin XFER"); 375 bta_ag_cb.sco.p_xfer_scb = p_scb; 376 bta_ag_cb.sco.conn_data = p_data->conn_evt; 377 bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST; 378 379 if (!bta_ag_remove_sco(bta_ag_cb.sco.p_curr_scb, true)) 380 { 381 APPL_TRACE_ERROR("bta_ag_esco_connreq_cback: Nothing to remove so accept Conn Request (sco_inx 0x%04x)", sco_inx); 382 bta_ag_cb.sco.p_xfer_scb = NULL; 383 bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST; 384 385 bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt); 386 } 387 } 388 } 389 /* If error occurred send reject response immediately */ 390 else 391 { 392 APPL_TRACE_WARNING("no scb for bta_ag_esco_connreq_cback or no resources"); 393 BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL); 394 } 395 } 396 /* Received a change in the esco link */ 397 else if (event == BTM_ESCO_CHG_EVT) 398 { 399 APPL_TRACE_EVENT("eSCO change event (inx %d): rtrans %d, rxlen %d, txlen %d, txint %d", 400 p_data->chg_evt.sco_inx, 401 p_data->chg_evt.retrans_window, p_data->chg_evt.rx_pkt_len, 402 p_data->chg_evt.tx_pkt_len, p_data->chg_evt.tx_interval); 403 } 404} 405 406/******************************************************************************* 407** 408** Function bta_ag_cback_sco 409** 410** Description Call application callback function with SCO event. 411** 412** 413** Returns void 414** 415*******************************************************************************/ 416static void bta_ag_cback_sco(tBTA_AG_SCB *p_scb, uint8_t event) 417{ 418 tBTA_AG_HDR sco; 419 420 sco.handle = bta_ag_scb_to_idx(p_scb); 421 sco.app_id = p_scb->app_id; 422 423 /* call close cback */ 424 (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &sco); 425} 426 427/******************************************************************************* 428** 429** Function bta_ag_create_sco 430** 431** Description 432** 433** 434** Returns void 435** 436*******************************************************************************/ 437static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, bool is_orig) 438{ 439 tBTM_STATUS status; 440 uint8_t *p_bd_addr = NULL; 441 tBTM_ESCO_PARAMS params; 442#if (BTM_WBS_INCLUDED == TRUE) 443 tBTA_AG_PEER_CODEC esco_codec = BTM_SCO_CODEC_CVSD; 444 int codec_index = 0; 445#endif 446#if (BTM_SCO_HCI_INCLUDED == TRUE) 447 tBTM_SCO_ROUTE_TYPE sco_route; 448 tBTA_CODEC_INFO codec_info = {BTA_SCO_CODEC_PCM}; 449 uint32_t pcm_sample_rate; 450#endif 451 452 /* Make sure this sco handle is not already in use */ 453 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) 454 { 455 APPL_TRACE_WARNING("bta_ag_create_sco: Index 0x%04x Already In Use!", 456 p_scb->sco_idx); 457 return; 458 } 459 460#if (BTM_WBS_INCLUDED == TRUE) 461 if ((p_scb->sco_codec == BTM_SCO_CODEC_MSBC) && 462 !p_scb->codec_fallback && 463 !p_scb->retry_with_sco_only) 464 esco_codec = BTM_SCO_CODEC_MSBC; 465 466 if (p_scb->codec_fallback) 467 { 468 p_scb->codec_fallback = false; 469 470 /* Force AG to send +BCS for the next audio connection. */ 471 p_scb->codec_updated = true; 472 } 473 474 /* If WBS included, use CVSD by default, index is 0 for CVSD by initialization */ 475 /* If eSCO codec is mSBC, index is T2 or T1 */ 476 if (esco_codec == BTM_SCO_CODEC_MSBC) 477 { 478 if (p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T2) 479 { 480 codec_index = BTA_AG_ESCO_SETTING_IDX_T2; 481 } 482 else 483 { 484 codec_index = BTA_AG_ESCO_SETTING_IDX_T1; 485 } 486 } 487 488 params = bta_ag_esco_params[codec_index]; 489#else 490 /* When WBS is not included, use CVSD by default */ 491 params = bta_ag_esco_params; 492#endif 493 494 if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */ 495 params = bta_ag_cb.sco.params; 496 497 if(!bta_ag_cb.sco.param_updated) 498 { 499#if (BTM_WBS_INCLUDED == TRUE) 500 if (esco_codec == BTM_SCO_CODEC_CVSD) /* For CVSD */ 501#endif 502 { 503 /* Use the application packet types (5 slot EV packets not allowed) */ 504 params.packet_types = p_bta_ag_cfg->sco_pkt_types | 505 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 506 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5; 507 } 508 } 509 510 /* if initiating set current scb and peer bd addr */ 511 if (is_orig) 512 { 513 /* Attempt to use eSCO if remote host supports HFP >= 1.5 */ 514 /* Need to find out from SIG if HSP can use eSCO; for now use SCO */ 515 if (p_scb->conn_service == BTA_AG_HFP && p_scb->peer_version >= HFP_VERSION_1_5 && !p_scb->retry_with_sco_only) 516 { 517 518 BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms); 519 /* If ESCO or EDR ESCO, retry with SCO only in case of failure */ 520 if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK) 521 ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_AG_NO_EDR_ESCO)) 522 { 523#if (BTM_WBS_INCLUDED == TRUE) 524 if (esco_codec != BTA_AG_CODEC_MSBC) 525 { 526 p_scb->retry_with_sco_only = true; 527 APPL_TRACE_API("Setting retry_with_sco_only to true"); 528 } 529 else /* Do not use SCO when using mSBC */ 530 { 531 p_scb->retry_with_sco_only = false; 532 APPL_TRACE_API("Setting retry_with_sco_only to false"); 533 } 534#else 535 p_scb->retry_with_sco_only = true; 536 APPL_TRACE_API("Setting retry_with_sco_only to true"); 537#endif 538 } 539 } 540 else 541 { 542 if(p_scb->retry_with_sco_only) 543 APPL_TRACE_API("retrying with SCO only"); 544 p_scb->retry_with_sco_only = false; 545 546 BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms); 547 } 548 549 bta_ag_cb.sco.p_curr_scb = p_scb; 550 551 /* tell sys to stop av if any */ 552 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 553 554#if (BTM_WBS_INCLUDED == TRUE) 555 /* Allow any platform specific pre-SCO set up to take place */ 556 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP, 557 esco_codec); 558 559 /* This setting may not be necessary */ 560 /* To be verified with stable 2049 boards */ 561 if (esco_codec == BTA_AG_CODEC_MSBC) 562 BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS); 563 else 564 BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD); 565 /* save the current codec because sco_codec can be updated while SCO is open. */ 566 p_scb->inuse_codec = esco_codec; 567#else 568 /* Allow any platform specific pre-SCO set up to take place */ 569 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP); 570#endif 571 572#if (BTM_SCO_HCI_INCLUDED == TRUE) 573#if (BTM_WBS_INCLUDED == TRUE) 574 if (esco_codec == BTA_AG_CODEC_MSBC) 575 pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_16K; 576 else 577#endif 578 pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K; 579 580 sco_route = bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id); 581#endif 582 583 584#if (BTM_SCO_HCI_INCLUDED == TRUE) 585 /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ 586 BTM_ConfigScoPath(sco_route, bta_ag_sco_read_cback, NULL, true); 587#endif 588 bta_ag_cb.sco.cur_idx = p_scb->sco_idx; 589 } 590 else 591 p_scb->retry_with_sco_only = false; 592 593 p_bd_addr = p_scb->peer_addr; 594 595 status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types, 596 &p_scb->sco_idx, bta_ag_sco_conn_cback, 597 bta_ag_sco_disc_cback); 598 if (status == BTM_CMD_STARTED) 599 { 600 if (!is_orig) 601 { 602 BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback); 603 } 604 else /* Initiating the connection, set the current sco handle */ 605 { 606 bta_ag_cb.sco.cur_idx = p_scb->sco_idx; 607 } 608 } 609 610 APPL_TRACE_API("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x", 611 is_orig, p_scb->sco_idx, status, params.packet_types); 612} 613 614#if (BTM_WBS_INCLUDED == TRUE) 615/******************************************************************************* 616** 617** Function bta_ag_attempt_msbc_safe_settings 618** 619** Description Checks if ESCO connection needs to be attempted using mSBC T1(safe) settings 620** 621** 622** Returns true if T1 settings has to be used, false otherwise 623** 624*******************************************************************************/ 625bool bta_ag_attempt_msbc_safe_settings(tBTA_AG_SCB *p_scb) 626{ 627 if (p_scb->svc_conn && p_scb->sco_codec == BTM_SCO_CODEC_MSBC && 628 p_scb->codec_msbc_settings == BTA_AG_SCO_MSBC_SETTINGS_T1) 629 return true; 630 else 631 return false; 632} 633 634/******************************************************************************* 635** 636** Function bta_ag_codec_negotiation_timer_cback 637** 638** Description 639** 640** 641** Returns void 642** 643*******************************************************************************/ 644static void bta_ag_codec_negotiation_timer_cback(void *data) 645{ 646 tBTA_AG_SCB *p_scb = (tBTA_AG_SCB *)data; 647 648 /* Announce that codec negotiation failed. */ 649 bta_ag_sco_codec_nego(p_scb, false); 650 651 /* call app callback */ 652 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT); 653} 654 655/******************************************************************************* 656** 657** Function bta_ag_codec_negotiate 658** 659** Description Initiate codec negotiation by sending AT command. 660** If not necessary, skip negotiation. 661** 662** Returns void 663** 664*******************************************************************************/ 665void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb) 666{ 667 bta_ag_cb.sco.p_curr_scb = p_scb; 668 669 if ((p_scb->codec_updated || p_scb->codec_fallback || 670 bta_ag_attempt_msbc_safe_settings(p_scb)) && 671 (p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) 672 { 673 /* Change the power mode to Active until sco open is completed. */ 674 bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 675 676 /* Send +BCS to the peer */ 677 bta_ag_send_bcs(p_scb, NULL); 678 679 /* Start timer to handle timeout */ 680 alarm_set_on_queue(p_scb->codec_negotiation_timer, 681 BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS, 682 bta_ag_codec_negotiation_timer_cback, 683 p_scb, 684 btu_bta_alarm_queue); 685 } 686 else 687 { 688 /* use same codec type as previous SCO connection, skip codec negotiation */ 689 APPL_TRACE_DEBUG("use same codec type as previous SCO connection,skip codec negotiation"); 690 bta_ag_sco_codec_nego(p_scb, true); 691 } 692} 693#endif /* (BTM_WBS_INCLUDED == TRUE) */ 694 695/******************************************************************************* 696** 697** Function bta_ag_sco_event 698** 699** Description 700** 701** 702** Returns void 703** 704*******************************************************************************/ 705static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, uint8_t event) 706{ 707 tBTA_AG_SCO_CB *p_sco = &bta_ag_cb.sco; 708#if (BTM_WBS_INCLUDED == TRUE) 709 tBTA_AG_SCB *p_cn_scb = NULL; /* For codec negotiation */ 710#endif 711#if (BTM_SCO_HCI_INCLUDED == TRUE) 712 BT_HDR *p_buf; 713#endif 714#if (BTA_AG_SCO_DEBUG == TRUE) 715 uint8_t in_state = p_sco->state; 716 717 APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)", 718 p_scb->sco_idx, 719 p_sco->state, bta_ag_sco_state_str(p_sco->state), 720 event, bta_ag_sco_evt_str(event)); 721#else 722 APPL_TRACE_EVENT("BTA ag sco evt (hdl 0x%04x): State %d, Event %d", 723 p_scb->sco_idx, p_sco->state, event); 724#endif 725 726#if (BTM_SCO_HCI_INCLUDED == TRUE) 727 if (event == BTA_AG_SCO_CI_DATA_E) 728 { 729 while (true) 730 { 731 bta_dm_sco_co_out_data(&p_buf); 732 if (p_buf) 733 { 734 if (p_sco->state == BTA_AG_SCO_OPEN_ST) 735 BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf); 736 else 737 osi_free(p_buf); 738 } 739 else 740 break; 741 } 742 743 return; 744 } 745#endif 746 747 switch (p_sco->state) 748 { 749 case BTA_AG_SCO_SHUTDOWN_ST: 750 switch (event) 751 { 752 case BTA_AG_SCO_LISTEN_E: 753 /* create sco listen connection */ 754 bta_ag_create_sco(p_scb, false); 755 p_sco->state = BTA_AG_SCO_LISTEN_ST; 756 break; 757 758 default: 759 APPL_TRACE_WARNING("BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d", event); 760 break; 761 } 762 break; 763 764 case BTA_AG_SCO_LISTEN_ST: 765 switch (event) 766 { 767 case BTA_AG_SCO_LISTEN_E: 768 /* create sco listen connection (Additional channel) */ 769 bta_ag_create_sco(p_scb, false); 770 break; 771 772 case BTA_AG_SCO_OPEN_E: 773 /* remove listening connection */ 774 bta_ag_remove_sco(p_scb, false); 775 776#if (BTM_WBS_INCLUDED == TRUE) 777 /* start codec negotiation */ 778 p_sco->state = BTA_AG_SCO_CODEC_ST; 779 p_cn_scb = p_scb; 780#else 781 /* create sco connection to peer */ 782 bta_ag_create_sco(p_scb, true); 783 p_sco->state = BTA_AG_SCO_OPENING_ST; 784#endif 785 break; 786 787 case BTA_AG_SCO_SHUTDOWN_E: 788 /* remove listening connection */ 789 bta_ag_remove_sco(p_scb, false); 790 791 if (p_scb == p_sco->p_curr_scb) 792 p_sco->p_curr_scb = NULL; 793 794 /* If last SCO instance then finish shutting down */ 795 if (!bta_ag_other_scb_open(p_scb)) 796 { 797 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; 798 } 799 break; 800 801 case BTA_AG_SCO_CLOSE_E: 802 /* remove listening connection */ 803 /* Ignore the event. We need to keep listening SCO for the active SLC */ 804 APPL_TRACE_WARNING("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event); 805 break; 806 807 case BTA_AG_SCO_CONN_CLOSE_E: 808 /* sco failed; create sco listen connection */ 809 bta_ag_create_sco(p_scb, false); 810 p_sco->state = BTA_AG_SCO_LISTEN_ST; 811 break; 812 813 default: 814 APPL_TRACE_WARNING("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event); 815 break; 816 } 817 break; 818 819#if (BTM_WBS_INCLUDED == TRUE) 820 case BTA_AG_SCO_CODEC_ST: 821 switch (event) 822 { 823 case BTA_AG_SCO_LISTEN_E: 824 /* create sco listen connection (Additional channel) */ 825 bta_ag_create_sco(p_scb, false); 826 break; 827 828 case BTA_AG_SCO_CN_DONE_E: 829 /* create sco connection to peer */ 830 bta_ag_create_sco(p_scb, true); 831 p_sco->state = BTA_AG_SCO_OPENING_ST; 832 break; 833 834 case BTA_AG_SCO_XFER_E: 835 /* save xfer scb */ 836 p_sco->p_xfer_scb = p_scb; 837 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; 838 break; 839 840 case BTA_AG_SCO_SHUTDOWN_E: 841 /* remove listening connection */ 842 bta_ag_remove_sco(p_scb, false); 843 844 if (p_scb == p_sco->p_curr_scb) 845 p_sco->p_curr_scb = NULL; 846 847 /* If last SCO instance then finish shutting down */ 848 if (!bta_ag_other_scb_open(p_scb)) 849 { 850 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; 851 } 852 break; 853 854 case BTA_AG_SCO_CLOSE_E: 855 /* sco open is not started yet. just go back to listening */ 856 p_sco->state = BTA_AG_SCO_LISTEN_ST; 857 break; 858 859 case BTA_AG_SCO_CONN_CLOSE_E: 860 /* sco failed; create sco listen connection */ 861 bta_ag_create_sco(p_scb, false); 862 p_sco->state = BTA_AG_SCO_LISTEN_ST; 863 break; 864 865 default: 866 APPL_TRACE_WARNING("BTA_AG_SCO_CODEC_ST: Ignoring event %d", event); 867 break; 868 } 869 break; 870#endif 871 872 case BTA_AG_SCO_OPENING_ST: 873 switch (event) 874 { 875 case BTA_AG_SCO_LISTEN_E: 876 /* second headset has now joined */ 877 /* create sco listen connection (Additional channel) */ 878 if (p_scb != p_sco->p_curr_scb) 879 { 880 bta_ag_create_sco(p_scb, false); 881 } 882 break; 883 884#if (BTM_WBS_INCLUDED == TRUE) 885 case BTA_AG_SCO_REOPEN_E: 886 /* start codec negotiation */ 887 p_sco->state = BTA_AG_SCO_CODEC_ST; 888 p_cn_scb = p_scb; 889 break; 890#endif 891 892 case BTA_AG_SCO_XFER_E: 893 /* save xfer scb */ 894 p_sco->p_xfer_scb = p_scb; 895 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; 896 break; 897 898 case BTA_AG_SCO_CLOSE_E: 899 p_sco->state = BTA_AG_SCO_OPEN_CL_ST; 900 break; 901 902 case BTA_AG_SCO_SHUTDOWN_E: 903 /* If not opening scb, just close it */ 904 if (p_scb != p_sco->p_curr_scb) 905 { 906 /* remove listening connection */ 907 bta_ag_remove_sco(p_scb, false); 908 } 909 else 910 p_sco->state = BTA_AG_SCO_SHUTTING_ST; 911 912 break; 913 914 case BTA_AG_SCO_CONN_OPEN_E: 915 p_sco->state = BTA_AG_SCO_OPEN_ST; 916 break; 917 918 case BTA_AG_SCO_CONN_CLOSE_E: 919 /* sco failed; create sco listen connection */ 920 bta_ag_create_sco(p_scb, false); 921 p_sco->state = BTA_AG_SCO_LISTEN_ST; 922 break; 923 924 default: 925 APPL_TRACE_WARNING("BTA_AG_SCO_OPENING_ST: Ignoring event %d", event); 926 break; 927 } 928 break; 929 930 case BTA_AG_SCO_OPEN_CL_ST: 931 switch (event) 932 { 933 case BTA_AG_SCO_XFER_E: 934 /* save xfer scb */ 935 p_sco->p_xfer_scb = p_scb; 936 937 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; 938 break; 939 940 case BTA_AG_SCO_OPEN_E: 941 p_sco->state = BTA_AG_SCO_OPENING_ST; 942 break; 943 944 case BTA_AG_SCO_SHUTDOWN_E: 945 /* If not opening scb, just close it */ 946 if (p_scb != p_sco->p_curr_scb) 947 { 948 /* remove listening connection */ 949 bta_ag_remove_sco(p_scb, false); 950 } 951 else 952 p_sco->state = BTA_AG_SCO_SHUTTING_ST; 953 954 break; 955 956 case BTA_AG_SCO_CONN_OPEN_E: 957 /* close sco connection */ 958 bta_ag_remove_sco(p_scb, true); 959 960 p_sco->state = BTA_AG_SCO_CLOSING_ST; 961 break; 962 963 case BTA_AG_SCO_CONN_CLOSE_E: 964 /* sco failed; create sco listen connection */ 965 966 p_sco->state = BTA_AG_SCO_LISTEN_ST; 967 break; 968 969 default: 970 APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d", event); 971 break; 972 } 973 break; 974 975 case BTA_AG_SCO_OPEN_XFER_ST: 976 switch (event) 977 { 978 case BTA_AG_SCO_CLOSE_E: 979 /* close sco connection */ 980 bta_ag_remove_sco(p_scb, true); 981 982 p_sco->state = BTA_AG_SCO_CLOSING_ST; 983 break; 984 985 case BTA_AG_SCO_SHUTDOWN_E: 986 /* remove all connection */ 987 bta_ag_remove_sco(p_scb, false); 988 p_sco->state = BTA_AG_SCO_SHUTTING_ST; 989 990 break; 991 992 case BTA_AG_SCO_CONN_CLOSE_E: 993 /* closed sco; place in listen mode and 994 accept the transferred connection */ 995 bta_ag_create_sco(p_scb, false); /* Back into listen mode */ 996 997 /* Accept sco connection with xfer scb */ 998 bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data); 999 p_sco->state = BTA_AG_SCO_OPENING_ST; 1000 p_sco->p_curr_scb = p_sco->p_xfer_scb; 1001 p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx; 1002 p_sco->p_xfer_scb = NULL; 1003 break; 1004 1005 default: 1006 APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d", event); 1007 break; 1008 } 1009 break; 1010 1011 case BTA_AG_SCO_OPEN_ST: 1012 switch (event) 1013 { 1014 case BTA_AG_SCO_LISTEN_E: 1015 /* second headset has now joined */ 1016 /* create sco listen connection (Additional channel) */ 1017 if (p_scb != p_sco->p_curr_scb) 1018 { 1019 bta_ag_create_sco(p_scb, false); 1020 } 1021 break; 1022 1023 case BTA_AG_SCO_XFER_E: 1024 /* close current sco connection */ 1025 bta_ag_remove_sco(p_sco->p_curr_scb, true); 1026 1027 /* save xfer scb */ 1028 p_sco->p_xfer_scb = p_scb; 1029 1030 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; 1031 break; 1032 1033 case BTA_AG_SCO_CLOSE_E: 1034 /* close sco connection if active */ 1035 if (bta_ag_remove_sco(p_scb, true)) 1036 { 1037 p_sco->state = BTA_AG_SCO_CLOSING_ST; 1038 } 1039 break; 1040 1041 case BTA_AG_SCO_SHUTDOWN_E: 1042 /* remove all listening connections */ 1043 bta_ag_remove_sco(p_scb, false); 1044 1045 /* If SCO was active on this scb, close it */ 1046 if (p_scb == p_sco->p_curr_scb) 1047 { 1048 p_sco->state = BTA_AG_SCO_SHUTTING_ST; 1049 } 1050 break; 1051 1052 case BTA_AG_SCO_CONN_CLOSE_E: 1053 /* peer closed sco; create sco listen connection */ 1054 bta_ag_create_sco(p_scb, false); 1055 p_sco->state = BTA_AG_SCO_LISTEN_ST; 1056 break; 1057 1058 default: 1059 APPL_TRACE_WARNING("BTA_AG_SCO_OPEN_ST: Ignoring event %d", event); 1060 break; 1061 } 1062 break; 1063 1064 case BTA_AG_SCO_CLOSING_ST: 1065 switch (event) 1066 { 1067 case BTA_AG_SCO_LISTEN_E: 1068 /* create sco listen connection (Additional channel) */ 1069 if (p_scb != p_sco->p_curr_scb) 1070 { 1071 bta_ag_create_sco(p_scb, false); 1072 } 1073 break; 1074 1075 case BTA_AG_SCO_OPEN_E: 1076 p_sco->state = BTA_AG_SCO_CLOSE_OP_ST; 1077 break; 1078 1079 case BTA_AG_SCO_XFER_E: 1080 /* save xfer scb */ 1081 p_sco->p_xfer_scb = p_scb; 1082 1083 p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; 1084 break; 1085 1086 case BTA_AG_SCO_SHUTDOWN_E: 1087 /* If not closing scb, just close it */ 1088 if (p_scb != p_sco->p_curr_scb) 1089 { 1090 /* remove listening connection */ 1091 bta_ag_remove_sco(p_scb, false); 1092 } 1093 else 1094 p_sco->state = BTA_AG_SCO_SHUTTING_ST; 1095 1096 break; 1097 1098 case BTA_AG_SCO_CONN_CLOSE_E: 1099 /* peer closed sco; create sco listen connection */ 1100 bta_ag_create_sco(p_scb, false); 1101 1102 p_sco->state = BTA_AG_SCO_LISTEN_ST; 1103 break; 1104 1105 default: 1106 APPL_TRACE_WARNING("BTA_AG_SCO_CLOSING_ST: Ignoring event %d", event); 1107 break; 1108 } 1109 break; 1110 1111 case BTA_AG_SCO_CLOSE_OP_ST: 1112 switch (event) 1113 { 1114 case BTA_AG_SCO_CLOSE_E: 1115 p_sco->state = BTA_AG_SCO_CLOSING_ST; 1116 break; 1117 1118 case BTA_AG_SCO_SHUTDOWN_E: 1119 p_sco->state = BTA_AG_SCO_SHUTTING_ST; 1120 break; 1121 1122 case BTA_AG_SCO_CONN_CLOSE_E: 1123#if (BTM_WBS_INCLUDED == TRUE) 1124 /* start codec negotiation */ 1125 p_sco->state = BTA_AG_SCO_CODEC_ST; 1126 p_cn_scb = p_scb; 1127#else 1128 /* open sco connection */ 1129 bta_ag_create_sco(p_scb, true); 1130 p_sco->state = BTA_AG_SCO_OPENING_ST; 1131#endif 1132 break; 1133 1134 case BTA_AG_SCO_LISTEN_E: 1135 /* create sco listen connection (Additional channel) */ 1136 if (p_scb != p_sco->p_curr_scb) 1137 { 1138 bta_ag_create_sco(p_scb, false); 1139 } 1140 break; 1141 1142 default: 1143 APPL_TRACE_WARNING("BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d", event); 1144 break; 1145 } 1146 break; 1147 1148 case BTA_AG_SCO_CLOSE_XFER_ST: 1149 switch (event) 1150 { 1151 case BTA_AG_SCO_CONN_OPEN_E: 1152 /* close sco connection so headset can be transferred 1153 Probably entered this state from "opening state" */ 1154 bta_ag_remove_sco(p_scb, true); 1155 break; 1156 1157 case BTA_AG_SCO_CLOSE_E: 1158 /* clear xfer scb */ 1159 p_sco->p_xfer_scb = NULL; 1160 1161 p_sco->state = BTA_AG_SCO_CLOSING_ST; 1162 break; 1163 1164 case BTA_AG_SCO_SHUTDOWN_E: 1165 /* clear xfer scb */ 1166 p_sco->p_xfer_scb = NULL; 1167 1168 p_sco->state = BTA_AG_SCO_SHUTTING_ST; 1169 break; 1170 1171 case BTA_AG_SCO_CONN_CLOSE_E: 1172 /* closed sco; place old sco in listen mode, 1173 take current sco out of listen, and 1174 create originating sco for current */ 1175 bta_ag_create_sco(p_scb, false); 1176 bta_ag_remove_sco(p_sco->p_xfer_scb, false); 1177 1178#if (BTM_WBS_INCLUDED == TRUE) 1179 /* start codec negotiation */ 1180 p_sco->state = BTA_AG_SCO_CODEC_ST; 1181 p_cn_scb = p_sco->p_xfer_scb; 1182 p_sco->p_xfer_scb = NULL; 1183#else 1184 /* create sco connection to peer */ 1185 bta_ag_create_sco(p_sco->p_xfer_scb, true); 1186 p_sco->p_xfer_scb = NULL; 1187 p_sco->state = BTA_AG_SCO_OPENING_ST; 1188#endif 1189 break; 1190 1191 default: 1192 APPL_TRACE_WARNING("BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d", event); 1193 break; 1194 } 1195 break; 1196 1197 case BTA_AG_SCO_SHUTTING_ST: 1198 switch (event) 1199 { 1200 case BTA_AG_SCO_CONN_OPEN_E: 1201 /* close sco connection; wait for conn close event */ 1202 bta_ag_remove_sco(p_scb, true); 1203 break; 1204 1205 case BTA_AG_SCO_CONN_CLOSE_E: 1206 /* If last SCO instance then finish shutting down */ 1207 if (!bta_ag_other_scb_open(p_scb)) 1208 { 1209 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; 1210 } 1211 else /* Other instance is still listening */ 1212 { 1213 p_sco->state = BTA_AG_SCO_LISTEN_ST; 1214 } 1215 1216 /* If SCO closed for other HS which is not being disconnected, 1217 then create listen sco connection for it as scb still open */ 1218 if (bta_ag_scb_open(p_scb)) 1219 { 1220 bta_ag_create_sco(p_scb, false); 1221 p_sco->state = BTA_AG_SCO_LISTEN_ST; 1222 } 1223 1224 if (p_scb == p_sco->p_curr_scb) 1225 { 1226 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX; 1227 p_sco->p_curr_scb = NULL; 1228 } 1229 break; 1230 1231 case BTA_AG_SCO_LISTEN_E: 1232 /* create sco listen connection (Additional channel) */ 1233 if (p_scb != p_sco->p_curr_scb) 1234 { 1235 bta_ag_create_sco(p_scb, false); 1236 } 1237 break; 1238 1239 case BTA_AG_SCO_SHUTDOWN_E: 1240 if (!bta_ag_other_scb_open(p_scb)) 1241 { 1242 p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; 1243 } 1244 else /* Other instance is still listening */ 1245 { 1246 p_sco->state = BTA_AG_SCO_LISTEN_ST; 1247 } 1248 1249 if (p_scb == p_sco->p_curr_scb) 1250 { 1251 p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX; 1252 p_sco->p_curr_scb = NULL; 1253 } 1254 break; 1255 1256 default: 1257 APPL_TRACE_WARNING("BTA_AG_SCO_SHUTTING_ST: Ignoring event %d", event); 1258 break; 1259 } 1260 break; 1261 1262 default: 1263 break; 1264 } 1265#if (BTA_AG_SCO_DEBUG == TRUE) 1266 if (p_sco->state != in_state) 1267 { 1268 APPL_TRACE_EVENT("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]", 1269 bta_ag_sco_state_str(in_state), 1270 bta_ag_sco_state_str(p_sco->state), 1271 bta_ag_sco_evt_str(event)); 1272 } 1273#endif 1274 1275#if (BTM_WBS_INCLUDED == TRUE) 1276 if (p_cn_scb) 1277 { 1278 bta_ag_codec_negotiate(p_cn_scb); 1279 } 1280#endif 1281} 1282 1283/******************************************************************************* 1284** 1285** Function bta_ag_sco_is_open 1286** 1287** Description Check if sco is open for this scb. 1288** 1289** 1290** Returns true if sco open for this scb, false otherwise. 1291** 1292*******************************************************************************/ 1293bool bta_ag_sco_is_open(tBTA_AG_SCB *p_scb) 1294{ 1295 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) && 1296 (bta_ag_cb.sco.p_curr_scb == p_scb)); 1297} 1298 1299/******************************************************************************* 1300** 1301** Function bta_ag_sco_is_opening 1302** 1303** Description Check if sco is in Opening state. 1304** 1305** 1306** Returns true if sco is in Opening state for this scb, false otherwise. 1307** 1308*******************************************************************************/ 1309bool bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb) 1310{ 1311 return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) && 1312 (bta_ag_cb.sco.p_curr_scb == p_scb)); 1313} 1314 1315/******************************************************************************* 1316** 1317** Function bta_ag_sco_listen 1318** 1319** Description 1320** 1321** 1322** Returns void 1323** 1324*******************************************************************************/ 1325void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, 1326 UNUSED_ATTR tBTA_AG_DATA *p_data) 1327{ 1328 bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E); 1329} 1330 1331/******************************************************************************* 1332** 1333** Function bta_ag_sco_open 1334** 1335** Description 1336** 1337** 1338** Returns void 1339** 1340*******************************************************************************/ 1341void bta_ag_sco_open(tBTA_AG_SCB *p_scb, 1342 UNUSED_ATTR tBTA_AG_DATA *p_data) 1343{ 1344 uint8_t event; 1345 1346 /* if another scb using sco, this is a transfer */ 1347 if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb) 1348 { 1349 event = BTA_AG_SCO_XFER_E; 1350 } 1351 /* else it is an open */ 1352 else 1353 { 1354 event = BTA_AG_SCO_OPEN_E; 1355 } 1356 1357 bta_ag_sco_event(p_scb, event); 1358} 1359 1360/******************************************************************************* 1361** 1362** Function bta_ag_sco_close 1363** 1364** Description 1365** 1366** 1367** Returns void 1368** 1369*******************************************************************************/ 1370void bta_ag_sco_close(tBTA_AG_SCB *p_scb, 1371 UNUSED_ATTR tBTA_AG_DATA *p_data) 1372{ 1373 /* if scb is in use */ 1374#if (BTM_WBS_INCLUDED == TRUE) 1375 /* sco_idx is not allocated in SCO_CODEC_ST, we still need to move to listening state. */ 1376 if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) || (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST)) 1377#else 1378 if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) 1379#endif 1380 { 1381 APPL_TRACE_DEBUG("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx); 1382 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E); 1383 } 1384} 1385 1386#if (BTM_WBS_INCLUDED == TRUE) 1387 1388/******************************************************************************* 1389** 1390** Function bta_ag_sco_codec_nego 1391** 1392** Description 1393** 1394** 1395** Returns void 1396** 1397*******************************************************************************/ 1398void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, bool result) 1399{ 1400 if(result == true) 1401 { 1402 /* Subsequent sco connection will skip codec negotiation */ 1403 p_scb->codec_updated = false; 1404 1405 bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E); 1406 } 1407 else /* codec negotiation failed */ 1408 bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E); 1409} 1410#endif 1411 1412/******************************************************************************* 1413** 1414** Function bta_ag_sco_shutdown 1415** 1416** Description 1417** 1418** 1419** Returns void 1420** 1421*******************************************************************************/ 1422void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, 1423 UNUSED_ATTR tBTA_AG_DATA *p_data) 1424{ 1425 bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E); 1426} 1427 1428/******************************************************************************* 1429** 1430** Function bta_ag_sco_conn_open 1431** 1432** Description 1433** 1434** 1435** Returns void 1436** 1437*******************************************************************************/ 1438void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, 1439 UNUSED_ATTR tBTA_AG_DATA *p_data) 1440{ 1441 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E); 1442 1443 bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1444 1445#if (BTM_WBS_INCLUDED == TRUE) 1446 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON, 1447 p_scb->inuse_codec); 1448#else 1449 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON); 1450#endif 1451 1452#if (BTM_SCO_HCI_INCLUDED == TRUE) 1453 /* open SCO codec if SCO is routed through transport */ 1454 bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT); 1455#endif 1456 1457 /* call app callback */ 1458 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT); 1459 1460 p_scb->retry_with_sco_only = false; 1461#if (BTM_WBS_INCLUDED == TRUE) 1462 /* reset to mSBC T2 settings as the preferred */ 1463 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; 1464#endif 1465} 1466 1467/******************************************************************************* 1468** 1469** Function bta_ag_sco_conn_close 1470** 1471** Description 1472** 1473** 1474** Returns void 1475** 1476*******************************************************************************/ 1477void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, 1478 UNUSED_ATTR tBTA_AG_DATA *p_data) 1479{ 1480 uint16_t handle = bta_ag_scb_to_idx(p_scb); 1481 1482 /* clear current scb */ 1483 bta_ag_cb.sco.p_curr_scb = NULL; 1484 p_scb->sco_idx = BTM_INVALID_SCO_INDEX; 1485 1486#if (BTM_WBS_INCLUDED == TRUE) 1487 /* codec_fallback is set when AG is initiator and connection failed for mSBC. */ 1488 /* OR if codec is msbc and T2 settings failed, then retry Safe T1 settings */ 1489 if ((p_scb->codec_fallback && p_scb->svc_conn) || 1490 bta_ag_attempt_msbc_safe_settings(p_scb)) 1491 { 1492 bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E); 1493 } 1494 else if (p_scb->retry_with_sco_only && p_scb->svc_conn) 1495 { 1496 /* retry_with_sco_only is set when AG is initiator and connection failed for eSCO */ 1497 bta_ag_create_sco(p_scb, true); 1498 } 1499#else 1500 /* retry_with_sco_only, will be set only when AG is initiator 1501 ** and AG is first trying to establish an eSCO connection */ 1502 if (p_scb->retry_with_sco_only && p_scb->svc_conn) 1503 { 1504 bta_ag_create_sco(p_scb, true); 1505 } 1506#endif 1507 else 1508 { 1509 sco_state_t sco_state = bta_ag_cb.sco.p_xfer_scb ? SCO_STATE_OFF_TRANSFER : SCO_STATE_OFF; 1510#if (BTM_WBS_INCLUDED == TRUE) 1511 /* Indicate if the closing of audio is because of transfer */ 1512 bta_ag_co_audio_state(handle, p_scb->app_id, sco_state, p_scb->inuse_codec); 1513#else 1514 /* Indicate if the closing of audio is because of transfer */ 1515 bta_ag_co_audio_state(handle, p_scb->app_id, sco_state); 1516#endif 1517 bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E); 1518 1519 bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1520 1521 /* if av got suspended by this call, let it resume. */ 1522 /* In case call stays alive regardless of sco, av should not be affected. */ 1523 if(((p_scb->call_ind == BTA_AG_CALL_INACTIVE) && (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE)) 1524 || (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)) 1525 { 1526 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1527 } 1528 1529 /* call app callback */ 1530 bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT); 1531#if (BTM_WBS_INCLUDED == TRUE) 1532 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; 1533#endif 1534 } 1535 p_scb->retry_with_sco_only = false; 1536} 1537 1538/******************************************************************************* 1539** 1540** Function bta_ag_sco_conn_rsp 1541** 1542** Description Process the SCO connection request 1543** 1544** 1545** Returns void 1546** 1547*******************************************************************************/ 1548void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data) 1549{ 1550 tBTM_ESCO_PARAMS resp; 1551 uint8_t hci_status = HCI_SUCCESS; 1552#if (BTM_SCO_HCI_INCLUDED == TRUE) 1553 tBTA_CODEC_INFO codec_info = {BTA_SCO_CODEC_PCM}; 1554 uint32_t pcm_sample_rate; 1555#endif 1556 1557 if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST || 1558 bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST || 1559 bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST) 1560 { 1561 /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */ 1562 if (bta_ag_cb.sco.param_updated) 1563 { 1564 resp = bta_ag_cb.sco.params; 1565 } 1566 else 1567 { 1568 resp.rx_bw = BTM_64KBITS_RATE; 1569 resp.tx_bw = BTM_64KBITS_RATE; 1570 resp.max_latency = 12; 1571 resp.voice_contfmt = 0x60; 1572 resp.retrans_effort = BTM_ESCO_RETRANS_QUALITY; 1573 1574 if (p_data->link_type == BTM_LINK_TYPE_SCO) 1575 { 1576 resp.packet_types = (BTM_SCO_LINK_ONLY_MASK | 1577 BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | 1578 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | 1579 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 1580 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5); 1581 } 1582 else /* Allow controller to use all types available except 5-slot EDR */ 1583 { 1584 resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK | 1585 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 1586 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5); 1587 } 1588 } 1589 1590 /* tell sys to stop av if any */ 1591 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 1592 1593#if (BTM_WBS_INCLUDED == FALSE) 1594 /* Allow any platform specific pre-SCO set up to take place */ 1595 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP); 1596#else 1597 /* When HS initiated SCO, it cannot be WBS. */ 1598 /* Allow any platform specific pre-SCO set up to take place */ 1599 bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP, 1600 BTA_AG_CODEC_CVSD); 1601#endif 1602 1603#if (BTM_SCO_HCI_INCLUDED == TRUE) 1604 pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K; 1605 1606 /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ 1607 BTM_ConfigScoPath(bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id), 1608 bta_ag_sco_read_cback, NULL, true); 1609#endif 1610 } 1611 else 1612 hci_status = HCI_ERR_HOST_REJECT_DEVICE; 1613 1614#if (BTM_WBS_INCLUDED == TRUE) 1615 /* If SCO open was initiated from HS, it must be CVSD */ 1616 p_scb->inuse_codec = BTA_AG_CODEC_NONE; 1617#endif 1618 1619 BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp); 1620} 1621 1622/******************************************************************************* 1623** 1624** Function bta_ag_ci_sco_data 1625** 1626** Description Process the SCO data ready callin event 1627** 1628** 1629** Returns void 1630** 1631*******************************************************************************/ 1632void bta_ag_ci_sco_data(UNUSED_ATTR tBTA_AG_SCB *p_scb, 1633 UNUSED_ATTR tBTA_AG_DATA *p_data) 1634{ 1635#if (BTM_SCO_HCI_INCLUDED == TRUE) 1636 bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E); 1637#endif 1638} 1639 1640/******************************************************************************* 1641** 1642** Function bta_ag_set_esco_param 1643** 1644** Description Update esco parameters from script wrapper. 1645** 1646** 1647** Returns void 1648** 1649*******************************************************************************/ 1650void bta_ag_set_esco_param(bool set_reset, tBTM_ESCO_PARAMS *param) 1651{ 1652 if(set_reset == false) /* reset the parameters to default */ 1653 { 1654 bta_ag_cb.sco.param_updated = false; 1655 APPL_TRACE_DEBUG("bta_ag_set_esco_param : Resetting ESCO parameters to default"); 1656 } 1657 else 1658 { 1659 bta_ag_cb.sco.param_updated = true; 1660 bta_ag_cb.sco.params = *param; 1661 APPL_TRACE_DEBUG("bta_ag_set_esco_param : Setting ESCO parameters"); 1662 } 1663} 1664 1665/******************************************************************************* 1666** Debugging functions 1667*******************************************************************************/ 1668 1669#if (BTA_AG_SCO_DEBUG == TRUE) 1670static char *bta_ag_sco_evt_str(uint8_t event) 1671{ 1672 switch (event) 1673 { 1674 case BTA_AG_SCO_LISTEN_E: 1675 return "Listen Request"; 1676 case BTA_AG_SCO_OPEN_E: 1677 return "Open Request"; 1678 case BTA_AG_SCO_XFER_E: 1679 return "Transfer Request"; 1680#if (BTM_WBS_INCLUDED == TRUE) 1681 case BTA_AG_SCO_CN_DONE_E: 1682 return "Codec Negotiation Done"; 1683 case BTA_AG_SCO_REOPEN_E: 1684 return "Reopen Request"; 1685#endif 1686 case BTA_AG_SCO_CLOSE_E: 1687 return "Close Request"; 1688 case BTA_AG_SCO_SHUTDOWN_E: 1689 return "Shutdown Request"; 1690 case BTA_AG_SCO_CONN_OPEN_E: 1691 return "Opened"; 1692 case BTA_AG_SCO_CONN_CLOSE_E: 1693 return "Closed"; 1694 case BTA_AG_SCO_CI_DATA_E : 1695 return "Sco Data"; 1696 default: 1697 return "Unknown SCO Event"; 1698 } 1699} 1700 1701static char *bta_ag_sco_state_str(uint8_t state) 1702{ 1703 switch (state) 1704 { 1705 case BTA_AG_SCO_SHUTDOWN_ST: 1706 return "Shutdown"; 1707 case BTA_AG_SCO_LISTEN_ST: 1708 return "Listening"; 1709#if (BTM_WBS_INCLUDED == TRUE) 1710 case BTA_AG_SCO_CODEC_ST: 1711 return "Codec Negotiation"; 1712#endif 1713 case BTA_AG_SCO_OPENING_ST: 1714 return "Opening"; 1715 case BTA_AG_SCO_OPEN_CL_ST: 1716 return "Open while closing"; 1717 case BTA_AG_SCO_OPEN_XFER_ST: 1718 return "Opening while Transferring"; 1719 case BTA_AG_SCO_OPEN_ST: 1720 return "Open"; 1721 case BTA_AG_SCO_CLOSING_ST: 1722 return "Closing"; 1723 case BTA_AG_SCO_CLOSE_OP_ST: 1724 return "Close while Opening"; 1725 case BTA_AG_SCO_CLOSE_XFER_ST: 1726 return "Close while Transferring"; 1727 case BTA_AG_SCO_SHUTTING_ST: 1728 return "Shutting Down"; 1729 default: 1730 return "Unknown SCO State"; 1731 } 1732} 1733 1734#endif 1735