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