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 46const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX] = 47{ 48 UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, 49 UUID_SERVCLASS_AG_HANDSFREE 50}; 51 52const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX] = 53{ 54 BTM_SEC_SERVICE_HEADSET_AG, 55 BTM_SEC_SERVICE_AG_HANDSFREE 56}; 57 58const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] = 59{ 60 BTA_HSP_SERVICE_ID, 61 BTA_HFP_SERVICE_ID 62}; 63 64const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] = 65{ 66 BTA_HSP_SERVICE_MASK, 67 BTA_HFP_SERVICE_MASK 68}; 69 70typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, 71 char *p_arg, INT16 int_arg); 72 73const 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*******************************************************************************/ 89static 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*******************************************************************************/ 122void 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*******************************************************************************/ 156void 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*******************************************************************************/ 181void 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*******************************************************************************/ 200void 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*******************************************************************************/ 242void 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*******************************************************************************/ 310void 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*******************************************************************************/ 334void 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 /* clear the remote BD address */ 344 bdcpy(p_scb->peer_addr, bd_addr_null); 345 346 /* call open cback w. failure */ 347 bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP); 348} 349 350/******************************************************************************* 351** 352** Function bta_ag_open_fail 353** 354** Description open connection failed. 355** 356** 357** Returns void 358** 359*******************************************************************************/ 360void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 361{ 362 /* call open cback w. failure */ 363 bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES); 364} 365 366/******************************************************************************* 367** 368** Function bta_ag_rfc_fail 369** 370** Description RFCOMM connection failed. 371** 372** 373** Returns void 374** 375*******************************************************************************/ 376void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 377{ 378 UNUSED(p_data); 379 380 /* reinitialize stuff */ 381 p_scb->conn_handle = 0; 382 p_scb->conn_service = 0; 383 p_scb->peer_features = 0; 384#if (BTM_WBS_INCLUDED == TRUE ) 385 p_scb->peer_codecs = BTA_AG_CODEC_CVSD; 386 p_scb->sco_codec = BTA_AG_CODEC_CVSD; 387#endif 388 p_scb->role = 0; 389 p_scb->svc_conn = FALSE; 390 p_scb->hsp_version = HSP_VERSION_1_2; 391 /*Clear the BD address*/ 392 bdcpy(p_scb->peer_addr, bd_addr_null); 393 394 /* reopen registered servers */ 395 bta_ag_start_servers(p_scb, p_scb->reg_services); 396 397 /* call open cback w. failure */ 398 bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM); 399} 400 401/******************************************************************************* 402** 403** Function bta_ag_rfc_close 404** 405** Description RFCOMM connection closed. 406** 407** 408** Returns void 409** 410*******************************************************************************/ 411void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 412{ 413 tBTA_AG_CLOSE close; 414 tBTA_SERVICE_MASK services; 415 int i, num_active_conn = 0; 416 UNUSED(p_data); 417 418 /* reinitialize stuff */ 419 p_scb->conn_service = 0; 420 p_scb->peer_features = 0; 421#if (BTM_WBS_INCLUDED == TRUE ) 422 p_scb->peer_codecs = BTA_AG_CODEC_CVSD; 423 p_scb->sco_codec = BTA_AG_CODEC_CVSD; 424 /* Clear these flags upon SLC teardown */ 425 p_scb->codec_updated = FALSE; 426 p_scb->codec_fallback = FALSE; 427 p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; 428#endif 429 p_scb->role = 0; 430 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 431 p_scb->svc_conn = FALSE; 432 p_scb->hsp_version = HSP_VERSION_1_2; 433 bta_ag_at_reinit(&p_scb->at_cb); 434 435 /* stop timers */ 436 alarm_cancel(p_scb->ring_timer); 437#if (BTM_WBS_INCLUDED == TRUE) 438 alarm_cancel(p_scb->codec_negotiation_timer); 439#endif 440 441 close.hdr.handle = bta_ag_scb_to_idx(p_scb); 442 close.hdr.app_id = p_scb->app_id; 443 bdcpy(close.bd_addr, p_scb->peer_addr); 444 445 bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 446 447 /* call close call-out */ 448 bta_ag_co_data_close(close.hdr.handle); 449 450 /* call close cback */ 451 (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close); 452 453 /* if not deregistering (deallocating) reopen registered servers */ 454 if (p_scb->dealloc == FALSE) 455 { 456 /* Clear peer bd_addr so instance can be reused */ 457 bdcpy(p_scb->peer_addr, bd_addr_null); 458 459 /* start only unopened server */ 460 services = p_scb->reg_services; 461 for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++) 462 { 463 if(p_scb->serv_handle[i]) 464 services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i)); 465 } 466 bta_ag_start_servers(p_scb, services); 467 468 p_scb->conn_handle = 0; 469 470 /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */ 471 bta_ag_sco_shutdown(p_scb, NULL); 472 473 /* Check if all the SLCs are down */ 474 for (i = 0; i < BTA_AG_NUM_SCB; i++) 475 { 476 if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn) 477 num_active_conn++; 478 } 479 480 if(!num_active_conn) 481 { 482 bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 483 } 484 485 } 486 /* else close port and deallocate scb */ 487 else 488 { 489 RFCOMM_RemoveServer(p_scb->conn_handle); 490 bta_ag_scb_dealloc(p_scb); 491 } 492} 493 494/******************************************************************************* 495** 496** Function bta_ag_rfc_open 497** 498** Description Handle RFCOMM channel open. 499** 500** 501** Returns void 502** 503*******************************************************************************/ 504void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 505{ 506 /* initialize AT feature variables */ 507 p_scb->clip_enabled = FALSE; 508 p_scb->ccwa_enabled = FALSE; 509 p_scb->cmer_enabled = FALSE; 510 p_scb->cmee_enabled = FALSE; 511 p_scb->inband_enabled = ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND); 512 513 /* set up AT command interpreter */ 514 p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD *) bta_ag_at_tbl[p_scb->conn_service]; 515 p_scb->at_cb.p_cmd_cback = (tBTA_AG_AT_CMD_CBACK *) bta_ag_at_cback_tbl[p_scb->conn_service]; 516 p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK *) bta_ag_at_err_cback; 517 p_scb->at_cb.p_user = p_scb; 518 p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX; 519 bta_ag_at_init(&p_scb->at_cb); 520 521 /* call app open call-out */ 522 bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb), bta_ag_svc_id[p_scb->conn_service]); 523 524 bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 525 526 bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS); 527 528 if (p_scb->conn_service == BTA_AG_HFP) { 529 /* if hfp start timer for service level conn */ 530 bta_sys_start_timer(p_scb->ring_timer, p_bta_ag_cfg->conn_tout, 531 BTA_AG_SVC_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb)); 532 } else { 533 /* else service level conn is open */ 534 bta_ag_svc_conn_open(p_scb, p_data); 535 } 536} 537 538/******************************************************************************* 539** 540** Function bta_ag_rfc_acp_open 541** 542** Description Handle RFCOMM channel open when accepting connection. 543** 544** 545** Returns void 546** 547*******************************************************************************/ 548void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 549{ 550 UINT16 lcid; 551 int i; 552 tBTA_AG_SCB *ag_scb, *other_scb; 553 BD_ADDR dev_addr; 554 int status; 555 556 /* set role */ 557 p_scb->role = BTA_AG_ACP; 558 559 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d", 560 p_scb->serv_handle[0], p_scb->serv_handle[1]); 561 562 /* get bd addr of peer */ 563 if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) 564 { 565 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status); 566 } 567 568 /* Collision Handling */ 569 for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++) 570 { 571 if (ag_scb->in_use && alarm_is_scheduled(ag_scb->collision_timer)) 572 { 573 alarm_cancel(ag_scb->collision_timer); 574 575 if (bdcmp (dev_addr, ag_scb->peer_addr) == 0) 576 { 577 /* If incoming and outgoing device are same, nothing more to do. */ 578 /* Outgoing conn will be aborted because we have successful incoming conn. */ 579 } 580 else 581 { 582 /* Resume outgoing connection. */ 583 other_scb = bta_ag_get_other_idle_scb (p_scb); 584 if (other_scb) 585 { 586 bdcpy(other_scb->peer_addr, ag_scb->peer_addr); 587 other_scb->open_services = ag_scb->open_services; 588 other_scb->cli_sec_mask = ag_scb->cli_sec_mask; 589 590 bta_ag_resume_open (other_scb); 591 } 592 } 593 594 break; 595 } 596 } 597 598 bdcpy (p_scb->peer_addr, dev_addr); 599 600 /* determine connected service from port handle */ 601 for (i = 0; i < BTA_AG_NUM_IDX; i++) 602 { 603 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", 604 i, p_scb->serv_handle[i], p_data->rfc.port_handle); 605 606 if (p_scb->serv_handle[i] == p_data->rfc.port_handle) 607 { 608 p_scb->conn_service = i; 609 p_scb->conn_handle = p_data->rfc.port_handle; 610 break; 611 } 612 } 613 614 APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d", 615 p_scb->conn_service, p_scb->conn_handle); 616 617 /* close any unopened server */ 618 bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service])); 619 620 /* do service discovery to get features */ 621 bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]); 622 623 /* continue with common open processing */ 624 bta_ag_rfc_open(p_scb, p_data); 625 626 627 628} 629 630/******************************************************************************* 631** 632** Function bta_ag_rfc_data 633** 634** Description Read and process data from RFCOMM. 635** 636** 637** Returns void 638** 639*******************************************************************************/ 640void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 641{ 642 UINT16 len; 643 char buf[BTA_AG_RFC_READ_MAX]; 644 UNUSED(p_data); 645 646 memset(buf, 0, BTA_AG_RFC_READ_MAX); 647 648 APPL_TRACE_DEBUG("%s", __func__); 649 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 if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb)) 669 { 670 APPL_TRACE_DEBUG ("%s change link policy for SCO", __func__); 671 bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 672 } else { 673 bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 674 } 675 676 /* no more data to read, we're done */ 677 if (len < BTA_AG_RFC_READ_MAX) 678 { 679 break; 680 } 681 } 682} 683 684/******************************************************************************* 685** 686** Function bta_ag_start_close 687** 688** Description Start the process of closing SCO and RFCOMM connection. 689** 690** 691** Returns void 692** 693*******************************************************************************/ 694void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 695{ 696 /* Take the link out of sniff and set L2C idle time to 0 */ 697 bta_dm_pm_active(p_scb->peer_addr); 698 L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0, BT_TRANSPORT_BR_EDR); 699 700 /* if SCO is open close SCO and wait on RFCOMM close */ 701 if (bta_ag_sco_is_open(p_scb)) 702 { 703 p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC; 704 } 705 else 706 { 707 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 708 bta_ag_rfc_do_close(p_scb, p_data); 709 } 710 711 /* always do SCO shutdown to handle all SCO corner cases */ 712 bta_ag_sco_shutdown(p_scb, p_data); 713} 714 715/******************************************************************************* 716** 717** Function bta_ag_post_sco_open 718** 719** Description Perform post-SCO open action, if any 720** 721** 722** Returns void 723** 724*******************************************************************************/ 725void bta_ag_post_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 726{ 727 switch (p_scb->post_sco) 728 { 729 case BTA_AG_POST_SCO_RING: 730 bta_ag_send_ring(p_scb, p_data); 731 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 732 break; 733 734 case BTA_AG_POST_SCO_CALL_CONN: 735 bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES); 736 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 737 break; 738 739 default: 740 break; 741 } 742} 743 744/******************************************************************************* 745** 746** Function bta_ag_post_sco_close 747** 748** Description Perform post-SCO close action, if any 749** 750** 751** Returns void 752** 753*******************************************************************************/ 754void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 755{ 756 switch (p_scb->post_sco) 757 { 758 case BTA_AG_POST_SCO_CLOSE_RFC: 759 bta_ag_rfc_do_close(p_scb, p_data); 760 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 761 break; 762 763 case BTA_AG_POST_SCO_CALL_CONN: 764 bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES); 765 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 766 break; 767 768 case BTA_AG_POST_SCO_CALL_ORIG: 769 bta_ag_send_call_inds(p_scb, BTA_AG_OUT_CALL_ORIG_RES); 770 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 771 break; 772 773 case BTA_AG_POST_SCO_CALL_END: 774 bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES); 775 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 776 break; 777 778 case BTA_AG_POST_SCO_CALL_END_INCALL: 779 bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES); 780 781 /* Sending callsetup IND and Ring were defered to after SCO close. */ 782 bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_RES); 783 784 if (bta_ag_inband_enabled(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO)) 785 { 786 p_scb->post_sco = BTA_AG_POST_SCO_RING; 787 bta_ag_sco_open(p_scb, p_data); 788 } 789 else 790 { 791 p_scb->post_sco = BTA_AG_POST_SCO_NONE; 792 bta_ag_send_ring(p_scb, p_data); 793 } 794 break; 795 796 default: 797 break; 798 } 799} 800 801/******************************************************************************* 802** 803** Function bta_ag_svc_conn_open 804** 805** Description Service level connection opened 806** 807** 808** Returns void 809** 810*******************************************************************************/ 811void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 812{ 813 tBTA_AG_CONN evt; 814 UNUSED(p_data); 815 816 if (!p_scb->svc_conn) 817 { 818 /* set state variable */ 819 p_scb->svc_conn = TRUE; 820 821 /* Clear AT+BIA mask from previous SLC if any. */ 822 p_scb->bia_masked_out = 0; 823 824 alarm_cancel(p_scb->ring_timer); 825 826 /* call callback */ 827 evt.hdr.handle = bta_ag_scb_to_idx(p_scb); 828 evt.hdr.app_id = p_scb->app_id; 829 evt.peer_feat = p_scb->peer_features; 830 bdcpy(evt.bd_addr, p_scb->peer_addr); 831#if (BTM_WBS_INCLUDED == TRUE ) 832 evt.peer_codec = p_scb->peer_codecs; 833#endif 834 835 if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) || 836 (p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE)) 837 { 838 bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 839 } 840 841 (*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG *) &evt); 842 } 843} 844 845/******************************************************************************* 846** 847** Function bta_ag_ci_rx_data 848** 849** Description Send result code 850** 851** Returns void 852** 853*******************************************************************************/ 854void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 855{ 856 UINT16 len; 857 tBTA_AG_CI_RX_WRITE *p_rx_write_msg = (tBTA_AG_CI_RX_WRITE *)p_data; 858 char *p_data_area = (char *)(p_rx_write_msg+1); /* Point to data area after header */ 859 860 APPL_TRACE_DEBUG("bta_ag_ci_rx_data:"); 861 /* send to RFCOMM */ 862 bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 863 PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len); 864 if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb)) 865 { 866 APPL_TRACE_DEBUG ("bta_ag_rfc_data, change link policy for SCO"); 867 bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 868 } 869 else 870 { 871 bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); 872 } 873} 874 875/******************************************************************************* 876** 877** Function bta_ag_rcvd_slc_ready 878** 879** Description Handles SLC ready call-in in case of pass-through mode. 880** 881** Returns void 882** 883*******************************************************************************/ 884void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 885{ 886 UNUSED(p_data); 887 888 APPL_TRACE_DEBUG("bta_ag_rcvd_slc_ready: handle = %d", bta_ag_scb_to_idx(p_scb)); 889 890 if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) 891 { 892 /* In pass-through mode, BTA knows that SLC is ready only through call-in. */ 893 bta_ag_svc_conn_open(p_scb, NULL); 894 } 895} 896 897/******************************************************************************* 898** 899** Function bta_ag_setcodec 900** 901** Description Handle API SetCodec 902** 903** 904** Returns void 905** 906*******************************************************************************/ 907void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) 908{ 909#if (BTM_WBS_INCLUDED == TRUE ) 910 tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec; 911 tBTA_AG_VAL val; 912 913 /* Check if the requested codec type is valid */ 914 if((codec_type != BTA_AG_CODEC_NONE) && 915 (codec_type != BTA_AG_CODEC_CVSD) && 916 (codec_type != BTA_AG_CODEC_MSBC)) 917 { 918 val.num = codec_type; 919 val.hdr.status = BTA_AG_FAIL_RESOURCES; 920 APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); 921 (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); 922 return; 923 } 924 925 if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || 926 (codec_type == BTA_AG_CODEC_CVSD)) 927 { 928 p_scb->sco_codec = codec_type; 929 p_scb->codec_updated = TRUE; 930 val.num = codec_type; 931 val.hdr.status = BTA_AG_SUCCESS; 932 APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type); 933 } 934 else 935 { 936 val.num = codec_type; 937 val.hdr.status = BTA_AG_FAIL_RESOURCES; 938 APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); 939 } 940 941 (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); 942#endif 943} 944 945