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