1/****************************************************************************** 2 * 3 * Copyright (c) 2014 The Android Open Source Project 4 * Copyright (C) 2004-2012 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 20#include "bta_hf_client_int.h" 21#include <bt_trace.h> 22#include <string.h> 23#include "bt_utils.h" 24 25#define BTA_HF_CLIENT_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \ 26 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \ 27 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \ 28 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5) 29 30static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = { 31 /* SCO CVSD */ 32 { 33 .rx_bw = BTM_64KBITS_RATE, 34 .tx_bw = BTM_64KBITS_RATE, 35 .max_latency = 10, 36 .voice_contfmt = BTM_VOICE_SETTING_CVSD, 37 .packet_types = (BTM_SCO_LINK_ONLY_MASK | 38 BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | 39 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | 40 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 41 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), 42 .retrans_effort = BTM_ESCO_RETRANS_POWER, 43 }, 44 /* ESCO CVSD */ 45 { 46 .rx_bw = BTM_64KBITS_RATE, 47 .tx_bw = BTM_64KBITS_RATE, 48 .max_latency = 10, 49 .voice_contfmt = BTM_VOICE_SETTING_CVSD, 50 /* Allow controller to use all types available except 5-slot EDR */ 51 .packet_types = (BTM_SCO_LINK_ALL_PKT_MASK | 52 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 53 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), 54 .retrans_effort = BTM_ESCO_RETRANS_POWER, 55 }, 56 /* ESCO mSBC */ 57 { 58 .rx_bw = BTM_64KBITS_RATE, 59 .tx_bw = BTM_64KBITS_RATE, 60 .max_latency = 13, 61 .voice_contfmt = BTM_VOICE_SETTING_TRANS, 62 /* Packet Types : EV3 + 2-EV3 */ 63 .packet_types = (BTM_SCO_PKT_TYPES_MASK_EV3 | 64 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | 65 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 66 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), 67 .retrans_effort = BTM_ESCO_RETRANS_QUALITY, 68 } 69}; 70 71enum 72{ 73 BTA_HF_CLIENT_SCO_LISTEN_E, 74 BTA_HF_CLIENT_SCO_OPEN_E, /* open request */ 75 BTA_HF_CLIENT_SCO_CLOSE_E, /* close request */ 76 BTA_HF_CLIENT_SCO_SHUTDOWN_E, /* shutdown request */ 77 BTA_HF_CLIENT_SCO_CONN_OPEN_E, /* sco opened */ 78 BTA_HF_CLIENT_SCO_CONN_CLOSE_E, /* sco closed */ 79}; 80 81/******************************************************************************* 82** 83** Function bta_hf_client_remove_sco 84** 85** Description Removes the specified SCO from the system. 86** If only_active is TRUE, then SCO is only removed if connected 87** 88** Returns BOOLEAN - TRUE if Sco removal was started 89** 90*******************************************************************************/ 91static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active) 92{ 93 BOOLEAN removed_started = FALSE; 94 tBTM_STATUS status; 95 96 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active); 97 98 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) 99 { 100 status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx); 101 102 APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status); 103 104 if (status == BTM_CMD_STARTED) 105 { 106 removed_started = TRUE; 107 } 108 /* If no connection reset the sco handle */ 109 else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) 110 { 111 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; 112 } 113 } 114 return removed_started; 115} 116 117/******************************************************************************* 118** 119** Function bta_hf_client_cback_sco 120** 121** Description Call application callback function with SCO event. 122** 123** 124** Returns void 125** 126*******************************************************************************/ 127void bta_hf_client_cback_sco(UINT8 event) 128{ 129 tBTA_HF_CLIENT evt; 130 131 memset(&evt, 0, sizeof(evt)); 132 133 /* call app cback */ 134 (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT *) &evt); 135} 136 137/******************************************************************************* 138** 139** Function bta_hf_client_sco_conn_rsp 140** 141** Description Process the SCO connection request 142** 143** 144** Returns void 145** 146*******************************************************************************/ 147static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data) 148{ 149 tBTM_ESCO_PARAMS resp; 150 UINT8 hci_status = HCI_SUCCESS; 151 152 APPL_TRACE_DEBUG("%s", __FUNCTION__); 153 154 if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST) 155 { 156 if (p_data->link_type == BTM_LINK_TYPE_SCO) 157 { 158 resp = bta_hf_client_esco_params[0]; 159 } 160 else 161 { 162 resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec]; 163 } 164 165 /* tell sys to stop av if any */ 166 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 167 } 168 else 169 { 170 hci_status = HCI_ERR_HOST_REJECT_DEVICE; 171 } 172 173 BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp); 174} 175 176/******************************************************************************* 177** 178** Function bta_hf_client_sco_connreq_cback 179** 180** Description BTM eSCO connection requests and eSCO change requests 181** Only the connection requests are processed by BTA. 182** 183** Returns void 184** 185*******************************************************************************/ 186static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) 187{ 188 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event); 189 190 if (event != BTM_ESCO_CONN_REQ_EVT) 191 { 192 return; 193 } 194 195 /* TODO check remote bdaddr, should allow connect only from device with 196 * active SLC */ 197 198 bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx; 199 200 bta_hf_client_sco_conn_rsp(&p_data->conn_evt); 201 202 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; 203} 204 205/******************************************************************************* 206** 207** Function bta_hf_client_sco_conn_cback 208** 209** Description BTM SCO connection callback. 210** 211** 212** Returns void 213** 214*******************************************************************************/ 215static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) 216{ 217 UINT8 *rem_bd; 218 219 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx); 220 221 rem_bd = BTM_ReadScoBdAddr(sco_idx); 222 223 if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && 224 bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) 225 { 226 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR)); 227 p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; 228 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; 229 bta_sys_sendmsg(p_buf); 230 } 231 /* no match found; disconnect sco, init sco variables */ 232 else 233 { 234 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 235 BTM_RemoveSco(sco_idx); 236 } 237} 238 239/******************************************************************************* 240** 241** Function bta_hf_client_sco_disc_cback 242** 243** Description BTM SCO disconnection callback. 244** 245** 246** Returns void 247** 248*******************************************************************************/ 249static void bta_hf_client_sco_disc_cback(UINT16 sco_idx) 250{ 251 APPL_TRACE_DEBUG("%s %d", __func__, sco_idx); 252 253 if (bta_hf_client_cb.scb.sco_idx == sco_idx) { 254 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR)); 255 p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT; 256 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;; 257 bta_sys_sendmsg(p_buf); 258 } 259} 260 261/******************************************************************************* 262** 263** Function bta_hf_client_create_sco 264** 265** Description 266** 267** 268** Returns void 269** 270*******************************************************************************/ 271static void bta_hf_client_sco_create(BOOLEAN is_orig) 272{ 273 tBTM_STATUS status; 274 UINT8 *p_bd_addr = NULL; 275 tBTM_ESCO_PARAMS params; 276 277 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig); 278 279 /* Make sure this sco handle is not already in use */ 280 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) 281 { 282 APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__, 283 bta_hf_client_cb.scb.sco_idx); 284 return; 285 } 286 287 params = bta_hf_client_esco_params[1]; 288 289 /* if initiating set current scb and peer bd addr */ 290 if (is_orig) 291 { 292 /* Attempt to use eSCO if remote host supports HFP >= 1.5 */ 293 if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only) 294 { 295 BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms); 296 /* If ESCO or EDR ESCO, retry with SCO only in case of failure */ 297 if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK) 298 ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO)) 299 { 300 bta_hf_client_cb.scb.retry_with_sco_only = TRUE; 301 APPL_TRACE_API("Setting retry_with_sco_only to TRUE"); 302 } 303 } 304 else 305 { 306 if(bta_hf_client_cb.scb.retry_with_sco_only) 307 APPL_TRACE_API("retrying with SCO only"); 308 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 309 310 BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms); 311 } 312 313 /* tell sys to stop av if any */ 314 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 315 } 316 else 317 { 318 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 319 } 320 321 p_bd_addr = bta_hf_client_cb.scb.peer_addr; 322 323 status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types, 324 &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback, 325 bta_hf_client_sco_disc_cback); 326 if (status == BTM_CMD_STARTED && !is_orig) 327 { 328 if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback)) 329 APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__); 330 } 331 332 APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x", 333 __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx, 334 status, params.packet_types); 335} 336 337 338/******************************************************************************* 339** 340** Function bta_hf_client_sco_event 341** 342** Description Handle SCO events 343** 344** 345** Returns void 346** 347*******************************************************************************/ 348static void bta_hf_client_sco_event(UINT8 event) 349{ 350 APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__, 351 bta_hf_client_cb.scb.sco_state, event); 352 353 switch (bta_hf_client_cb.scb.sco_state) 354 { 355 case BTA_HF_CLIENT_SCO_SHUTDOWN_ST: 356 switch (event) 357 { 358 case BTA_HF_CLIENT_SCO_LISTEN_E: 359 /* create sco listen connection */ 360 bta_hf_client_sco_create(FALSE); 361 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 362 break; 363 364 default: 365 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event); 366 break; 367 } 368 break; 369 370 case BTA_HF_CLIENT_SCO_LISTEN_ST: 371 switch (event) 372 { 373 case BTA_HF_CLIENT_SCO_LISTEN_E: 374 /* create sco listen connection (Additional channel) */ 375 bta_hf_client_sco_create(FALSE); 376 break; 377 378 case BTA_HF_CLIENT_SCO_OPEN_E: 379 /* remove listening connection */ 380 bta_hf_client_sco_remove(FALSE); 381 382 /* create sco connection to peer */ 383 bta_hf_client_sco_create(TRUE); 384 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; 385 break; 386 387 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 388 /* remove listening connection */ 389 bta_hf_client_sco_remove(FALSE); 390 391 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 392 break; 393 394 case BTA_HF_CLIENT_SCO_CLOSE_E: 395 /* remove listening connection */ 396 /* Ignore the event. We need to keep listening SCO for the active SLC */ 397 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); 398 break; 399 400 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 401 /* sco failed; create sco listen connection */ 402 bta_hf_client_sco_create(FALSE); 403 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 404 break; 405 406 default: 407 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); 408 break; 409 } 410 break; 411 412 case BTA_HF_CLIENT_SCO_OPENING_ST: 413 switch (event) 414 { 415 case BTA_HF_CLIENT_SCO_CLOSE_E: 416 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST; 417 break; 418 419 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 420 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 421 break; 422 423 case BTA_HF_CLIENT_SCO_CONN_OPEN_E: 424 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST; 425 break; 426 427 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 428 /* sco failed; create sco listen connection */ 429 bta_hf_client_sco_create(FALSE); 430 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 431 break; 432 433 default: 434 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event); 435 break; 436 } 437 break; 438 439 case BTA_HF_CLIENT_SCO_OPEN_CL_ST: 440 switch (event) 441 { 442 case BTA_HF_CLIENT_SCO_OPEN_E: 443 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; 444 break; 445 446 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 447 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 448 break; 449 450 case BTA_HF_CLIENT_SCO_CONN_OPEN_E: 451 /* close sco connection */ 452 bta_hf_client_sco_remove(TRUE); 453 454 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; 455 break; 456 457 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 458 /* sco failed; create sco listen connection */ 459 460 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 461 break; 462 463 default: 464 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event); 465 break; 466 } 467 break; 468 469 case BTA_HF_CLIENT_SCO_OPEN_ST: 470 switch (event) 471 { 472 case BTA_HF_CLIENT_SCO_CLOSE_E: 473 /* close sco connection if active */ 474 if (bta_hf_client_sco_remove(TRUE)) 475 { 476 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; 477 } 478 break; 479 480 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 481 /* remove all listening connections */ 482 bta_hf_client_sco_remove(FALSE); 483 484 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 485 break; 486 487 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 488 /* peer closed sco; create sco listen connection */ 489 bta_hf_client_sco_create(FALSE); 490 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 491 break; 492 493 default: 494 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event); 495 break; 496 } 497 break; 498 499 case BTA_HF_CLIENT_SCO_CLOSING_ST: 500 switch (event) 501 { 502 case BTA_HF_CLIENT_SCO_OPEN_E: 503 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST; 504 break; 505 506 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 507 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 508 break; 509 510 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 511 /* peer closed sco; create sco listen connection */ 512 bta_hf_client_sco_create(FALSE); 513 514 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 515 break; 516 517 default: 518 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event); 519 break; 520 } 521 break; 522 523 case BTA_HF_CLIENT_SCO_CLOSE_OP_ST: 524 switch (event) 525 { 526 case BTA_HF_CLIENT_SCO_CLOSE_E: 527 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; 528 break; 529 530 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 531 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 532 break; 533 534 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 535 /* open sco connection */ 536 bta_hf_client_sco_create(TRUE); 537 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; 538 break; 539 540 default: 541 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event); 542 break; 543 } 544 break; 545 546 case BTA_HF_CLIENT_SCO_SHUTTING_ST: 547 switch (event) 548 { 549 case BTA_HF_CLIENT_SCO_CONN_OPEN_E: 550 /* close sco connection; wait for conn close event */ 551 bta_hf_client_sco_remove(TRUE); 552 break; 553 554 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 555 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 556 break; 557 558 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 559 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 560 break; 561 562 default: 563 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event); 564 break; 565 } 566 break; 567 568 default: 569 break; 570 } 571} 572 573/******************************************************************************* 574** 575** Function bta_hf_client_sco_listen 576** 577** Description Initialize SCO listener 578** 579** 580** Returns void 581** 582*******************************************************************************/ 583void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data) 584{ 585 UNUSED(p_data); 586 587 APPL_TRACE_DEBUG("%s", __FUNCTION__); 588 589 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E); 590} 591 592/******************************************************************************* 593** 594** Function bta_hf_client_sco_shutdown 595** 596** Description 597** 598** 599** Returns void 600** 601*******************************************************************************/ 602void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data) 603{ 604 UNUSED(p_data); 605 606 APPL_TRACE_DEBUG("%s", __FUNCTION__); 607 608 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E); 609} 610 611/******************************************************************************* 612** 613** Function bta_hf_client_sco_conn_open 614** 615** Description 616** 617** 618** Returns void 619** 620*******************************************************************************/ 621void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data) 622{ 623 UNUSED(p_data); 624 625 APPL_TRACE_DEBUG("%s", __FUNCTION__); 626 627 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E); 628 629 bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 630 631 if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) 632 { 633 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT); 634 } 635 else 636 { 637 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT); 638 } 639 640 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 641} 642 643/******************************************************************************* 644** 645** Function bta_hf_client_sco_conn_close 646** 647** Description 648** 649** 650** Returns void 651** 652*******************************************************************************/ 653void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data) 654{ 655 APPL_TRACE_DEBUG("%s", __FUNCTION__); 656 657 /* clear current scb */ 658 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; 659 660 /* retry_with_sco_only, will be set only when initiator 661 ** and HFClient is first trying to establish an eSCO connection */ 662 if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn) 663 { 664 bta_hf_client_sco_create(TRUE); 665 } 666 else 667 { 668 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E); 669 670 bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 671 672 bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 673 674 /* call app callback */ 675 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT); 676 677 if (bta_hf_client_cb.scb.sco_close_rfc == TRUE) 678 { 679 bta_hf_client_cb.scb.sco_close_rfc = FALSE; 680 bta_hf_client_rfc_do_close(p_data); 681 } 682 } 683 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 684} 685 686/******************************************************************************* 687** 688** Function bta_hf_client_sco_open 689** 690** Description 691** 692** 693** Returns void 694** 695*******************************************************************************/ 696void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data) 697{ 698 UNUSED(p_data); 699 700 APPL_TRACE_DEBUG("%s", __FUNCTION__); 701 702 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E); 703} 704 705/******************************************************************************* 706** 707** Function bta_hf_client_sco_close 708** 709** Description 710** 711** 712** Returns void 713** 714*******************************************************************************/ 715void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data) 716{ 717 UNUSED(p_data); 718 719 APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx); 720 721 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) 722 { 723 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E); 724 } 725} 726