1 /****************************************************************************** 2 * 3 * Copyright (C) 2003-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 action functions for the audio gateway. 22 * 23 ******************************************************************************/ 24 25 #include "bta_api.h" 26 #include "bd.h" 27 #include "bta_sys.h" 28 #include "bta_ag_api.h" 29 #include "bta_ag_co.h" 30 #include "bta_ag_int.h" 31 #include "port_api.h" 32 #include "utl.h" 33 #include <string.h> 34 #include "bta_dm_int.h" 35 #include "l2c_api.h" 36 37 /***************************************************************************** 38 ** Constants 39 *****************************************************************************/ 40 41 /* maximum length of data to read from RFCOMM */ 42 #define BTA_AG_RFC_READ_MAX 512 43 44 /* maximum AT command length */ 45 #define BTA_AG_CMD_MAX 512 46 47 const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX] = 48 { 49 UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, 50 UUID_SERVCLASS_AG_HANDSFREE 51 }; 52 53 const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX] = 54 { 55 BTM_SEC_SERVICE_HEADSET_AG, 56 BTM_SEC_SERVICE_AG_HANDSFREE 57 }; 58 59 const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] = 60 { 61 BTA_HSP_SERVICE_ID, 62 BTA_HFP_SERVICE_ID 63 }; 64 65 const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] = 66 { 67 BTA_HSP_SERVICE_MASK, 68 BTA_HFP_SERVICE_MASK 69 }; 70 71 typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, 72 char *p_arg, INT16 int_arg); 73 74 const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] = 75 { 76 bta_ag_at_hsp_cback, 77 bta_ag_at_hfp_cback 78 }; 79 80 /******************************************************************************* 81 ** 82 ** Function bta_ag_cback_open 83 ** 84 ** Description Send open callback event to application. 85 ** 86 ** 87 ** Returns void 88 ** 89 *******************************************************************************/ 90 static void bta_ag_cback_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data, tBTA_AG_STATUS status) 91 { 92 tBTA_AG_OPEN open; 93 94 /* call app callback with open event */ 95 open.hdr.handle = bta_ag_scb_to_idx(p_scb); 96 open.hdr.app_id = p_scb->app_id; 97 open.status = status; 98 open.service_id = bta_ag_svc_id[p_scb->conn_service]; 99 if(p_data) 100 { 101 /* if p_data is provided then we need to pick the bd address from the open api structure */ 102 bdcpy(open.bd_addr, p_data->api_open.bd_addr); 103 } 104 else 105 { 106 bdcpy(open.bd_addr, p_scb->peer_addr); 107 } 108 109 (*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG *) &open); 110 } 111 112 /******************************************************************************* 113 ** 114 ** Function bta_ag_register 115 ** 116 ** Description This function initializes values of the AG cb and sets up 117 ** the SDP record for the services. 118 ** 119 ** 120 ** Returns void 121 ** 122 *******************************************************************************/ 123 void bta_ag_register(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 124 { 125 tBTA_AG_REGISTER reg; 126 127 /* initialize control block */ 128 p_scb->reg_services = p_data->api_register.services; 129 p_scb->serv_sec_mask = p_data->api_register.sec_mask; 130 p_scb->features = p_data->api_register.features; 131 p_scb->app_id = p_data->api_register.app_id; 132 133 /* create SDP records */ 134 bta_ag_create_records(p_scb, p_data); 135 136 /* start RFCOMM servers */ 137 bta_ag_start_servers(p_scb, p_scb->reg_services); 138 139 /* call app callback with register event */ 140 reg.hdr.handle = bta_ag_scb_to_idx(p_scb); 141 reg.hdr.app_id = p_scb->app_id; 142 reg.status = BTA_AG_SUCCESS; 143 (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG *) ®); 144 } 145 146 /******************************************************************************* 147 ** 148 ** Function bta_ag_deregister 149 ** 150 ** Description This function removes the sdp records, closes the RFCOMM 151 ** servers, and deallocates the service control block. 152 ** 153 ** 154 ** Returns void 155 ** 156 *******************************************************************************/ 157 void bta_ag_deregister(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 158 { 159 /* set dealloc */ 160 p_scb->dealloc = TRUE; 161 162 /* remove sdp records */ 163 bta_ag_del_records(p_scb, p_data); 164 165 /* remove rfcomm servers */ 166 bta_ag_close_servers(p_scb, p_scb->reg_services); 167 168 /* dealloc */ 169 bta_ag_scb_dealloc(p_scb); 170 } 171 172 /******************************************************************************* 173 ** 174 ** Function bta_ag_start_dereg 175 ** 176 ** Description Start a deregister event. 177 ** 178 ** 179 ** Returns void 180 ** 181 *******************************************************************************/ 182 void bta_ag_start_dereg(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 183 { 184 /* set dealloc */ 185 p_scb->dealloc = TRUE; 186 187 /* remove sdp records */ 188 bta_ag_del_records(p_scb, p_data); 189 } 190 191 /******************************************************************************* 192 ** 193 ** Function bta_ag_start_open 194 ** 195 ** Description This starts an AG open. 196 ** 197 ** 198 ** Returns void 199 ** 200 *******************************************************************************/ 201 void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 202 { 203 BD_ADDR pending_bd_addr; 204 205 /* store parameters */ 206 if (p_data) 207 { 208 bdcpy(p_scb->peer_addr, p_data->api_open.bd_addr); 209 p_scb->open_services = p_data->api_open.services; 210 p_scb->cli_sec_mask = p_data->api_open.sec_mask; 211 } 212 213 /* Check if RFCOMM has any incoming connection to avoid collision. */ 214 if (PORT_IsOpening (pending_bd_addr)) 215 { 216 /* Let the incoming connection goes through. */ 217 /* Issue collision for this scb for now. */ 218 /* We will decide what to do when we find incoming connetion later. */ 219 bta_ag_collision_cback (0, BTA_ID_AG, 0, p_scb->peer_addr); 220 return; 221 } 222 223 /* close servers */ 224 bta_ag_close_servers(p_scb, p_scb->reg_services); 225 226 /* set role */ 227 p_scb->role = BTA_AG_INT; 228 229 /* do service search */ 230 bta_ag_do_disc(p_scb, p_scb->open_services); 231 } 232 233 /******************************************************************************* 234 ** 235 ** Function bta_ag_disc_int_res 236 ** 237 ** Description This function handles a discovery result when initiator. 238 ** 239 ** 240 ** Returns void 241 ** 242 *******************************************************************************/ 243 void bta_ag_disc_int_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 244 { 245 UINT16 event = BTA_AG_DISC_FAIL_EVT; 246 247 APPL_TRACE_DEBUG ("bta_ag_disc_int_res: Status: %d", p_data->disc_result.status); 248 249 /* if found service */ 250 if (p_data->disc_result.status == SDP_SUCCESS || 251 p_data->disc_result.status == SDP_DB_FULL) 252 { 253 /* get attributes */ 254 if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services)) 255 { 256 /* set connected service */ 257 p_scb->conn_service = bta_ag_service_to_idx(p_scb->open_services); 258 259 /* send ourselves sdp ok event */ 260 event = BTA_AG_DISC_OK_EVT; 261 } 262 } 263 264 /* free discovery db */ 265 bta_ag_free_db(p_scb, p_data); 266 267 /* if service not found check if we should search for other service */ 268 if ((event == BTA_AG_DISC_FAIL_EVT) && 269 (p_data->disc_result.status == SDP_SUCCESS || 270 p_data->disc_result.status == SDP_DB_FULL || 271 p_data->disc_result.status == SDP_NO_RECS_MATCH)) 272 { 273 if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) && 274 (p_scb->open_services & BTA_HSP_SERVICE_MASK)) 275 { 276 /* search for HSP */ 277 p_scb->open_services &= ~BTA_HFP_SERVICE_MASK; 278 bta_ag_do_disc(p_scb, p_scb->open_services); 279 } 280 else if ((p_scb->open_services & BTA_HSP_SERVICE_MASK) && 281 (p_scb->hsp_version == HSP_VERSION_1_2)) 282 { 283 /* search for UUID_SERVCLASS_HEADSET for HSP 1.0 device */ 284 p_scb->hsp_version = HSP_VERSION_1_0; 285 bta_ag_do_disc(p_scb, p_scb->open_services); 286 } 287 else 288 { 289 /* send ourselves sdp ok/fail event */ 290 bta_ag_sm_execute(p_scb, event, p_data); 291 } 292 } 293 else 294 { 295 /* send ourselves sdp ok/fail event */ 296 bta_ag_sm_execute(p_scb, event, p_data); 297 } 298 299 } 300 301 /******************************************************************************* 302 ** 303 ** Function bta_ag_disc_acp_res 304 ** 305 ** Description This function handles a discovery result when acceptor. 306 ** 307 ** 308 ** Returns void 309 ** 310 *******************************************************************************/ 311 void bta_ag_disc_acp_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 312 { 313 /* if found service */ 314 if (p_data->disc_result.status == SDP_SUCCESS || 315 p_data->disc_result.status == SDP_DB_FULL) 316 { 317 /* get attributes */ 318 bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]); 319 } 320 321 /* free discovery db */ 322 bta_ag_free_db(p_scb, p_data); 323 } 324 325 /******************************************************************************* 326 ** 327 ** Function bta_ag_disc_fail 328 ** 329 ** Description This function handles a discovery failure. 330 ** 331 ** 332 ** Returns void 333 ** 334 *******************************************************************************/ 335 void bta_ag_disc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 336 { 337 UNUSED(p_data); 338 339 /* reopen registered servers */ 340 bta_ag_start_servers(p_scb, p_scb->reg_services); 341 342 /* reinitialize stuff */ 343 344 /* call open cback w. failure */ 345 bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP); 346 } 347 348 /******************************************************************************* 349 ** 350 ** Function bta_ag_open_fail 351 ** 352 ** Description open connection failed. 353 ** 354 ** 355 ** Returns void 356 ** 357 *******************************************************************************/ 358 void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 359 { 360 /* call open cback w. failure */ 361 bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES); 362 } 363 364 /******************************************************************************* 365 ** 366 ** Function bta_ag_rfc_fail 367 ** 368 ** Description RFCOMM connection failed. 369 ** 370 ** 371 ** Returns void 372 ** 373 *******************************************************************************/ 374 void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 375 { 376 UNUSED(p_data); 377 378 /* reinitialize stuff */ 379 p_scb->conn_handle = 0; 380 p_scb->conn_service = 0; 381 p_scb->peer_features = 0; 382 #if (BTM_WBS_INCLUDED == TRUE ) 383 p_scb->peer_codecs = BTA_AG_CODEC_NONE; 384 p_scb->sco_codec = BTA_AG_CODEC_NONE; 385 #endif 386 p_scb->role = 0; 387 p_scb->svc_conn = FALSE; 388 p_scb->hsp_version = HSP_VERSION_1_2; 389 390 /* reopen registered servers */ 391 bta_ag_start_servers(p_scb, p_scb->reg_services); 392 393 /* call open cback w. failure */ 394 bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM); 395 } 396 397 /******************************************************************************* 398 ** 399 ** Function bta_ag_rfc_close 400 ** 401 ** Description RFCOMM connection closed. 402 ** 403 ** 404 ** Returns void 405 ** 406 *******************************************************************************/ 407 void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 408 { 409 tBTA_AG_CLOSE close; 410 tBTA_SERVICE_MASK services; 411 int i, num_active_conn = 0; 412 UNUSED(p_data); 413 414 #ifdef _WIN32_WCE 415 /* The BTE RFCOMM automatically removes the connection when closed, but BTW does not */ 416 if (p_scb->conn_handle != 0) 417 RFCOMM_RemoveConnection (p_scb->conn_handle); 418 #endif 419 420 /* reinitialize stuff */ 421 p_scb->conn_service = 0; 422 p_scb->peer_features = 0; 423 #if (BTM_WBS_INCLUDED == TRUE ) 424 p_scb->peer_codecs = BTA_AG_CODEC_NONE; 425 p_scb->sco_codec = BTA_AG_CODEC_NONE; 426 /* Clear these flags upon SLC teardown */ 427 p_scb->codec_updated = FALSE; 428 p_scb->codec_fallback = FALSE; 429 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; 430 #endif 431 p_scb->role = 0; 432 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 433 p_scb->svc_conn = FALSE; 434 p_scb->hsp_version = HSP_VERSION_1_2; 435 bta_ag_at_reinit(&p_scb->at_cb); 436 437 /* stop timers */ 438 bta_sys_stop_timer(&p_scb->act_timer); 439 #if (BTM_WBS_INCLUDED == TRUE) 440 bta_sys_stop_timer(&p_scb->cn_timer); 441 #endif 442 443 close.hdr.handle = bta_ag_scb_to_idx(p_scb); 444 close.hdr.app_id = p_scb->app_id; 445 bdcpy(close.bd_addr, p_scb->peer_addr); 446 447 bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 448 449 /* call close call-out */ 450 bta_ag_co_data_close(close.hdr.handle); 451 452 /* call close cback */ 453 (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close); 454 455 /* if not deregistering (deallocating) reopen registered servers */ 456 if (p_scb->dealloc == FALSE) 457 { 458 /* Clear peer bd_addr so instance can be reused */ 459 bdcpy(p_scb->peer_addr, bd_addr_null); 460 461 /* start only unopened server */ 462 services = p_scb->reg_services; 463 for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++) 464 { 465 if(p_scb->serv_handle[i]) 466 services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i)); 467 } 468 bta_ag_start_servers(p_scb, services); 469 470 p_scb->conn_handle = 0; 471 472 /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */ 473 bta_ag_sco_shutdown(p_scb, NULL); 474 475 /* Check if all the SLCs are down */ 476 for (i = 0; i < BTA_AG_NUM_SCB; i++) 477 { 478 if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn) 479 num_active_conn++; 480 } 481 482 if(!num_active_conn) 483 { 484 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 485 } 486 487 } 488 /* else close port and deallocate scb */ 489 else 490 { 491 RFCOMM_RemoveServer(p_scb->conn_handle); 492 bta_ag_scb_dealloc(p_scb); 493 } 494 } 495 496 /******************************************************************************* 497 ** 498 ** Function bta_ag_rfc_open 499 ** 500 ** Description Handle RFCOMM channel open. 501 ** 502 ** 503 ** Returns void 504 ** 505 *******************************************************************************/ 506 void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 507 { 508 /* initialize AT feature variables */ 509 p_scb->clip_enabled = FALSE; 510 p_scb->ccwa_enabled = FALSE; 511 p_scb->cmer_enabled = FALSE; 512 p_scb->cmee_enabled = FALSE; 513 p_scb->inband_enabled = ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND); 514 515 /* set up AT command interpreter */ 516 p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD *) bta_ag_at_tbl[p_scb->conn_service]; 517 p_scb->at_cb.p_cmd_cback = (tBTA_AG_AT_CMD_CBACK *) bta_ag_at_cback_tbl[p_scb->conn_service]; 518 p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK *) bta_ag_at_err_cback; 519 p_scb->at_cb.p_user = p_scb; 520 p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX; 521 bta_ag_at_init(&p_scb->at_cb); 522 523 /* call app open call-out */ 524 bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb), bta_ag_svc_id[p_scb->conn_service]); 525 526 bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 527 528 bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS); 529 530 if (p_scb->conn_service == BTA_AG_HFP) 531 { 532 /* if hfp start timer for service level conn */ 533 bta_sys_start_timer(&p_scb->act_timer, BTA_AG_SVC_TOUT_EVT, p_bta_ag_cfg->conn_tout); 534 } 535 else 536 { 537 /* else service level conn is open */ 538 bta_ag_svc_conn_open(p_scb, p_data); 539 } 540 } 541 542 /******************************************************************************* 543 ** 544 ** Function bta_ag_rfc_acp_open 545 ** 546 ** Description Handle RFCOMM channel open when accepting connection. 547 ** 548 ** 549 ** Returns void 550 ** 551 *******************************************************************************/ 552 void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 553 { 554 UINT16 lcid; 555 int i; 556 tBTA_AG_SCB *ag_scb, *other_scb; 557 BD_ADDR dev_addr; 558 int status; 559 560 /* set role */ 561 p_scb->role = BTA_AG_ACP; 562 563 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d", 564 p_scb->serv_handle[0], p_scb->serv_handle[1]); 565 566 /* get bd addr of peer */ 567 if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) 568 { 569 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status); 570 } 571 572 /* Collision Handling */ 573 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++) 574 { 575 if ((ag_scb->in_use) && (ag_scb->colli_tmr_on)) 576 { 577 /* stop collision timer */ 578 ag_scb->colli_tmr_on = FALSE; 579 bta_sys_stop_timer (&ag_scb->colli_timer); 580 581 if (bdcmp (dev_addr, ag_scb->peer_addr) == 0) 582 { 583 /* If incoming and outgoing device are same, nothing more to do. */ 584 /* Outgoing conn will be aborted because we have successful incoming conn. */ 585 } 586 else 587 { 588 /* Resume outgoing connection. */ 589 other_scb = bta_ag_get_other_idle_scb (p_scb); 590 if (other_scb) 591 { 592 bdcpy(other_scb->peer_addr, ag_scb->peer_addr); 593 other_scb->open_services = ag_scb->open_services; 594 other_scb->cli_sec_mask = ag_scb->cli_sec_mask; 595 596 bta_ag_resume_open (other_scb); 597 } 598 } 599 600 break; 601 } 602 } 603 604 bdcpy (p_scb->peer_addr, dev_addr); 605 606 /* determine connected service from port handle */ 607 for (i = 0; i < BTA_AG_NUM_IDX; i++) 608 { 609 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", 610 i, p_scb->serv_handle[i], p_data->rfc.port_handle); 611 612 if (p_scb->serv_handle[i] == p_data->rfc.port_handle) 613 { 614 p_scb->conn_service = i; 615 p_scb->conn_handle = p_data->rfc.port_handle; 616 break; 617 } 618 } 619 620 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d", 621 p_scb->conn_service, p_scb->conn_handle); 622 623 /* close any unopened server */ 624 bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service])); 625 626 /* do service discovery to get features */ 627 bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]); 628 629 /* continue with common open processing */ 630 bta_ag_rfc_open(p_scb, p_data); 631 632 633 634 } 635 636 /******************************************************************************* 637 ** 638 ** Function bta_ag_rfc_data 639 ** 640 ** Description Read and process data from RFCOMM. 641 ** 642 ** 643 ** Returns void 644 ** 645 *******************************************************************************/ 646 void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 647 { 648 UINT16 len; 649 char buf[BTA_AG_RFC_READ_MAX]; 650 UNUSED(p_data); 651 652 memset(buf, 0, BTA_AG_RFC_READ_MAX); 653 654 /* do the following */ 655 for(;;) 656 { 657 /* read data from rfcomm; if bad status, we're done */ 658 if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) != PORT_SUCCESS) 659 { 660 break; 661 } 662 663 /* if no data, we're done */ 664 if (len == 0) 665 { 666 break; 667 } 668 669 /* run AT command interpreter on data */ 670 bta_ag_at_parse(&p_scb->at_cb, buf, len); 671 672 /* no more data to read, we're done */ 673 if (len < BTA_AG_RFC_READ_MAX) 674 { 675 break; 676 } 677 } 678 } 679 680 /******************************************************************************* 681 ** 682 ** Function bta_ag_start_close 683 ** 684 ** Description Start the process of closing SCO and RFCOMM connection. 685 ** 686 ** 687 ** Returns void 688 ** 689 *******************************************************************************/ 690 void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 691 { 692 /* Take the link out of sniff and set L2C idle time to 0 */ 693 bta_dm_pm_active(p_scb->peer_addr); 694 L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0); 695 696 /* if SCO is open close SCO and wait on RFCOMM close */ 697 if (bta_ag_sco_is_open(p_scb)) 698 { 699 p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC; 700 } 701 else 702 { 703 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 704 bta_ag_rfc_do_close(p_scb, p_data); 705 } 706 707 /* always do SCO shutdown to handle all SCO corner cases */ 708 bta_ag_sco_shutdown(p_scb, p_data); 709 } 710 711 /******************************************************************************* 712 ** 713 ** Function bta_ag_post_sco_open 714 ** 715 ** Description Perform post-SCO open action, if any 716 ** 717 ** 718 ** Returns void 719 ** 720 *******************************************************************************/ 721 void bta_ag_post_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 722 { 723 switch (p_scb->post_sco) 724 { 725 case BTA_AG_POST_SCO_RING: 726 bta_ag_send_ring(p_scb, p_data); 727 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 728 break; 729 730 case BTA_AG_POST_SCO_CALL_CONN: 731 bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES); 732 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 733 break; 734 735 default: 736 break; 737 } 738 } 739 740 /******************************************************************************* 741 ** 742 ** Function bta_ag_post_sco_close 743 ** 744 ** Description Perform post-SCO close action, if any 745 ** 746 ** 747 ** Returns void 748 ** 749 *******************************************************************************/ 750 void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 751 { 752 switch (p_scb->post_sco) 753 { 754 case BTA_AG_POST_SCO_CLOSE_RFC: 755 bta_ag_rfc_do_close(p_scb, p_data); 756 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 757 break; 758 759 case BTA_AG_POST_SCO_CALL_CONN: 760 bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES); 761 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 762 break; 763 764 case BTA_AG_POST_SCO_CALL_ORIG: 765 bta_ag_send_call_inds(p_scb, BTA_AG_OUT_CALL_ORIG_RES); 766 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 767 break; 768 769 case BTA_AG_POST_SCO_CALL_END: 770 bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES); 771 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 772 break; 773 774 case BTA_AG_POST_SCO_CALL_END_INCALL: 775 bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES); 776 777 /* Sending callsetup IND and Ring were defered to after SCO close. */ 778 bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_RES); 779 780 if (bta_ag_inband_enabled(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO)) 781 { 782 p_scb->post_sco = BTA_AG_POST_SCO_RING; 783 bta_ag_sco_open(p_scb, p_data); 784 } 785 else 786 { 787 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 788 bta_ag_send_ring(p_scb, p_data); 789 } 790 break; 791 792 default: 793 break; 794 } 795 } 796 797 /******************************************************************************* 798 ** 799 ** Function bta_ag_svc_conn_open 800 ** 801 ** Description Service level connection opened 802 ** 803 ** 804 ** Returns void 805 ** 806 *******************************************************************************/ 807 void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 808 { 809 tBTA_AG_CONN evt; 810 UNUSED(p_data); 811 812 if (!p_scb->svc_conn) 813 { 814 /* set state variable */ 815 p_scb->svc_conn = TRUE; 816 817 /* Clear AT+BIA mask from previous SLC if any. */ 818 p_scb->bia_masked_out = 0; 819 820 /* stop timer */ 821 bta_sys_stop_timer(&p_scb->act_timer); 822 823 /* call callback */ 824 evt.hdr.handle = bta_ag_scb_to_idx(p_scb); 825 evt.hdr.app_id = p_scb->app_id; 826 evt.peer_feat = p_scb->peer_features; 827 bdcpy(evt.bd_addr, p_scb->peer_addr); 828 #if (BTM_WBS_INCLUDED == TRUE ) 829 evt.peer_codec = p_scb->peer_codecs; 830 #endif 831 832 if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) || 833 (p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE)) 834 { 835 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 836 } 837 838 (*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG *) &evt); 839 } 840 } 841 842 /******************************************************************************* 843 ** 844 ** Function bta_ag_ci_rx_data 845 ** 846 ** Description Send result code 847 ** 848 ** Returns void 849 ** 850 *******************************************************************************/ 851 void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 852 { 853 UINT16 len; 854 tBTA_AG_CI_RX_WRITE *p_rx_write_msg = (tBTA_AG_CI_RX_WRITE *)p_data; 855 char *p_data_area = (char *)(p_rx_write_msg+1); /* Point to data area after header */ 856 857 /* send to RFCOMM */ 858 PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len); 859 } 860 861 /******************************************************************************* 862 ** 863 ** Function bta_ag_rcvd_slc_ready 864 ** 865 ** Description Handles SLC ready call-in in case of pass-through mode. 866 ** 867 ** Returns void 868 ** 869 *******************************************************************************/ 870 void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 871 { 872 UNUSED(p_data); 873 874 APPL_TRACE_DEBUG("bta_ag_rcvd_slc_ready: handle = %d", bta_ag_scb_to_idx(p_scb)); 875 876 if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) 877 { 878 /* In pass-through mode, BTA knows that SLC is ready only through call-in. */ 879 bta_ag_svc_conn_open(p_scb, NULL); 880 } 881 } 882 883 /******************************************************************************* 884 ** 885 ** Function bta_ag_setcodec 886 ** 887 ** Description Handle API SetCodec 888 ** 889 ** 890 ** Returns void 891 ** 892 *******************************************************************************/ 893 void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 894 { 895 #if (BTM_WBS_INCLUDED == TRUE ) 896 tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec; 897 tBTA_AG_VAL val; 898 899 /* Check if the requested codec type is valid */ 900 if((codec_type != BTA_AG_CODEC_NONE) && 901 (codec_type != BTA_AG_CODEC_CVSD) && 902 (codec_type != BTA_AG_CODEC_MSBC)) 903 { 904 val.num = codec_type; 905 val.hdr.status = BTA_AG_FAIL_RESOURCES; 906 APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); 907 (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); 908 return; 909 } 910 911 if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || 912 (codec_type == BTA_AG_CODEC_CVSD)) 913 { 914 p_scb->sco_codec = codec_type; 915 p_scb->codec_updated = TRUE; 916 val.num = codec_type; 917 val.hdr.status = BTA_AG_SUCCESS; 918 APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type); 919 } 920 else 921 { 922 val.num = codec_type; 923 val.hdr.status = BTA_AG_FAIL_RESOURCES; 924 APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); 925 } 926 927 (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); 928 #endif 929 } 930 931