btif_hf.c revision 27c81965d8bcf9050b6fa66e004373ca2dea52a1
1/****************************************************************************** 2 * 3 * Copyright (C) 2009-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 * Filename: btif_hf.c 22 * 23 * Description: Handsfree Profile Bluetooth Interface 24 * 25 * 26 ***********************************************************************************/ 27 28#include <hardware/bluetooth.h> 29#include <hardware/bt_hf.h> 30#include <stdlib.h> 31 32#define LOG_TAG "BTIF_HF" 33#include "btif_common.h" 34#include "btif_util.h" 35#include "btif_profile_queue.h" 36 37#include "bd.h" 38#include "bta_ag_api.h" 39 40/************************************************************************************ 41** Constants & Macros 42************************************************************************************/ 43#ifndef BTIF_HSAG_SERVICE_NAME 44#define BTIF_HSAG_SERVICE_NAME ("Headset Gateway") 45#endif 46 47#ifndef BTIF_HFAG_SERVICE_NAME 48#define BTIF_HFAG_SERVICE_NAME ("Handsfree Gateway") 49#endif 50 51#ifndef BTIF_HF_SERVICES 52#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK | BTA_HFP_SERVICE_MASK ) 53#endif 54 55#ifndef BTIF_HF_SERVICE_NAMES 56#define BTIF_HF_SERVICE_NAMES {BTIF_HSAG_SERVICE_NAME , BTIF_HFAG_SERVICE_NAME} 57#endif 58 59#ifndef BTIF_HF_SECURITY 60#define BTIF_HF_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT) 61#endif 62 63#ifndef BTIF_HF_FEATURES 64#define BTIF_HF_FEATURES ( BTA_AG_FEAT_3WAY | \ 65 BTA_AG_FEAT_ECNR | \ 66 BTA_AG_FEAT_REJECT | \ 67 BTA_AG_FEAT_ECS | \ 68 BTA_AG_FEAT_EXTERR | \ 69 BTA_AG_FEAT_BTRH | \ 70 BTA_AG_FEAT_VREC | \ 71 BTA_AG_FEAT_UNAT) 72#endif 73 74#define BTIF_HF_CALL_END_TIMEOUT 6 75 76#define BTIF_HF_INVALID_IDX -1 77 78/* Number of BTIF-HF control blocks */ 79#define BTIF_HF_NUM_CB 2 80 81/* Max HF clients supported from App */ 82UINT16 btif_max_hf_clients = -1; 83 84/* HF app ids for service registration */ 85typedef enum { 86 BTIF_HF_ID_1 = 0, 87 BTIF_HF_ID_2, 88#if (BTIF_HF_NUM_CB == 3) 89 BTIF_HF_ID_3 90#endif 91} bthf_hf_id_t; 92 93UINT16 bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2, 94 #if (BTIF_HF_NUM_CB == 3) 95 BTIF_HF_ID_3 96 #endif 97 }; 98 99/************************************************************************************ 100** Local type definitions 101************************************************************************************/ 102 103/************************************************************************************ 104** Static variables 105************************************************************************************/ 106static bthf_callbacks_t *bt_hf_callbacks = NULL; 107static int hf_idx = BTIF_HF_INVALID_IDX; 108 109#define CHECK_BTHF_INIT() if (bt_hf_callbacks == NULL)\ 110 {\ 111 BTIF_TRACE_WARNING1("BTHF: %s: BTHF not initialized", __FUNCTION__);\ 112 return BT_STATUS_NOT_READY;\ 113 }\ 114 else\ 115 {\ 116 BTIF_TRACE_EVENT1("BTHF: %s", __FUNCTION__);\ 117 } 118 119#define CHECK_BTHF_SLC_CONNECTED() if (bt_hf_callbacks == NULL)\ 120 {\ 121 BTIF_TRACE_WARNING1("BTHF: %s: BTHF not initialized", __FUNCTION__);\ 122 return BT_STATUS_NOT_READY;\ 123 }\ 124 else if (btif_hf_cb.state != BTHF_CONNECTION_STATE_SLC_CONNECTED)\ 125 {\ 126 BTIF_TRACE_WARNING2("BTHF: %s: SLC connection not up. state=%s", __FUNCTION__, dump_hf_conn_state(btif_hf_cb.state));\ 127 return BT_STATUS_NOT_READY;\ 128 }\ 129 else\ 130 {\ 131 BTIF_TRACE_EVENT1("BTHF: %s", __FUNCTION__);\ 132 } 133 134/* BTIF-HF control block to map bdaddr to BTA handle */ 135typedef struct _btif_hf_cb 136{ 137 UINT16 handle; 138 bt_bdaddr_t connected_bda; 139 bthf_connection_state_t state; 140 bthf_vr_state_t vr_state; 141 tBTA_AG_PEER_FEAT peer_feat; 142 int num_active; 143 int num_held; 144 struct timespec call_end_timestamp; 145 struct timespec connected_timestamp; 146 bthf_call_state_t call_setup_state; 147} btif_hf_cb_t; 148 149static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB]; 150 151 152/************************************************************************************ 153** Static functions 154************************************************************************************/ 155 156/************************************************************************************ 157** Externs 158************************************************************************************/ 159 160/************************************************************************************ 161** Functions 162************************************************************************************/ 163 164/******************************************************************************* 165** 166** Function is_connected 167** 168** Description Internal function to check if HF is connected 169** 170** Returns TRUE if connected 171** 172*******************************************************************************/ 173static BOOLEAN is_connected(bt_bdaddr_t *bd_addr) 174{ 175 int i; 176 for (i = 0; i < btif_max_hf_clients; ++i) 177 { 178 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) || 179 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) && 180 ((bd_addr == NULL) || (bdcmp(bd_addr->address, 181 btif_hf_cb[i].connected_bda.address) == 0))) 182 return TRUE; 183 } 184 return FALSE; 185} 186 187/******************************************************************************* 188** 189** Function btif_hf_idx_by_bdaddr 190** 191** Description Internal function to get idx by bdaddr 192** 193** Returns idx 194** 195*******************************************************************************/ 196static int btif_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr) 197{ 198 int i; 199 for (i = 0; i < btif_max_hf_clients; ++i) 200 { 201 if ((bdcmp(bd_addr->address, 202 btif_hf_cb[i].connected_bda.address) == 0)) 203 return i; 204 } 205 return BTIF_HF_INVALID_IDX; 206} 207 208/******************************************************************************* 209** 210** Function callstate_to_callsetup 211** 212** Description Converts HAL call state to BTA call setup indicator value 213** 214** Returns BTA call indicator value 215** 216*******************************************************************************/ 217static UINT8 callstate_to_callsetup(bthf_call_state_t call_state) 218{ 219 UINT8 call_setup = 0; 220 if (call_state == BTHF_CALL_STATE_INCOMING) 221 call_setup = 1; 222 if (call_state == BTHF_CALL_STATE_DIALING) 223 call_setup = 2; 224 if (call_state == BTHF_CALL_STATE_ALERTING) 225 call_setup = 3; 226 227 return call_setup; 228} 229 230/******************************************************************************* 231** 232** Function send_at_result 233** 234** Description Send AT result code (OK/ERROR) 235** 236** Returns void 237** 238*******************************************************************************/ 239static void send_at_result(UINT8 ok_flag, UINT16 errcode, int idx) 240{ 241 tBTA_AG_RES_DATA ag_res; 242 memset (&ag_res, 0, sizeof (ag_res)); 243 244 ag_res.ok_flag = ok_flag; 245 if (ok_flag == BTA_AG_OK_ERROR) 246 { 247 ag_res.errcode = errcode; 248 } 249 250 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res); 251} 252 253/******************************************************************************* 254** 255** Function send_indicator_update 256** 257** Description Send indicator update (CIEV) 258** 259** Returns void 260** 261*******************************************************************************/ 262static void send_indicator_update (UINT16 indicator, UINT16 value) 263{ 264 tBTA_AG_RES_DATA ag_res; 265 266 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); 267 ag_res.ind.id = indicator; 268 ag_res.ind.value = value; 269 270 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res); 271} 272 273void clear_phone_state_multihf(int idx) 274{ 275 btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE; 276 btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0; 277} 278 279/******************************************************************************* 280** 281** Function btif_hf_latest_connected_idx 282** 283** Description Returns idx for latest connected HF 284** 285** Returns int 286** 287*******************************************************************************/ 288static int btif_hf_latest_connected_idx() 289{ 290 struct timespec now, conn_time_delta; 291 int latest_conn_idx = BTIF_HF_INVALID_IDX, i; 292 293 clock_gettime(CLOCK_MONOTONIC, &now); 294 conn_time_delta.tv_sec = now.tv_sec; 295 296 for (i = 0; i < btif_max_hf_clients; i++) 297 { 298 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) 299 { 300 if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec) 301 < conn_time_delta.tv_sec) 302 { 303 conn_time_delta.tv_sec = 304 now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec; 305 latest_conn_idx = i; 306 } 307 } 308 } 309 return latest_conn_idx; 310} 311 312/******************************************************************************* 313** 314** Function btif_hf_check_if_slc_connected 315** 316** Description Returns BT_STATUS_SUCCESS if SLC is up for any HF 317** 318** Returns bt_status_t 319** 320*******************************************************************************/ 321static bt_status_t btif_hf_check_if_slc_connected() 322{ 323 if (bt_hf_callbacks == NULL) 324 { 325 BTIF_TRACE_WARNING1("BTHF: %s: BTHF not initialized", __FUNCTION__); 326 return BT_STATUS_NOT_READY; 327 } 328 else 329 { 330 int i; 331 for (i = 0; i < btif_max_hf_clients; i++) 332 { 333 if ((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) 334 { 335 BTIF_TRACE_EVENT2("BTHF: %s: slc connected for idx = %d", 336 __FUNCTION__, i); 337 return BT_STATUS_SUCCESS; 338 } 339 } 340 BTIF_TRACE_WARNING1("BTHF: %s: No SLC connection up", __FUNCTION__); 341 return BT_STATUS_NOT_READY; 342 } 343} 344 345/***************************************************************************** 346** Section name (Group of functions) 347*****************************************************************************/ 348 349/***************************************************************************** 350** 351** btif hf api functions (no context switch) 352** 353*****************************************************************************/ 354 355 356/******************************************************************************* 357** 358** Function btif_hf_upstreams_evt 359** 360** Description Executes HF UPSTREAMS events in btif context 361** 362** Returns void 363** 364*******************************************************************************/ 365static void btif_hf_upstreams_evt(UINT16 event, char* p_param) 366{ 367 tBTA_AG *p_data = (tBTA_AG *)p_param; 368 bdstr_t bdstr; 369 bt_bdaddr_t addr; 370 int idx = p_data->hdr.handle - 1; 371 372 BTIF_TRACE_DEBUG2("%s: event=%s", __FUNCTION__, dump_hf_event(event)); 373 374 switch (event) 375 { 376 case BTA_AG_ENABLE_EVT: 377 case BTA_AG_DISABLE_EVT: 378 break; 379 380 case BTA_AG_REGISTER_EVT: 381 btif_hf_cb[idx].handle = p_data->reg.hdr.handle; 382 BTIF_TRACE_DEBUG2("%s: BTA_AG_REGISTER_EVT," 383 "btif_hf_cb.handle = %d", __FUNCTION__, btif_hf_cb[idx].handle); 384 break; 385 386 case BTA_AG_OPEN_EVT: 387 if (p_data->open.status == BTA_AG_SUCCESS) 388 { 389 bdcpy(btif_hf_cb[idx].connected_bda.address, 390 p_data->open.bd_addr); 391 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED; 392 btif_hf_cb[idx].peer_feat = 0; 393 clear_phone_state_multihf(idx); 394 } 395 else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING) 396 { 397 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED; 398 } 399 else 400 { 401 BTIF_TRACE_WARNING4("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s", 402 __FUNCTION__, p_data->open.status, btif_hf_cb[idx].state, 403 bd2str(&btif_hf_cb[idx].connected_bda, &bdstr)); 404 break; 405 } 406 407 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state, 408 &btif_hf_cb[idx].connected_bda); 409 410 if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED) 411 bdsetany(btif_hf_cb[idx].connected_bda.address); 412 413 if (p_data->open.status != BTA_AG_SUCCESS) 414 btif_queue_advance(); 415 break; 416 417 case BTA_AG_CLOSE_EVT: 418 btif_hf_cb[idx].connected_timestamp.tv_sec = 0; 419 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED; 420 BTIF_TRACE_DEBUG3("%s: BTA_AG_CLOSE_EVT," 421 "idx = %d, btif_hf_cb.handle = %d", __FUNCTION__, idx, 422 btif_hf_cb[idx].handle); 423 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state, 424 &btif_hf_cb[idx].connected_bda); 425 bdsetany(btif_hf_cb[idx].connected_bda.address); 426 btif_hf_cb[idx].peer_feat = 0; 427 clear_phone_state_multihf(idx); 428 hf_idx = btif_hf_latest_connected_idx(); 429 /* If AG_OPEN was received but SLC was not setup in a specified time (10 seconds), 430 ** then AG_CLOSE may be received. We need to advance the queue here 431 */ 432 btif_queue_advance(); 433 break; 434 435 case BTA_AG_CONN_EVT: 436 clock_gettime(CLOCK_MONOTONIC, 437 &btif_hf_cb[idx].connected_timestamp); 438 BTIF_TRACE_DEBUG2("%s: BTA_AG_CONN_EVT, idx = %d ", 439 __FUNCTION__, idx); 440 btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat; 441 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED; 442 hf_idx = btif_hf_latest_connected_idx(); 443 444 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state, 445 &btif_hf_cb[idx].connected_bda); 446 btif_queue_advance(); 447 break; 448 449 case BTA_AG_AUDIO_OPEN_EVT: 450 hf_idx = idx; 451 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED, 452 &btif_hf_cb[idx].connected_bda); 453 break; 454 455 case BTA_AG_AUDIO_CLOSE_EVT: 456 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED, 457 &btif_hf_cb[idx].connected_bda); 458 break; 459 460 /* BTA auto-responds, silently discard */ 461 case BTA_AG_SPK_EVT: 462 case BTA_AG_MIC_EVT: 463 HAL_CBACK(bt_hf_callbacks, volume_cmd_cb, 464 (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK : 465 BTHF_VOLUME_TYPE_MIC, p_data->val.num, 466 &btif_hf_cb[idx].connected_bda); 467 break; 468 469 case BTA_AG_AT_A_EVT: 470 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0) 471 hf_idx = idx; 472 else 473 BTIF_TRACE_DEBUG0("Donot set hf_idx for ATA since already in a call"); 474 475 HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb, 476 &btif_hf_cb[idx].connected_bda); 477 break; 478 479 /* Java needs to send OK/ERROR for these commands */ 480 case BTA_AG_AT_BLDN_EVT: 481 case BTA_AG_AT_D_EVT: 482 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0) 483 hf_idx = idx; 484 else 485 BTIF_TRACE_DEBUG0("Donot set hf_idx for BLDN/D since already in a call"); 486 487 HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb, 488 (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL, 489 &btif_hf_cb[idx].connected_bda); 490 break; 491 492 case BTA_AG_AT_CHUP_EVT: 493 HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb, 494 &btif_hf_cb[idx].connected_bda); 495 break; 496 497 case BTA_AG_AT_CIND_EVT: 498 HAL_CBACK(bt_hf_callbacks, cind_cmd_cb, 499 &btif_hf_cb[idx].connected_bda); 500 break; 501 502 case BTA_AG_AT_VTS_EVT: 503 HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0], 504 &btif_hf_cb[idx].connected_bda); 505 break; 506 507 case BTA_AG_AT_BVRA_EVT: 508 HAL_CBACK(bt_hf_callbacks, vr_cmd_cb, 509 (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED : 510 BTHF_VR_STATE_STOPPED, &btif_hf_cb[idx].connected_bda); 511 break; 512 513 case BTA_AG_AT_NREC_EVT: 514 HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb, 515 (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP, 516 &btif_hf_cb[idx].connected_bda); 517 break; 518 519 /* TODO: Add a callback for CBC */ 520 case BTA_AG_AT_CBC_EVT: 521 break; 522 523 case BTA_AG_AT_CKPD_EVT: 524 HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb, 525 &btif_hf_cb[idx].connected_bda); 526 break; 527 528 /* Java needs to send OK/ERROR for these commands */ 529 case BTA_AG_AT_CHLD_EVT: 530 HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str), 531 &btif_hf_cb[idx].connected_bda); 532 break; 533 534 case BTA_AG_AT_CLCC_EVT: 535 HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb, 536 &btif_hf_cb[idx].connected_bda); 537 break; 538 539 case BTA_AG_AT_COPS_EVT: 540 HAL_CBACK(bt_hf_callbacks, cops_cmd_cb, 541 &btif_hf_cb[idx].connected_bda); 542 break; 543 544 case BTA_AG_AT_UNAT_EVT: 545 HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str, 546 &btif_hf_cb[idx].connected_bda); 547 break; 548 549 case BTA_AG_AT_CNUM_EVT: 550 HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb, 551 &btif_hf_cb[idx].connected_bda); 552 break; 553 554 /* TODO: Some of these commands may need to be sent to app. For now respond with error */ 555 case BTA_AG_AT_BINP_EVT: 556 case BTA_AG_AT_BTRH_EVT: 557 send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx); 558 break; 559 560 561 default: 562 BTIF_TRACE_WARNING2("%s: Unhandled event: %d", __FUNCTION__, event); 563 break; 564 } 565} 566 567/******************************************************************************* 568** 569** Function bte_hf_evt 570** 571** Description Switches context from BTE to BTIF for all HF events 572** 573** Returns void 574** 575*******************************************************************************/ 576 577static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *p_data) 578{ 579 bt_status_t status; 580 int param_len = 0; 581 582 /* TODO: BTA sends the union members and not tBTA_AG. If using param_len=sizeof(tBTA_AG), we get a crash on memcpy */ 583 if (BTA_AG_REGISTER_EVT == event) 584 param_len = sizeof(tBTA_AG_REGISTER); 585 else if (BTA_AG_OPEN_EVT == event) 586 param_len = sizeof(tBTA_AG_OPEN); 587 else if (BTA_AG_CONN_EVT == event) 588 param_len = sizeof(tBTA_AG_CONN); 589 else if ( (BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) || (BTA_AG_AUDIO_CLOSE_EVT == event)) 590 param_len = sizeof(tBTA_AG_HDR); 591 else if (p_data) 592 param_len = sizeof(tBTA_AG_VAL); 593 594 /* switch context to btif task context (copy full union size for convenience) */ 595 status = btif_transfer_context(btif_hf_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL); 596 597 /* catch any failed context transfers */ 598 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status); 599} 600 601 602/******************************************************************************* 603** 604** Function btif_in_hf_generic_evt 605** 606** Description Processes generic events to be sent to JNI that are not triggered from the BTA. 607** Always runs in BTIF context 608** 609** Returns void 610** 611*******************************************************************************/ 612static void btif_in_hf_generic_evt(UINT16 event, char *p_param) 613{ 614 int idx = btif_hf_idx_by_bdaddr((bt_bdaddr_t *)p_param); 615 616 BTIF_TRACE_EVENT2("%s: event=%d", __FUNCTION__, event); 617 switch (event) { 618 case BTIF_HFP_CB_AUDIO_CONNECTING: 619 { 620 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING, 621 &btif_hf_cb[idx].connected_bda); 622 } break; 623 default: 624 { 625 BTIF_TRACE_WARNING2("%s : Unknown event 0x%x", __FUNCTION__, event); 626 } 627 break; 628 } 629} 630 631 632/******************************************************************************* 633** 634** Function btif_hf_init 635** 636** Description initializes the hf interface 637** 638** Returns bt_status_t 639** 640*******************************************************************************/ 641static bt_status_t init( bthf_callbacks_t* callbacks, int max_hf_clients) 642{ 643 BTIF_TRACE_EVENT1("%s", __FUNCTION__); 644 int i; 645 646 bt_hf_callbacks = callbacks; 647 648 /* Invoke the enable service API to the core to set the appropriate service_id 649 * Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled (phone) 650 * othwerwise only HSP is enabled (tablet) 651 */ 652#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK)) 653 btif_enable_service(BTA_HFP_SERVICE_ID); 654#else 655 btif_enable_service(BTA_HSP_SERVICE_ID); 656#endif 657 658 memset(&btif_hf_cb, 0, sizeof(btif_hf_cb)); 659 btif_max_hf_clients = max_hf_clients; 660 BTIF_TRACE_DEBUG1("btif_max_hf_clients = %d", btif_max_hf_clients); 661 for (i = 0; i < btif_max_hf_clients; i++) 662 { 663 clear_phone_state_multihf(i); 664 } 665 666 return BT_STATUS_SUCCESS; 667} 668 669/******************************************************************************* 670** 671** Function connect 672** 673** Description connect to headset 674** 675** Returns bt_status_t 676** 677*******************************************************************************/ 678static bt_status_t connect_int( bt_bdaddr_t *bd_addr ) 679{ 680 CHECK_BTHF_INIT(); 681 int i; 682 for (i = 0; i < btif_max_hf_clients;) 683 { 684 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) || 685 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED))) 686 i++; 687 else 688 break; 689 } 690 691 if (i == btif_max_hf_clients) 692 return BT_STATUS_BUSY; 693 694 if (!is_connected(bd_addr)) 695 { 696 btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING; 697 bdcpy(btif_hf_cb[i].connected_bda.address, bd_addr->address); 698 699 BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda.address, 700 BTIF_HF_SECURITY, BTIF_HF_SERVICES); 701 return BT_STATUS_SUCCESS; 702 } 703 704 return BT_STATUS_BUSY; 705} 706 707static bt_status_t connect( bt_bdaddr_t *bd_addr ) 708{ 709 CHECK_BTHF_INIT(); 710 return btif_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_int); 711} 712 713/******************************************************************************* 714** 715** Function disconnect 716** 717** Description disconnect from headset 718** 719** Returns bt_status_t 720** 721*******************************************************************************/ 722static bt_status_t disconnect( bt_bdaddr_t *bd_addr ) 723{ 724 CHECK_BTHF_INIT(); 725 726 int idx = btif_hf_idx_by_bdaddr(bd_addr); 727 728 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 729 { 730 BTA_AgClose(btif_hf_cb[idx].handle); 731 return BT_STATUS_SUCCESS; 732 } 733 734 return BT_STATUS_FAIL; 735} 736 737/******************************************************************************* 738** 739** Function connect_audio 740** 741** Description create an audio connection 742** 743** Returns bt_status_t 744** 745*******************************************************************************/ 746static bt_status_t connect_audio( bt_bdaddr_t *bd_addr ) 747{ 748 CHECK_BTHF_INIT(); 749 750 int idx = btif_hf_idx_by_bdaddr(bd_addr); 751 752 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 753 { 754 BTA_AgAudioOpen(btif_hf_cb[idx].handle); 755 756 /* Inform the application that the audio connection has been initiated successfully */ 757 btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING, 758 (char *)bd_addr, sizeof(bt_bdaddr_t), NULL); 759 return BT_STATUS_SUCCESS; 760 } 761 762 return BT_STATUS_FAIL; 763} 764 765/******************************************************************************* 766** 767** Function disconnect_audio 768** 769** Description close the audio connection 770** 771** Returns bt_status_t 772** 773*******************************************************************************/ 774static bt_status_t disconnect_audio( bt_bdaddr_t *bd_addr ) 775{ 776 CHECK_BTHF_INIT(); 777 778 int idx = btif_hf_idx_by_bdaddr(bd_addr); 779 780 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 781 { 782 BTA_AgAudioClose(btif_hf_cb[idx].handle); 783 return BT_STATUS_SUCCESS; 784 } 785 786 return BT_STATUS_FAIL; 787} 788 789/******************************************************************************* 790** 791** Function start_voice_recognition 792** 793** Description start voice recognition 794** 795** Returns bt_status_t 796** 797*******************************************************************************/ 798static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr) 799{ 800 CHECK_BTHF_INIT(); 801 802 int idx = btif_hf_idx_by_bdaddr(bd_addr); 803 804 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 805 { 806 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) 807 { 808 tBTA_AG_RES_DATA ag_res; 809 memset(&ag_res, 0, sizeof(ag_res)); 810 ag_res.state = 1; 811 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res); 812 813 return BT_STATUS_SUCCESS; 814 } 815 else 816 { 817 return BT_STATUS_UNSUPPORTED; 818 } 819 } 820 821 return BT_STATUS_NOT_READY; 822} 823 824/******************************************************************************* 825** 826** Function stop_voice_recognition 827** 828** Description stop voice recognition 829** 830** Returns bt_status_t 831** 832*******************************************************************************/ 833static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr) 834{ 835 CHECK_BTHF_INIT(); 836 837 int idx = btif_hf_idx_by_bdaddr(bd_addr); 838 839 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 840 { 841 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) 842 { 843 tBTA_AG_RES_DATA ag_res; 844 memset(&ag_res, 0, sizeof(ag_res)); 845 ag_res.state = 0; 846 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res); 847 848 return BT_STATUS_SUCCESS; 849 } 850 else 851 { 852 return BT_STATUS_UNSUPPORTED; 853 } 854 } 855 856 return BT_STATUS_NOT_READY; 857} 858 859/******************************************************************************* 860** 861** Function volume_control 862** 863** Description volume control 864** 865** Returns bt_status_t 866** 867*******************************************************************************/ 868static bt_status_t volume_control(bthf_volume_type_t type, int volume, 869 bt_bdaddr_t *bd_addr) 870{ 871 CHECK_BTHF_INIT(); 872 873 int idx = btif_hf_idx_by_bdaddr(bd_addr); 874 875 tBTA_AG_RES_DATA ag_res; 876 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); 877 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 878 { 879 ag_res.num = volume; 880 BTA_AgResult(btif_hf_cb[idx].handle, 881 (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES, 882 &ag_res); 883 return BT_STATUS_SUCCESS; 884 } 885 886 return BT_STATUS_FAIL; 887} 888 889/******************************************************************************* 890** 891** Function device_status_notification 892** 893** Description Combined device status change notification 894** 895** Returns bt_status_t 896** 897*******************************************************************************/ 898static bt_status_t device_status_notification(bthf_network_state_t ntk_state, 899 bthf_service_type_t svc_type, int signal, int batt_chg) 900{ 901 CHECK_BTHF_INIT(); 902 903 if (is_connected(NULL)) 904 { 905 /* send all indicators to BTA. 906 ** BTA will make sure no duplicates are sent out 907 */ 908 send_indicator_update(BTA_AG_IND_SERVICE, 909 (ntk_state == BTHF_NETWORK_STATE_AVAILABLE) ? 1 : 0); 910 send_indicator_update(BTA_AG_IND_ROAM, 911 (svc_type == BTHF_SERVICE_TYPE_HOME) ? 0 : 1); 912 send_indicator_update(BTA_AG_IND_SIGNAL, signal); 913 send_indicator_update(BTA_AG_IND_BATTCHG, batt_chg); 914 return BT_STATUS_SUCCESS; 915 } 916 917 return BT_STATUS_SUCCESS; 918} 919 920/******************************************************************************* 921** 922** Function cops_response 923** 924** Description Response for COPS command 925** 926** Returns bt_status_t 927** 928*******************************************************************************/ 929static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr) 930{ 931 CHECK_BTHF_INIT(); 932 933 int idx = btif_hf_idx_by_bdaddr(bd_addr); 934 935 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 936 { 937 tBTA_AG_RES_DATA ag_res; 938 939 /* Format the response */ 940 sprintf (ag_res.str, "0,0,\"%s\"", cops); 941 ag_res.ok_flag = BTA_AG_OK_DONE; 942 943 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res); 944 return BT_STATUS_SUCCESS; 945 } 946 return BT_STATUS_FAIL; 947} 948 949/******************************************************************************* 950** 951** Function cind_response 952** 953** Description Response for CIND command 954** 955** Returns bt_status_t 956** 957*******************************************************************************/ 958static bt_status_t cind_response(int svc, int num_active, int num_held, 959 bthf_call_state_t call_setup_state, 960 int signal, int roam, int batt_chg, 961 bt_bdaddr_t *bd_addr) 962{ 963 CHECK_BTHF_INIT(); 964 965 int idx = btif_hf_idx_by_bdaddr(bd_addr); 966 967 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 968 { 969 tBTA_AG_RES_DATA ag_res; 970 971 memset (&ag_res, 0, sizeof (ag_res)); 972 /* per the errata 2043, call=1 implies atleast one call is in progress (active/held) 973 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043 974 **/ 975 sprintf (ag_res.str, "%d,%d,%d,%d,%d,%d,%d", 976 (num_active + num_held) ? 1 : 0, /* Call state */ 977 callstate_to_callsetup(call_setup_state), /* Callsetup state */ 978 svc, /* network service */ 979 signal, /* Signal strength */ 980 roam, /* Roaming indicator */ 981 batt_chg, /* Battery level */ 982 ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */ 983 984 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res); 985 986 return BT_STATUS_SUCCESS; 987 } 988 989 return BT_STATUS_FAIL; 990} 991 992/******************************************************************************* 993** 994** Function formatted_at_response 995** 996** Description Pre-formatted AT response, typically in response to unknown AT cmd 997** 998** Returns bt_status_t 999** 1000*******************************************************************************/ 1001static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr) 1002{ 1003 CHECK_BTHF_INIT(); 1004 tBTA_AG_RES_DATA ag_res; 1005 int idx = btif_hf_idx_by_bdaddr(bd_addr); 1006 1007 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 1008 { 1009 /* Format the response and send */ 1010 memset (&ag_res, 0, sizeof (ag_res)); 1011 strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN); 1012 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res); 1013 1014 return BT_STATUS_SUCCESS; 1015 } 1016 1017 return BT_STATUS_FAIL; 1018} 1019 1020/******************************************************************************* 1021** 1022** Function at_response 1023** 1024** Description ok/error response 1025** 1026** Returns bt_status_t 1027** 1028*******************************************************************************/ 1029static bt_status_t at_response(bthf_at_response_t response_code, 1030 int error_code, bt_bdaddr_t *bd_addr) 1031{ 1032 CHECK_BTHF_INIT(); 1033 1034 int idx = btif_hf_idx_by_bdaddr(bd_addr); 1035 1036 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 1037 { 1038 send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE 1039 : BTA_AG_OK_ERROR, error_code, idx); 1040 return BT_STATUS_SUCCESS; 1041 } 1042 1043 1044 return BT_STATUS_FAIL; 1045} 1046 1047/******************************************************************************* 1048** 1049** Function clcc_response 1050** 1051** Description response for CLCC command 1052** Can be iteratively called for each call index. Call index 1053** of 0 will be treated as NULL termination (Completes response) 1054** 1055** Returns bt_status_t 1056** 1057*******************************************************************************/ 1058static bt_status_t clcc_response(int index, bthf_call_direction_t dir, 1059 bthf_call_state_t state, bthf_call_mode_t mode, 1060 bthf_call_mpty_type_t mpty, const char *number, 1061 bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr) 1062{ 1063 CHECK_BTHF_INIT(); 1064 1065 int idx = btif_hf_idx_by_bdaddr(bd_addr); 1066 1067 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) 1068 { 1069 tBTA_AG_RES_DATA ag_res; 1070 int xx; 1071 1072 memset (&ag_res, 0, sizeof (ag_res)); 1073 1074 /* Format the response */ 1075 if (index == 0) 1076 { 1077 ag_res.ok_flag = BTA_AG_OK_DONE; 1078 } 1079 else 1080 { 1081 BTIF_TRACE_EVENT6("clcc_response: [%d] dir %d state %d mode %d number = %s type = %d", 1082 index, dir, state, mode, number, type); 1083 xx = sprintf (ag_res.str, "%d,%d,%d,%d,%d", 1084 index, dir, state, mode, mpty); 1085 1086 if (number) 1087 { 1088 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+')) 1089 sprintf (&ag_res.str[xx], ",\"+%s\",%d", number, type); 1090 else 1091 sprintf (&ag_res.str[xx], ",\"%s\",%d", number, type); 1092 } 1093 } 1094 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res); 1095 1096 return BT_STATUS_SUCCESS; 1097 } 1098 1099 return BT_STATUS_FAIL; 1100} 1101 1102/******************************************************************************* 1103** 1104** Function phone_state_change 1105** 1106** Description notify of a call state change 1107** number & type: valid only for incoming & waiting call 1108** 1109** Returns bt_status_t 1110** 1111*******************************************************************************/ 1112 1113static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_state_t call_setup_state, 1114 const char *number, bthf_call_addrtype_t type) 1115{ 1116 tBTA_AG_RES res = 0xff; 1117 tBTA_AG_RES_DATA ag_res; 1118 bt_status_t status = BT_STATUS_SUCCESS; 1119 BOOLEAN activeCallUpdated = FALSE; 1120 int idx, i; 1121 1122 /* hf_idx is index of connected HS that sent ATA/BLDN, 1123 otherwise index of latest connected HS */ 1124 if (hf_idx != BTIF_HF_INVALID_IDX) 1125 idx = hf_idx; 1126 else 1127 idx = btif_hf_latest_connected_idx(); 1128 1129 BTIF_TRACE_DEBUG1("phone_state_change: idx = %d", idx); 1130 1131 /* Check if SLC is connected */ 1132 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS) 1133 return BT_STATUS_NOT_READY; 1134 1135 BTIF_TRACE_DEBUG6("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]" 1136 " call_setup=%s [prev: %s]", num_active, btif_hf_cb[idx].num_active, 1137 num_held, btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state), 1138 dump_hf_call_state(btif_hf_cb[idx].call_setup_state)); 1139 1140 /* if all indicators are 0, send end call and return */ 1141 if (num_active == 0 && num_held == 0 && call_setup_state == BTHF_CALL_STATE_IDLE) 1142 { 1143 BTIF_TRACE_DEBUG1("%s: Phone on hook", __FUNCTION__); 1144 1145 /* record call termination timestamp if there was an active/held call or 1146 callsetup state > BTHF_CALL_STATE_IDLE */ 1147 if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE ) || 1148 (btif_hf_cb[idx].num_active) ||(btif_hf_cb[idx].num_held)) 1149 { 1150 BTIF_TRACE_DEBUG1("%s: Record call termination timestamp", __FUNCTION__); 1151 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp); 1152 } 1153 BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL); 1154 hf_idx = BTIF_HF_INVALID_IDX; 1155 1156 /* if held call was present, reset that as well */ 1157 if (btif_hf_cb[idx].num_held) 1158 send_indicator_update(BTA_AG_IND_CALLHELD, 0); 1159 1160 goto update_call_states; 1161 } 1162 1163 /* active state can change when: 1164 ** 1. an outgoing/incoming call was answered 1165 ** 2. an held was resumed 1166 ** 3. without callsetup notifications, call became active 1167 ** (3) can happen if call is active and a headset connects to us 1168 ** 1169 ** In the case of (3), we will have to notify the stack of an active 1170 ** call, instead of sending an indicator update. This will also 1171 ** force the SCO to be setup. Handle this special case here prior to 1172 ** call setup handling 1173 */ 1174 if ( (num_active == 1) && (btif_hf_cb[idx].num_active == 0) && (btif_hf_cb[idx].num_held == 0) 1175 && (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) ) 1176 { 1177 BTIF_TRACE_DEBUG1("%s: Active call notification received without call setup update", 1178 __FUNCTION__); 1179 1180 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); 1181 ag_res.audio_handle = btif_hf_cb[idx].handle; 1182 res = BTA_AG_OUT_CALL_CONN_RES; 1183 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res); 1184 activeCallUpdated = TRUE; 1185 } 1186 1187 /* Ringing call changed? */ 1188 if (call_setup_state != btif_hf_cb[idx].call_setup_state) 1189 { 1190 BTIF_TRACE_DEBUG3("%s: Call setup states changed. old: %s new: %s", 1191 __FUNCTION__, dump_hf_call_state(btif_hf_cb[idx].call_setup_state), 1192 dump_hf_call_state(call_setup_state)); 1193 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); 1194 1195 switch (call_setup_state) 1196 { 1197 case BTHF_CALL_STATE_IDLE: 1198 { 1199 switch (btif_hf_cb[idx].call_setup_state) 1200 { 1201 case BTHF_CALL_STATE_INCOMING: 1202 if (num_active > btif_hf_cb[idx].num_active) 1203 { 1204 res = BTA_AG_IN_CALL_CONN_RES; 1205 ag_res.audio_handle = btif_hf_cb[idx].handle; 1206 } 1207 else if (num_held > btif_hf_cb[idx].num_held) 1208 res = BTA_AG_IN_CALL_HELD_RES; 1209 else 1210 res = BTA_AG_CALL_CANCEL_RES; 1211 break; 1212 case BTHF_CALL_STATE_DIALING: 1213 case BTHF_CALL_STATE_ALERTING: 1214 if (num_active > btif_hf_cb[idx].num_active) 1215 { 1216 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE; 1217 res = BTA_AG_OUT_CALL_CONN_RES; 1218 } 1219 else 1220 res = BTA_AG_CALL_CANCEL_RES; 1221 break; 1222 default: 1223 BTIF_TRACE_ERROR1("%s: Incorrect Call setup state transition", __FUNCTION__); 1224 status = BT_STATUS_PARM_INVALID; 1225 break; 1226 } 1227 } break; 1228 1229 case BTHF_CALL_STATE_INCOMING: 1230 if (num_active || num_held) 1231 res = BTA_AG_CALL_WAIT_RES; 1232 else 1233 res = BTA_AG_IN_CALL_RES; 1234 if (number) 1235 { 1236 int xx = 0; 1237 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+')) 1238 xx = sprintf (ag_res.str, "\"+%s\"", number); 1239 else 1240 xx = sprintf (ag_res.str, "\"%s\"", number); 1241 ag_res.num = type; 1242 1243 if (res == BTA_AG_CALL_WAIT_RES) 1244 sprintf(&ag_res.str[xx], ",%d", type); 1245 } 1246 break; 1247 case BTHF_CALL_STATE_DIALING: 1248 ag_res.audio_handle = btif_hf_cb[idx].handle; 1249 res = BTA_AG_OUT_CALL_ORIG_RES; 1250 break; 1251 case BTHF_CALL_STATE_ALERTING: 1252 /* if we went from idle->alert, force SCO setup here. dialing usually triggers it */ 1253 if (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) 1254 ag_res.audio_handle = btif_hf_cb[idx].handle; 1255 res = BTA_AG_OUT_CALL_ALERT_RES; 1256 break; 1257 default: 1258 BTIF_TRACE_ERROR1("%s: Incorrect new ringing call state", __FUNCTION__); 1259 status = BT_STATUS_PARM_INVALID; 1260 break; 1261 } 1262 BTIF_TRACE_DEBUG3("%s: Call setup state changed. res=%d, audio_handle=%d", __FUNCTION__, res, ag_res.audio_handle); 1263 1264 if (res) 1265 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res); 1266 1267 /* if call setup is idle, we have already updated call indicator, jump out */ 1268 if (call_setup_state == BTHF_CALL_STATE_IDLE) 1269 { 1270 /* check & update callheld */ 1271 if ((num_held > 0) && (num_active > 0)) 1272 send_indicator_update(BTA_AG_IND_CALLHELD, 1); 1273 goto update_call_states; 1274 } 1275 } 1276 1277 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); 1278 1279 /* per the errata 2043, call=1 implies atleast one call is in progress (active/held) 1280 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043 1281 ** Handle call indicator change 1282 **/ 1283 if (!activeCallUpdated && ((num_active + num_held) != 1284 (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held)) ) 1285 { 1286 BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb[idx].num_active, num_active); 1287 send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0); 1288 } 1289 1290 /* Held Changed? */ 1291 if (num_held != btif_hf_cb[idx].num_held) 1292 { 1293 BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d", 1294 __FUNCTION__, btif_hf_cb[idx].num_held, num_held); 1295 send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); 1296 } 1297 1298 /* Calls Swapped? */ 1299 if ( (call_setup_state == btif_hf_cb[idx].call_setup_state) && 1300 (num_active && num_held) && 1301 (num_active == btif_hf_cb[idx].num_active) && 1302 (num_held == btif_hf_cb[idx].num_held) ) 1303 { 1304 BTIF_TRACE_DEBUG1("%s: Calls swapped", __FUNCTION__); 1305 send_indicator_update(BTA_AG_IND_CALLHELD, 1); 1306 } 1307 1308update_call_states: 1309 for (i = 0; i < btif_max_hf_clients; i++) 1310 { 1311 btif_hf_cb[i].num_active = num_active; 1312 btif_hf_cb[i].num_held = num_held; 1313 btif_hf_cb[i].call_setup_state = call_setup_state; 1314 } 1315 return status; 1316} 1317 1318 1319/******************************************************************************* 1320** 1321** Function btif_hf_call_terminated_recently 1322** 1323** Description Checks if a call has been terminated 1324** 1325** Returns bt_status_t 1326** 1327*******************************************************************************/ 1328BOOLEAN btif_hf_call_terminated_recently() 1329{ 1330 struct timespec now; 1331 1332 clock_gettime(CLOCK_MONOTONIC, &now); 1333 if (now.tv_sec < btif_hf_cb[0].call_end_timestamp.tv_sec + 1334 BTIF_HF_CALL_END_TIMEOUT) 1335 { 1336 return TRUE; 1337 } 1338 else 1339 { 1340 btif_hf_cb[0].call_end_timestamp.tv_sec = 0; 1341 return FALSE; 1342 } 1343} 1344 1345/******************************************************************************* 1346** 1347** Function cleanup 1348** 1349** Description Closes the HF interface 1350** 1351** Returns bt_status_t 1352** 1353*******************************************************************************/ 1354static void cleanup( void ) 1355{ 1356 BTIF_TRACE_EVENT1("%s", __FUNCTION__); 1357 1358 if (bt_hf_callbacks) 1359 { 1360 btif_disable_service(BTA_HFP_SERVICE_ID); 1361 bt_hf_callbacks = NULL; 1362 } 1363} 1364 1365static const bthf_interface_t bthfInterface = { 1366 sizeof(bthfInterface), 1367 init, 1368 connect, 1369 disconnect, 1370 connect_audio, 1371 disconnect_audio, 1372 start_voice_recognition, 1373 stop_voice_recognition, 1374 volume_control, 1375 device_status_notification, 1376 cops_response, 1377 cind_response, 1378 formatted_at_response, 1379 at_response, 1380 clcc_response, 1381 phone_state_change, 1382 cleanup, 1383}; 1384 1385/******************************************************************************* 1386** 1387** Function btif_hf_execute_service 1388** 1389** Description Initializes/Shuts down the service 1390** 1391** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise 1392** 1393*******************************************************************************/ 1394bt_status_t btif_hf_execute_service(BOOLEAN b_enable) 1395{ 1396 char * p_service_names[] = BTIF_HF_SERVICE_NAMES; 1397 int i; 1398 if (b_enable) 1399 { 1400 /* Enable and register with BTA-AG */ 1401 BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt); 1402 for (i = 0; i < btif_max_hf_clients; i++) 1403 { 1404 BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY, 1405 BTIF_HF_FEATURES, p_service_names, bthf_hf_id[i]); 1406 } 1407 } 1408 else { 1409 /* De-register AG */ 1410 for (i = 0; i < btif_max_hf_clients; i++) 1411 { 1412 BTA_AgDeregister(btif_hf_cb[i].handle); 1413 } 1414 /* Disable AG */ 1415 BTA_AgDisable(); 1416 } 1417 return BT_STATUS_SUCCESS; 1418} 1419 1420/******************************************************************************* 1421** 1422** Function btif_hf_get_interface 1423** 1424** Description Get the hf callback interface 1425** 1426** Returns bthf_interface_t 1427** 1428*******************************************************************************/ 1429const bthf_interface_t *btif_hf_get_interface() 1430{ 1431 BTIF_TRACE_EVENT1("%s", __FUNCTION__); 1432 return &bthfInterface; 1433} 1434