1 /****************************************************************************** 2 * 3 * Copyright (c) 2014 The Android Open Source Project 4 * Copyright (C) 2003-2012 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 20 /****************************************************************************** 21 * 22 * This file contains action functions for the handsfree client. 23 * 24 ******************************************************************************/ 25 26 #include "bta_api.h" 27 #include "bd.h" 28 #include "bta_hf_client_api.h" 29 #include "bta_hf_client_int.h" 30 #include "bta_dm_int.h" 31 #include "l2c_api.h" 32 #include "port_api.h" 33 #include "bta_sys.h" 34 #include "utl.h" 35 #include "bt_utils.h" 36 #include <string.h> 37 38 /***************************************************************************** 39 ** Constants 40 *****************************************************************************/ 41 42 /* maximum length of data to read from RFCOMM */ 43 #define BTA_HF_CLIENT_RFC_READ_MAX 512 44 45 /******************************************************************************* 46 ** 47 ** Function bta_hf_client_register 48 ** 49 ** Description This function initializes values of the scb and sets up 50 ** the SDP record for the services. 51 ** 52 ** 53 ** Returns void 54 ** 55 *******************************************************************************/ 56 void bta_hf_client_register(tBTA_HF_CLIENT_DATA *p_data) 57 { 58 tBTA_HF_CLIENT evt; 59 tBTA_UTL_COD cod; 60 61 memset(&evt, 0, sizeof(evt)); 62 63 /* initialize control block */ 64 bta_hf_client_scb_init(); 65 66 bta_hf_client_cb.scb.serv_sec_mask = p_data->api_register.sec_mask; 67 bta_hf_client_cb.scb.features = p_data->api_register.features; 68 69 /* initialize AT control block */ 70 bta_hf_client_at_init(); 71 72 /* create SDP records */ 73 bta_hf_client_create_record(p_data); 74 75 /* Set the Audio service class bit */ 76 cod.service = BTM_COD_SERVICE_AUDIO; 77 utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); 78 79 /* start RFCOMM server */ 80 bta_hf_client_start_server(); 81 82 /* call app callback with register event */ 83 evt.reg.status = BTA_HF_CLIENT_SUCCESS; 84 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_REGISTER_EVT, &evt); 85 } 86 87 /******************************************************************************* 88 ** 89 ** Function bta_hf_client_deregister 90 ** 91 ** Description This function removes the sdp records, closes the RFCOMM 92 ** servers, and deallocates the service control block. 93 ** 94 ** 95 ** Returns void 96 ** 97 *******************************************************************************/ 98 void bta_hf_client_deregister(tBTA_HF_CLIENT_DATA *p_data) 99 { 100 bta_hf_client_cb.scb.deregister = TRUE; 101 102 /* remove sdp record */ 103 bta_hf_client_del_record(p_data); 104 105 /* remove rfcomm server */ 106 bta_hf_client_close_server(); 107 108 /* disable */ 109 bta_hf_client_scb_disable(); 110 } 111 112 /******************************************************************************* 113 ** 114 ** Function bta_hf_client_start_dereg 115 ** 116 ** Description Start a deregister event. 117 ** 118 ** 119 ** Returns void 120 ** 121 *******************************************************************************/ 122 void bta_hf_client_start_dereg(tBTA_HF_CLIENT_DATA *p_data) 123 { 124 bta_hf_client_cb.scb.deregister = TRUE; 125 126 /* remove sdp record */ 127 bta_hf_client_del_record(p_data); 128 } 129 130 /******************************************************************************* 131 ** 132 ** Function bta_hf_client_start_close 133 ** 134 ** Description Start the process of closing SCO and RFCOMM connection. 135 ** 136 ** 137 ** Returns void 138 ** 139 *******************************************************************************/ 140 void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data) 141 { 142 /* Take the link out of sniff and set L2C idle time to 0 */ 143 bta_dm_pm_active(bta_hf_client_cb.scb.peer_addr); 144 L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0); 145 146 /* if SCO is open close SCO and wait on RFCOMM close */ 147 if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) 148 { 149 bta_hf_client_cb.scb.sco_close_rfc = TRUE; 150 } 151 else 152 { 153 bta_hf_client_rfc_do_close(p_data); 154 } 155 156 /* always do SCO shutdown to handle all SCO corner cases */ 157 bta_hf_client_sco_shutdown(NULL); 158 } 159 160 /******************************************************************************* 161 ** 162 ** Function bta_hf_client_start_open 163 ** 164 ** Description This starts an HF Client open. 165 ** 166 ** 167 ** Returns void 168 ** 169 *******************************************************************************/ 170 void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA *p_data) 171 { 172 BD_ADDR pending_bd_addr; 173 174 /* store parameters */ 175 if (p_data) 176 { 177 bdcpy(bta_hf_client_cb.scb.peer_addr, p_data->api_open.bd_addr); 178 bta_hf_client_cb.scb.cli_sec_mask = p_data->api_open.sec_mask; 179 } 180 181 /* Check if RFCOMM has any incoming connection to avoid collision. */ 182 if (PORT_IsOpening (pending_bd_addr)) 183 { 184 /* Let the incoming connection goes through. */ 185 /* Issue collision for now. */ 186 /* We will decide what to do when we find incoming connection later.*/ 187 bta_hf_client_collision_cback (0, BTA_ID_HS, 0, bta_hf_client_cb.scb.peer_addr); 188 return; 189 } 190 191 /* close server */ 192 bta_hf_client_close_server(); 193 194 /* set role */ 195 bta_hf_client_cb.scb.role = BTA_HF_CLIENT_INT; 196 197 /* do service search */ 198 bta_hf_client_do_disc(); 199 } 200 201 /******************************************************************************* 202 ** 203 ** Function bta_hf_client_cback_open 204 ** 205 ** Description Send open callback event to application. 206 ** 207 ** 208 ** Returns void 209 ** 210 *******************************************************************************/ 211 static void bta_hf_client_cback_open(tBTA_HF_CLIENT_DATA *p_data, tBTA_HF_CLIENT_STATUS status) 212 { 213 tBTA_HF_CLIENT evt; 214 215 memset(&evt, 0, sizeof(evt)); 216 217 /* call app callback with open event */ 218 evt.open.status = status; 219 if(p_data) 220 { 221 /* if p_data is provided then we need to pick the bd address from the open api structure */ 222 bdcpy(evt.open.bd_addr, p_data->api_open.bd_addr); 223 } 224 else 225 { 226 bdcpy(evt.open.bd_addr, bta_hf_client_cb.scb.peer_addr); 227 } 228 229 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_OPEN_EVT, &evt); 230 } 231 232 /******************************************************************************* 233 ** 234 ** Function bta_hf_client_rfc_open 235 ** 236 ** Description Handle RFCOMM channel open. 237 ** 238 ** 239 ** Returns void 240 ** 241 *******************************************************************************/ 242 void bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA *p_data) 243 { 244 UNUSED(p_data); 245 246 bta_sys_conn_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 247 248 bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_SUCCESS); 249 250 /* start SLC procedure */ 251 bta_hf_client_slc_seq(FALSE); 252 } 253 254 /******************************************************************************* 255 ** 256 ** Function bta_hf_client_rfc_acp_open 257 ** 258 ** Description Handle RFCOMM channel open when accepting connection. 259 ** 260 ** 261 ** Returns void 262 ** 263 *******************************************************************************/ 264 void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA *p_data) 265 { 266 UINT16 lcid; 267 int i; 268 BD_ADDR dev_addr; 269 int status; 270 271 /* set role */ 272 bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; 273 274 APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open: serv_handle = %d rfc.port_handle = %d", 275 bta_hf_client_cb.scb.serv_handle, p_data->rfc.port_handle); 276 277 /* get bd addr of peer */ 278 if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) 279 { 280 APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open error PORT_CheckConnection returned status %d", status); 281 } 282 283 /* Collision Handling */ 284 if (bta_hf_client_cb.scb.colli_tmr_on) 285 { 286 /* stop collision timer */ 287 bta_hf_client_cb.scb.colli_tmr_on = FALSE; 288 bta_sys_stop_timer (&bta_hf_client_cb.scb.colli_timer); 289 290 if (bdcmp (dev_addr, bta_hf_client_cb.scb.peer_addr) == 0) 291 { 292 /* If incoming and outgoing device are same, nothing more to do. */ 293 /* Outgoing conn will be aborted because we have successful incoming conn. */ 294 } 295 else 296 { 297 /* Resume outgoing connection. */ 298 bta_hf_client_resume_open (); 299 } 300 } 301 302 bdcpy (bta_hf_client_cb.scb.peer_addr, dev_addr); 303 bta_hf_client_cb.scb.conn_handle = p_data->rfc.port_handle; 304 305 /* do service discovery to get features */ 306 bta_hf_client_do_disc(); 307 308 /* continue with open processing */ 309 bta_hf_client_rfc_open(p_data); 310 } 311 312 /******************************************************************************* 313 ** 314 ** Function bta_hf_client_rfc_fail 315 ** 316 ** Description RFCOMM connection failed. 317 ** 318 ** 319 ** Returns void 320 ** 321 *******************************************************************************/ 322 void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA *p_data) 323 { 324 UNUSED(p_data); 325 326 /* reinitialize stuff */ 327 bta_hf_client_cb.scb.conn_handle = 0; 328 bta_hf_client_cb.scb.peer_features = 0; 329 bta_hf_client_cb.scb.chld_features = 0; 330 bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; 331 bta_hf_client_cb.scb.svc_conn = FALSE; 332 bta_hf_client_cb.scb.send_at_reply = FALSE; 333 bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; 334 335 bta_hf_client_at_reset(); 336 337 /* reopen server */ 338 bta_hf_client_start_server(); 339 340 /* call open cback w. failure */ 341 bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_FAIL_RFCOMM); 342 } 343 344 /******************************************************************************* 345 ** 346 ** Function bta_hf_client_disc_fail 347 ** 348 ** Description This function handles a discovery failure. 349 ** 350 ** 351 ** Returns void 352 ** 353 *******************************************************************************/ 354 void bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA *p_data) 355 { 356 UNUSED(p_data); 357 358 /* reopen server */ 359 bta_hf_client_start_server(); 360 361 /* reinitialize stuff */ 362 363 /* call open cback w. failure */ 364 bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_FAIL_SDP); 365 } 366 367 /******************************************************************************* 368 ** 369 ** Function bta_hf_client_open_fail 370 ** 371 ** Description open connection failed. 372 ** 373 ** 374 ** Returns void 375 ** 376 *******************************************************************************/ 377 void bta_hf_client_open_fail(tBTA_HF_CLIENT_DATA *p_data) 378 { 379 /* call open cback w. failure */ 380 bta_hf_client_cback_open(p_data, BTA_HF_CLIENT_FAIL_RESOURCES); 381 } 382 383 /******************************************************************************* 384 ** 385 ** Function bta_hf_client_rfc_close 386 ** 387 ** Description RFCOMM connection closed. 388 ** 389 ** 390 ** Returns void 391 ** 392 *******************************************************************************/ 393 void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA *p_data) 394 { 395 int i, num_active_conn = 0; 396 UNUSED(p_data); 397 398 /* reinitialize stuff */ 399 bta_hf_client_cb.scb.peer_features = 0; 400 bta_hf_client_cb.scb.chld_features = 0; 401 bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; 402 bta_hf_client_cb.scb.svc_conn = FALSE; 403 bta_hf_client_cb.scb.send_at_reply = FALSE; 404 bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; 405 406 bta_hf_client_at_reset(); 407 408 bta_sys_conn_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 409 410 /* call close cback */ 411 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLOSE_EVT, NULL); 412 413 /* if not deregistering reopen server */ 414 if (bta_hf_client_cb.scb.deregister == FALSE) 415 { 416 /* Clear peer bd_addr so instance can be reused */ 417 bdcpy(bta_hf_client_cb.scb.peer_addr, bd_addr_null); 418 419 /* start server as it might got closed on open*/ 420 bta_hf_client_start_server(); 421 422 bta_hf_client_cb.scb.conn_handle = 0; 423 424 /* Make sure SCO is shutdown */ 425 bta_hf_client_sco_shutdown(NULL); 426 427 bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); 428 } 429 /* else close port and deallocate scb */ 430 else 431 { 432 bta_hf_client_close_server(); 433 bta_hf_client_scb_disable(); 434 } 435 } 436 437 /******************************************************************************* 438 ** 439 ** Function bta_hf_client_disc_int_res 440 ** 441 ** Description This function handles a discovery result when initiator. 442 ** 443 ** 444 ** Returns void 445 ** 446 *******************************************************************************/ 447 void bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA *p_data) 448 { 449 UINT16 event = BTA_HF_CLIENT_DISC_FAIL_EVT; 450 451 APPL_TRACE_DEBUG ("bta_hf_client_disc_int_res: Status: %d", p_data->disc_result.status); 452 453 /* if found service */ 454 if (p_data->disc_result.status == SDP_SUCCESS || 455 p_data->disc_result.status == SDP_DB_FULL) 456 { 457 /* get attributes */ 458 if (bta_hf_client_sdp_find_attr()) 459 { 460 event = BTA_HF_CLIENT_DISC_OK_EVT; 461 } 462 } 463 464 /* free discovery db */ 465 bta_hf_client_free_db(p_data); 466 467 /* send ourselves sdp ok/fail event */ 468 bta_hf_client_sm_execute(event, p_data); 469 } 470 471 /******************************************************************************* 472 ** 473 ** Function bta_hf_client_disc_acp_res 474 ** 475 ** Description This function handles a discovery result when acceptor. 476 ** 477 ** 478 ** Returns void 479 ** 480 *******************************************************************************/ 481 void bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA *p_data) 482 { 483 /* if found service */ 484 if (p_data->disc_result.status == SDP_SUCCESS || 485 p_data->disc_result.status == SDP_DB_FULL) 486 { 487 /* get attributes */ 488 bta_hf_client_sdp_find_attr(); 489 } 490 491 /* free discovery db */ 492 bta_hf_client_free_db(p_data); 493 } 494 495 /******************************************************************************* 496 ** 497 ** Function bta_hf_client_rfc_data 498 ** 499 ** Description Read and process data from RFCOMM. 500 ** 501 ** 502 ** Returns void 503 ** 504 *******************************************************************************/ 505 void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA *p_data) 506 { 507 UINT16 len; 508 char buf[BTA_HF_CLIENT_RFC_READ_MAX]; 509 UNUSED(p_data); 510 511 memset(buf, 0, sizeof(buf)); 512 513 /* read data from rfcomm; if bad status, we're done */ 514 while (PORT_ReadData(bta_hf_client_cb.scb.conn_handle, buf, BTA_HF_CLIENT_RFC_READ_MAX, &len) == PORT_SUCCESS) 515 { 516 /* if no data, we're done */ 517 if (len == 0) 518 { 519 break; 520 } 521 522 bta_hf_client_at_parse(buf, len); 523 524 /* no more data to read, we're done */ 525 if (len < BTA_HF_CLIENT_RFC_READ_MAX) 526 { 527 break; 528 } 529 } 530 } 531 532 /******************************************************************************* 533 ** 534 ** Function bta_hf_client_svc_conn_open 535 ** 536 ** Description Service level connection opened 537 ** 538 ** 539 ** Returns void 540 ** 541 *******************************************************************************/ 542 void bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA *p_data) 543 { 544 tBTA_HF_CLIENT evt; 545 UNUSED(p_data); 546 547 memset(&evt, 0, sizeof(evt)); 548 549 if (!bta_hf_client_cb.scb.svc_conn) 550 { 551 /* set state variable */ 552 bta_hf_client_cb.scb.svc_conn = TRUE; 553 554 /* call callback */ 555 evt.conn.peer_feat = bta_hf_client_cb.scb.peer_features; 556 evt.conn.chld_feat = bta_hf_client_cb.scb.chld_features; 557 558 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CONN_EVT, &evt); 559 } 560 } 561 562 /******************************************************************************* 563 ** 564 ** Function bta_hf_client_cback_ind 565 ** 566 ** Description Send indicator callback event to application. 567 ** 568 ** Returns void 569 ** 570 *******************************************************************************/ 571 void bta_hf_client_ind(tBTA_HF_CLIENT_IND_TYPE type, UINT16 value) 572 { 573 tBTA_HF_CLIENT evt; 574 575 memset(&evt, 0, sizeof(evt)); 576 577 evt.ind.type = type; 578 evt.ind.value = value; 579 580 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_IND_EVT, &evt); 581 } 582 583 /******************************************************************************* 584 ** 585 ** Function bta_hf_client_evt_val 586 ** 587 ** Description Send event to application. 588 ** This is a generic helper for events with common data. 589 ** 590 ** 591 ** Returns void 592 ** 593 *******************************************************************************/ 594 void bta_hf_client_evt_val(tBTA_HF_CLIENT_EVT type, UINT16 value) 595 { 596 tBTA_HF_CLIENT evt; 597 598 memset(&evt, 0, sizeof(evt)); 599 600 evt.val.value = value; 601 602 (*bta_hf_client_cb.p_cback)(type, &evt); 603 } 604 605 /******************************************************************************* 606 ** 607 ** Function bta_hf_client_operator_name 608 ** 609 ** Description Send operator name event to application. 610 ** 611 ** 612 ** Returns void 613 ** 614 *******************************************************************************/ 615 void bta_hf_client_operator_name(char *name) 616 { 617 tBTA_HF_CLIENT evt; 618 619 memset(&evt, 0, sizeof(evt)); 620 621 strlcpy(evt.operator.name, name, BTA_HF_CLIENT_OPERATOR_NAME_LEN + 1); 622 evt.operator.name[BTA_HF_CLIENT_OPERATOR_NAME_LEN] = '\0'; 623 624 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_OPERATOR_NAME_EVT, &evt); 625 } 626 627 628 /******************************************************************************* 629 ** 630 ** Function bta_hf_client_clip 631 ** 632 ** Description Send CLIP event to application. 633 ** 634 ** 635 ** Returns void 636 ** 637 *******************************************************************************/ 638 void bta_hf_client_clip(char *number) 639 { 640 tBTA_HF_CLIENT evt; 641 642 memset(&evt, 0, sizeof(evt)); 643 644 strlcpy(evt.number.number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); 645 evt.number.number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; 646 647 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLIP_EVT, &evt); 648 } 649 650 /******************************************************************************* 651 ** 652 ** Function bta_hf_client_ccwa 653 ** 654 ** Description Send CLIP event to application. 655 ** 656 ** 657 ** Returns void 658 ** 659 *******************************************************************************/ 660 void bta_hf_client_ccwa(char *number) 661 { 662 tBTA_HF_CLIENT evt; 663 664 memset(&evt, 0, sizeof(evt)); 665 666 strlcpy(evt.number.number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); 667 evt.number.number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; 668 669 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CCWA_EVT, &evt); 670 } 671 672 /******************************************************************************* 673 ** 674 ** Function bta_hf_client_at_result 675 ** 676 ** Description Send AT result event to application. 677 ** 678 ** 679 ** Returns void 680 ** 681 *******************************************************************************/ 682 void bta_hf_client_at_result(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme) 683 { 684 tBTA_HF_CLIENT evt; 685 686 memset(&evt, 0, sizeof(evt)); 687 688 evt.result.type = type; 689 evt.result.cme = cme; 690 691 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_AT_RESULT_EVT, &evt); 692 } 693 694 /******************************************************************************* 695 ** 696 ** Function bta_hf_client_clcc 697 ** 698 ** Description Send clcc event to application. 699 ** 700 ** 701 ** Returns void 702 ** 703 *******************************************************************************/ 704 void bta_hf_client_clcc(UINT32 idx, BOOLEAN incoming, UINT8 status, BOOLEAN mpty, char *number) 705 { 706 tBTA_HF_CLIENT evt; 707 708 memset(&evt, 0, sizeof(evt)); 709 710 evt.clcc.idx = idx; 711 evt.clcc.inc = incoming; 712 evt.clcc.status = status; 713 evt.clcc.mpty = mpty; 714 715 if (number) 716 { 717 evt.clcc.number_present = TRUE; 718 strlcpy(evt.clcc.number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); 719 evt.clcc.number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; 720 } 721 722 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLCC_EVT, &evt); 723 } 724 725 /******************************************************************************* 726 ** 727 ** Function bta_hf_client_cnum 728 ** 729 ** Description Send cnum event to application. 730 ** 731 ** 732 ** Returns void 733 ** 734 *******************************************************************************/ 735 void bta_hf_client_cnum(char *number, UINT16 service) 736 { 737 tBTA_HF_CLIENT evt; 738 739 memset(&evt, 0, sizeof(evt)); 740 741 evt.cnum.service = service; 742 strlcpy(evt.cnum.number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); 743 evt.cnum.number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; 744 745 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CNUM_EVT, &evt); 746 } 747 748 /******************************************************************************* 749 ** 750 ** Function bta_hf_client_binp 751 ** 752 ** Description Send BINP event to application. 753 ** 754 ** 755 ** Returns void 756 ** 757 *******************************************************************************/ 758 void bta_hf_client_binp(char *number) 759 { 760 tBTA_HF_CLIENT evt; 761 762 memset(&evt, 0, sizeof(evt)); 763 764 strlcpy(evt.number.number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); 765 evt.number.number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; 766 767 (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_BINP_EVT, &evt); 768 } 769