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 30 static 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 71 enum 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 *******************************************************************************/ 91 static 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 *******************************************************************************/ 127 void 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 *******************************************************************************/ 147 static 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 *******************************************************************************/ 186 static 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 *******************************************************************************/ 215 static 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 *******************************************************************************/ 249 static 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 *******************************************************************************/ 271 static 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 *******************************************************************************/ 348 static 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 *******************************************************************************/ 583 void 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 *******************************************************************************/ 602 void 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 *******************************************************************************/ 621 void 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 *******************************************************************************/ 653 void 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 *******************************************************************************/ 696 void 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 *******************************************************************************/ 715 void 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