blob: d2e835499f7020dccd777d4817330fbaec5a4459 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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
The Android Open Source Project5738f832012-12-12 16:00:35 -080074#define BTIF_HF_CALL_END_TIMEOUT 6
75
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070076#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
The Android Open Source Project5738f832012-12-12 16:00:35 -080099/************************************************************************************
100** Local type definitions
101************************************************************************************/
102
103/************************************************************************************
104** Static variables
105************************************************************************************/
106static bthf_callbacks_t *bt_hf_callbacks = NULL;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700107static int hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800108
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;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700145 struct timespec connected_timestamp;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800146 bthf_call_state_t call_setup_state;
147} btif_hf_cb_t;
148
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700149static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800150
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{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700175 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 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800184 return FALSE;
185}
186
187/*******************************************************************************
188**
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700189** 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**
The Android Open Source Project5738f832012-12-12 16:00:35 -0800210** 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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700239static void send_at_result(UINT8 ok_flag, UINT16 errcode, int idx)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800240{
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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700250 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800251}
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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700273void clear_phone_state_multihf(int idx)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800274{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700275 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;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800277}
278
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700279/*******************************************************************************
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}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800344
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;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700369 bt_bdaddr_t addr;
370 int idx = p_data->hdr.handle - 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800371
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:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700381 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);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800384 break;
385
386 case BTA_AG_OPEN_EVT:
387 if (p_data->open.status == BTA_AG_SUCCESS)
388 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700389 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);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800394 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700395 else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800396 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700397 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800398 }
399 else
400 {
401 BTIF_TRACE_WARNING4("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s",
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700402 __FUNCTION__, p_data->open.status, btif_hf_cb[idx].state,
403 bd2str(&btif_hf_cb[idx].connected_bda, &bdstr));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800404 break;
405 }
406
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700407 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
408 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800409
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700410 if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
411 bdsetany(btif_hf_cb[idx].connected_bda.address);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800412
413 if (p_data->open.status != BTA_AG_SUCCESS)
414 btif_queue_advance();
415 break;
416
417 case BTA_AG_CLOSE_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700418 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();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800429 /* 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:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700436 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();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800443
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700444 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
445 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800446 btif_queue_advance();
447 break;
448
449 case BTA_AG_AUDIO_OPEN_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700450 hf_idx = idx;
451 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
452 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800453 break;
454
455 case BTA_AG_AUDIO_CLOSE_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700456 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
457 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800458 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,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700464 (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);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800467 break;
468
469 case BTA_AG_AT_A_EVT:
Hemant Gupta4974d812014-05-05 17:45:08 +0530470 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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700475 HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
476 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800477 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:
Hemant Gupta4974d812014-05-05 17:45:08 +0530482 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
The Android Open Source Project5738f832012-12-12 16:00:35 -0800487 HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700488 (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
489 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800490 break;
491
492 case BTA_AG_AT_CHUP_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700493 HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
494 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800495 break;
496
497 case BTA_AG_AT_CIND_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700498 HAL_CBACK(bt_hf_callbacks, cind_cmd_cb,
499 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800500 break;
501
502 case BTA_AG_AT_VTS_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700503 HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
504 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800505 break;
506
507 case BTA_AG_AT_BVRA_EVT:
508 HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700509 (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED :
510 BTHF_VR_STATE_STOPPED, &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800511 break;
512
513 case BTA_AG_AT_NREC_EVT:
514 HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700515 (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
516 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800517 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:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700524 HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
525 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800526 break;
527
528 /* Java needs to send OK/ERROR for these commands */
529 case BTA_AG_AT_CHLD_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700530 HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str),
531 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800532 break;
533
534 case BTA_AG_AT_CLCC_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700535 HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb,
536 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800537 break;
538
539 case BTA_AG_AT_COPS_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700540 HAL_CBACK(bt_hf_callbacks, cops_cmd_cb,
541 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800542 break;
543
544 case BTA_AG_AT_UNAT_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700545 HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
546 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800547 break;
548
549 case BTA_AG_AT_CNUM_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700550 HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb,
551 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800552 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:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700557 send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800558 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{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700614 int idx = btif_hf_idx_by_bdaddr((bt_bdaddr_t *)p_param);
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800615
The Android Open Source Project5738f832012-12-12 16:00:35 -0800616 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,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700621 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800622 } 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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700641static bt_status_t init( bthf_callbacks_t* callbacks, int max_hf_clients)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800642{
643 BTIF_TRACE_EVENT1("%s", __FUNCTION__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700644 int i;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800645
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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700658 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 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800665
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{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700680 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
The Android Open Source Project5738f832012-12-12 16:00:35 -0800694 if (!is_connected(bd_addr))
695 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700696 btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
697 bdcpy(btif_hf_cb[i].connected_bda.address, bd_addr->address);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800698
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700699 BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda.address,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800700 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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700726 int idx = btif_hf_idx_by_bdaddr(bd_addr);
727
728 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800729 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700730 BTA_AgClose(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800731 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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700750 int idx = btif_hf_idx_by_bdaddr(bd_addr);
751
752 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800753 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700754 BTA_AgAudioOpen(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800755
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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700778 int idx = btif_hf_idx_by_bdaddr(bd_addr);
779
780 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800781 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700782 BTA_AgAudioClose(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800783 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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700798static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800799{
800 CHECK_BTHF_INIT();
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700801
802 int idx = btif_hf_idx_by_bdaddr(bd_addr);
803
804 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800805 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700806 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800807 {
808 tBTA_AG_RES_DATA ag_res;
809 memset(&ag_res, 0, sizeof(ag_res));
810 ag_res.state = 1;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700811 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800812
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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700833static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800834{
835 CHECK_BTHF_INIT();
836
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700837 int idx = btif_hf_idx_by_bdaddr(bd_addr);
838
839 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800840 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700841 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800842 {
843 tBTA_AG_RES_DATA ag_res;
844 memset(&ag_res, 0, sizeof(ag_res));
845 ag_res.state = 0;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700846 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800847
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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700868static bt_status_t volume_control(bthf_volume_type_t type, int volume,
869 bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800870{
871 CHECK_BTHF_INIT();
872
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700873 int idx = btif_hf_idx_by_bdaddr(bd_addr);
874
The Android Open Source Project5738f832012-12-12 16:00:35 -0800875 tBTA_AG_RES_DATA ag_res;
876 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700877 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800878 {
879 ag_res.num = volume;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700880 BTA_AgResult(btif_hf_cb[idx].handle,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800881 (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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700929static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800930{
931 CHECK_BTHF_INIT();
932
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700933 int idx = btif_hf_idx_by_bdaddr(bd_addr);
934
935 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800936 {
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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700943 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800944 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,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700960 int signal, int roam, int batt_chg,
961 bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800962{
963 CHECK_BTHF_INIT();
964
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700965 int idx = btif_hf_idx_by_bdaddr(bd_addr);
966
967 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800968 {
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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700984 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800985
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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001001static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001002{
1003 CHECK_BTHF_INIT();
1004 tBTA_AG_RES_DATA ag_res;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001005 int idx = btif_hf_idx_by_bdaddr(bd_addr);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001006
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001007 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001008 {
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);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001012 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001013
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*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001029static bt_status_t at_response(bthf_at_response_t response_code,
1030 int error_code, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001031{
1032 CHECK_BTHF_INIT();
1033
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001034 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1035
1036 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001037 {
1038 send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001039 : BTA_AG_OK_ERROR, error_code, idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001040 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,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001059 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)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001062{
1063 CHECK_BTHF_INIT();
1064
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001065 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1066
1067 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001068 {
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 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001094 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001095
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;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001120 int idx, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001121
Hemant Gupta4974d812014-05-05 17:45:08 +05301122 /* 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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001129 BTIF_TRACE_DEBUG1("phone_state_change: idx = %d", idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001130
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001131 /* 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));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001139
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
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001145 /* 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))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001149 {
1150 BTIF_TRACE_DEBUG1("%s: Record call termination timestamp", __FUNCTION__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001151 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001152 }
1153 BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001154 hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001155
1156 /* if held call was present, reset that as well */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001157 if (btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001158 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 */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001174 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) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001176 {
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));
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001181 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001182 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? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001188 if (call_setup_state != btif_hf_cb[idx].call_setup_state)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001189 {
1190 BTIF_TRACE_DEBUG3("%s: Call setup states changed. old: %s new: %s",
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001191 __FUNCTION__, dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001192 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 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001199 switch (btif_hf_cb[idx].call_setup_state)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001200 {
1201 case BTHF_CALL_STATE_INCOMING:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001202 if (num_active > btif_hf_cb[idx].num_active)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001203 {
1204 res = BTA_AG_IN_CALL_CONN_RES;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001205 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001206 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001207 else if (num_held > btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001208 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:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001214 if (num_active > btif_hf_cb[idx].num_active)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001215 {
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:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001248 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001249 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 */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001253 if (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE)
1254 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001255 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 **/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001283 if (!activeCallUpdated && ((num_active + num_held) !=
1284 (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held)) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001285 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001286 BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb[idx].num_active, num_active);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001287 send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
1288 }
1289
1290 /* Held Changed? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001291 if (num_held != btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001292 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001293 BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d",
1294 __FUNCTION__, btif_hf_cb[idx].num_held, num_held);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001295 send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
1296 }
1297
1298 /* Calls Swapped? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001299 if ( (call_setup_state == btif_hf_cb[idx].call_setup_state) &&
The Android Open Source Project5738f832012-12-12 16:00:35 -08001300 (num_active && num_held) &&
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001301 (num_active == btif_hf_cb[idx].num_active) &&
1302 (num_held == btif_hf_cb[idx].num_held) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001303 {
1304 BTIF_TRACE_DEBUG1("%s: Calls swapped", __FUNCTION__);
1305 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
1306 }
1307
1308update_call_states:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001309 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 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001315 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);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001333 if (now.tv_sec < btif_hf_cb[0].call_end_timestamp.tv_sec +
1334 BTIF_HF_CALL_END_TIMEOUT)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001335 {
1336 return TRUE;
1337 }
1338 else
1339 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001340 btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001341 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 = {
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001366 sizeof(bthfInterface),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001367 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;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001397 int i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001398 if (b_enable)
1399 {
1400 /* Enable and register with BTA-AG */
1401 BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001402 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 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001407 }
1408 else {
1409 /* De-register AG */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001410 for (i = 0; i < btif_max_hf_clients; i++)
1411 {
1412 BTA_AgDeregister(btif_hf_cb[i].handle);
1413 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001414 /* 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}