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