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