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