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