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