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