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