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 BT_HDR *p_buf; 218 UINT8 *rem_bd; 219 220 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx); 221 222 rem_bd = BTM_ReadScoBdAddr(sco_idx); 223 224 if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && 225 bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) 226 { 227 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) 228 { 229 p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; 230 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; 231 bta_sys_sendmsg(p_buf); 232 } 233 } 234 /* no match found; disconnect sco, init sco variables */ 235 else 236 { 237 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 238 BTM_RemoveSco(sco_idx); 239 } 240} 241 242/******************************************************************************* 243** 244** Function bta_hf_client_sco_disc_cback 245** 246** Description BTM SCO disconnection callback. 247** 248** 249** Returns void 250** 251*******************************************************************************/ 252static void bta_hf_client_sco_disc_cback(UINT16 sco_idx) 253{ 254 BT_HDR *p_buf; 255 256 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx); 257 258 if (bta_hf_client_cb.scb.sco_idx == sco_idx) 259 { 260 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) 261 { 262 p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT; 263 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;; 264 bta_sys_sendmsg(p_buf); 265 } 266 } 267} 268 269/******************************************************************************* 270** 271** Function bta_hf_client_create_sco 272** 273** Description 274** 275** 276** Returns void 277** 278*******************************************************************************/ 279static void bta_hf_client_sco_create(BOOLEAN is_orig) 280{ 281 tBTM_STATUS status; 282 UINT8 *p_bd_addr = NULL; 283 tBTM_ESCO_PARAMS params; 284 285 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig); 286 287 /* Make sure this sco handle is not already in use */ 288 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) 289 { 290 APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__, 291 bta_hf_client_cb.scb.sco_idx); 292 return; 293 } 294 295 params = bta_hf_client_esco_params[1]; 296 297 /* if initiating set current scb and peer bd addr */ 298 if (is_orig) 299 { 300 /* Attempt to use eSCO if remote host supports HFP >= 1.5 */ 301 if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only) 302 { 303 BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms); 304 /* If ESCO or EDR ESCO, retry with SCO only in case of failure */ 305 if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK) 306 ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO)) 307 { 308 bta_hf_client_cb.scb.retry_with_sco_only = TRUE; 309 APPL_TRACE_API("Setting retry_with_sco_only to TRUE"); 310 } 311 } 312 else 313 { 314 if(bta_hf_client_cb.scb.retry_with_sco_only) 315 APPL_TRACE_API("retrying with SCO only"); 316 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 317 318 BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms); 319 } 320 321 /* tell sys to stop av if any */ 322 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 323 } 324 else 325 { 326 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 327 } 328 329 p_bd_addr = bta_hf_client_cb.scb.peer_addr; 330 331 status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types, 332 &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback, 333 bta_hf_client_sco_disc_cback); 334 if (status == BTM_CMD_STARTED && !is_orig) 335 { 336 if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback)) 337 APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__); 338 } 339 340 APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x", 341 __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx, 342 status, params.packet_types); 343} 344 345 346/******************************************************************************* 347** 348** Function bta_hf_client_sco_event 349** 350** Description Handle SCO events 351** 352** 353** Returns void 354** 355*******************************************************************************/ 356static void bta_hf_client_sco_event(UINT8 event) 357{ 358 APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__, 359 bta_hf_client_cb.scb.sco_state, event); 360 361 switch (bta_hf_client_cb.scb.sco_state) 362 { 363 case BTA_HF_CLIENT_SCO_SHUTDOWN_ST: 364 switch (event) 365 { 366 case BTA_HF_CLIENT_SCO_LISTEN_E: 367 /* create sco listen connection */ 368 bta_hf_client_sco_create(FALSE); 369 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 370 break; 371 372 default: 373 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event); 374 break; 375 } 376 break; 377 378 case BTA_HF_CLIENT_SCO_LISTEN_ST: 379 switch (event) 380 { 381 case BTA_HF_CLIENT_SCO_LISTEN_E: 382 /* create sco listen connection (Additional channel) */ 383 bta_hf_client_sco_create(FALSE); 384 break; 385 386 case BTA_HF_CLIENT_SCO_OPEN_E: 387 /* remove listening connection */ 388 bta_hf_client_sco_remove(FALSE); 389 390 /* create sco connection to peer */ 391 bta_hf_client_sco_create(TRUE); 392 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; 393 break; 394 395 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 396 /* remove listening connection */ 397 bta_hf_client_sco_remove(FALSE); 398 399 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 400 break; 401 402 case BTA_HF_CLIENT_SCO_CLOSE_E: 403 /* remove listening connection */ 404 /* Ignore the event. We need to keep listening SCO for the active SLC */ 405 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); 406 break; 407 408 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 409 /* sco failed; create sco listen connection */ 410 bta_hf_client_sco_create(FALSE); 411 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 412 break; 413 414 default: 415 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); 416 break; 417 } 418 break; 419 420 case BTA_HF_CLIENT_SCO_OPENING_ST: 421 switch (event) 422 { 423 case BTA_HF_CLIENT_SCO_CLOSE_E: 424 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST; 425 break; 426 427 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 428 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 429 break; 430 431 case BTA_HF_CLIENT_SCO_CONN_OPEN_E: 432 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST; 433 break; 434 435 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 436 /* sco failed; create sco listen connection */ 437 bta_hf_client_sco_create(FALSE); 438 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 439 break; 440 441 default: 442 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event); 443 break; 444 } 445 break; 446 447 case BTA_HF_CLIENT_SCO_OPEN_CL_ST: 448 switch (event) 449 { 450 case BTA_HF_CLIENT_SCO_OPEN_E: 451 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; 452 break; 453 454 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 455 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 456 break; 457 458 case BTA_HF_CLIENT_SCO_CONN_OPEN_E: 459 /* close sco connection */ 460 bta_hf_client_sco_remove(TRUE); 461 462 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; 463 break; 464 465 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 466 /* sco failed; create sco listen connection */ 467 468 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 469 break; 470 471 default: 472 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event); 473 break; 474 } 475 break; 476 477 case BTA_HF_CLIENT_SCO_OPEN_ST: 478 switch (event) 479 { 480 case BTA_HF_CLIENT_SCO_CLOSE_E: 481 /* close sco connection if active */ 482 if (bta_hf_client_sco_remove(TRUE)) 483 { 484 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; 485 } 486 break; 487 488 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 489 /* remove all listening connections */ 490 bta_hf_client_sco_remove(FALSE); 491 492 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 493 break; 494 495 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 496 /* peer closed sco; create sco listen connection */ 497 bta_hf_client_sco_create(FALSE); 498 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 499 break; 500 501 default: 502 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event); 503 break; 504 } 505 break; 506 507 case BTA_HF_CLIENT_SCO_CLOSING_ST: 508 switch (event) 509 { 510 case BTA_HF_CLIENT_SCO_OPEN_E: 511 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST; 512 break; 513 514 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 515 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 516 break; 517 518 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 519 /* peer closed sco; create sco listen connection */ 520 bta_hf_client_sco_create(FALSE); 521 522 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; 523 break; 524 525 default: 526 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event); 527 break; 528 } 529 break; 530 531 case BTA_HF_CLIENT_SCO_CLOSE_OP_ST: 532 switch (event) 533 { 534 case BTA_HF_CLIENT_SCO_CLOSE_E: 535 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; 536 break; 537 538 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 539 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; 540 break; 541 542 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 543 /* open sco connection */ 544 bta_hf_client_sco_create(TRUE); 545 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; 546 break; 547 548 default: 549 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event); 550 break; 551 } 552 break; 553 554 case BTA_HF_CLIENT_SCO_SHUTTING_ST: 555 switch (event) 556 { 557 case BTA_HF_CLIENT_SCO_CONN_OPEN_E: 558 /* close sco connection; wait for conn close event */ 559 bta_hf_client_sco_remove(TRUE); 560 break; 561 562 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: 563 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 564 break; 565 566 case BTA_HF_CLIENT_SCO_SHUTDOWN_E: 567 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; 568 break; 569 570 default: 571 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event); 572 break; 573 } 574 break; 575 576 default: 577 break; 578 } 579} 580 581/******************************************************************************* 582** 583** Function bta_hf_client_sco_listen 584** 585** Description Initialize SCO listener 586** 587** 588** Returns void 589** 590*******************************************************************************/ 591void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data) 592{ 593 UNUSED(p_data); 594 595 APPL_TRACE_DEBUG("%s", __FUNCTION__); 596 597 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E); 598} 599 600/******************************************************************************* 601** 602** Function bta_hf_client_sco_shutdown 603** 604** Description 605** 606** 607** Returns void 608** 609*******************************************************************************/ 610void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data) 611{ 612 UNUSED(p_data); 613 614 APPL_TRACE_DEBUG("%s", __FUNCTION__); 615 616 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E); 617} 618 619/******************************************************************************* 620** 621** Function bta_hf_client_sco_conn_open 622** 623** Description 624** 625** 626** Returns void 627** 628*******************************************************************************/ 629void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data) 630{ 631 UNUSED(p_data); 632 633 APPL_TRACE_DEBUG("%s", __FUNCTION__); 634 635 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E); 636 637 bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 638 639 if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) 640 { 641 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT); 642 } 643 else 644 { 645 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT); 646 } 647 648 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 649} 650 651/******************************************************************************* 652** 653** Function bta_hf_client_sco_conn_close 654** 655** Description 656** 657** 658** Returns void 659** 660*******************************************************************************/ 661void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data) 662{ 663 APPL_TRACE_DEBUG("%s", __FUNCTION__); 664 665 /* clear current scb */ 666 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; 667 668 /* retry_with_sco_only, will be set only when initiator 669 ** and HFClient is first trying to establish an eSCO connection */ 670 if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn) 671 { 672 bta_hf_client_sco_create(TRUE); 673 } 674 else 675 { 676 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E); 677 678 bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 679 680 bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 681 682 /* call app callback */ 683 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT); 684 685 if (bta_hf_client_cb.scb.sco_close_rfc == TRUE) 686 { 687 bta_hf_client_cb.scb.sco_close_rfc = FALSE; 688 bta_hf_client_rfc_do_close(p_data); 689 } 690 } 691 bta_hf_client_cb.scb.retry_with_sco_only = FALSE; 692} 693 694/******************************************************************************* 695** 696** Function bta_hf_client_sco_open 697** 698** Description 699** 700** 701** Returns void 702** 703*******************************************************************************/ 704void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data) 705{ 706 UNUSED(p_data); 707 708 APPL_TRACE_DEBUG("%s", __FUNCTION__); 709 710 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E); 711} 712 713/******************************************************************************* 714** 715** Function bta_hf_client_sco_close 716** 717** Description 718** 719** 720** Returns void 721** 722*******************************************************************************/ 723void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data) 724{ 725 UNUSED(p_data); 726 727 APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx); 728 729 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) 730 { 731 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E); 732 } 733} 734