blob: c0cc4df18e9af60c724dbd22a16db981a570f06a [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
Matthew Xie66432dc2014-04-27 05:45:32 -070063#if (BTM_WBS_INCLUDED == TRUE )
64#ifndef BTIF_HF_FEATURES
65#define BTIF_HF_FEATURES ( BTA_AG_FEAT_3WAY | \
66 BTA_AG_FEAT_ECNR | \
67 BTA_AG_FEAT_REJECT | \
68 BTA_AG_FEAT_ECS | \
69 BTA_AG_FEAT_EXTERR | \
70 BTA_AG_FEAT_BTRH | \
71 BTA_AG_FEAT_VREC | \
72 BTA_AG_FEAT_CODEC |\
73 BTA_AG_FEAT_UNAT)
74#endif
75#else
The Android Open Source Project5738f832012-12-12 16:00:35 -080076#ifndef BTIF_HF_FEATURES
77#define BTIF_HF_FEATURES ( BTA_AG_FEAT_3WAY | \
78 BTA_AG_FEAT_ECNR | \
79 BTA_AG_FEAT_REJECT | \
80 BTA_AG_FEAT_ECS | \
81 BTA_AG_FEAT_EXTERR | \
82 BTA_AG_FEAT_BTRH | \
83 BTA_AG_FEAT_VREC | \
84 BTA_AG_FEAT_UNAT)
85#endif
Matthew Xie66432dc2014-04-27 05:45:32 -070086#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -080087
The Android Open Source Project5738f832012-12-12 16:00:35 -080088#define BTIF_HF_CALL_END_TIMEOUT 6
89
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070090#define BTIF_HF_INVALID_IDX -1
91
92/* Number of BTIF-HF control blocks */
93#define BTIF_HF_NUM_CB 2
94
95/* Max HF clients supported from App */
96UINT16 btif_max_hf_clients = -1;
97
98/* HF app ids for service registration */
99typedef enum {
100 BTIF_HF_ID_1 = 0,
101 BTIF_HF_ID_2,
102#if (BTIF_HF_NUM_CB == 3)
103 BTIF_HF_ID_3
104#endif
105} bthf_hf_id_t;
106
107UINT16 bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2,
108 #if (BTIF_HF_NUM_CB == 3)
109 BTIF_HF_ID_3
110 #endif
111 };
112
The Android Open Source Project5738f832012-12-12 16:00:35 -0800113/************************************************************************************
114** Local type definitions
115************************************************************************************/
116
117/************************************************************************************
118** Static variables
119************************************************************************************/
120static bthf_callbacks_t *bt_hf_callbacks = NULL;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700121static int hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800122
123#define CHECK_BTHF_INIT() if (bt_hf_callbacks == NULL)\
124 {\
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700125 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __FUNCTION__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800126 return BT_STATUS_NOT_READY;\
127 }\
128 else\
129 {\
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700130 BTIF_TRACE_EVENT("BTHF: %s", __FUNCTION__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800131 }
132
133#define CHECK_BTHF_SLC_CONNECTED() if (bt_hf_callbacks == NULL)\
134 {\
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700135 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __FUNCTION__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800136 return BT_STATUS_NOT_READY;\
137 }\
138 else if (btif_hf_cb.state != BTHF_CONNECTION_STATE_SLC_CONNECTED)\
139 {\
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700140 BTIF_TRACE_WARNING("BTHF: %s: SLC connection not up. state=%s", __FUNCTION__, dump_hf_conn_state(btif_hf_cb.state));\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800141 return BT_STATUS_NOT_READY;\
142 }\
143 else\
144 {\
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700145 BTIF_TRACE_EVENT("BTHF: %s", __FUNCTION__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800146 }
147
148/* BTIF-HF control block to map bdaddr to BTA handle */
149typedef struct _btif_hf_cb
150{
151 UINT16 handle;
152 bt_bdaddr_t connected_bda;
153 bthf_connection_state_t state;
154 bthf_vr_state_t vr_state;
155 tBTA_AG_PEER_FEAT peer_feat;
156 int num_active;
157 int num_held;
158 struct timespec call_end_timestamp;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700159 struct timespec connected_timestamp;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800160 bthf_call_state_t call_setup_state;
161} btif_hf_cb_t;
162
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700163static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800164
165
166/************************************************************************************
167** Static functions
168************************************************************************************/
169
170/************************************************************************************
171** Externs
172************************************************************************************/
Matthew Xie66432dc2014-04-27 05:45:32 -0700173/* By default, even though codec negotiation is enabled, we will not use WBS as the default
174* codec unless this variable is set to TRUE.
175*/
176#ifndef BTIF_HF_WBS_PREFERRED
177#define BTIF_HF_WBS_PREFERRED FALSE
178#endif
179
180BOOLEAN btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800181
182/************************************************************************************
183** Functions
184************************************************************************************/
185
186/*******************************************************************************
187**
188** Function is_connected
189**
190** Description Internal function to check if HF is connected
191**
192** Returns TRUE if connected
193**
194*******************************************************************************/
195static BOOLEAN is_connected(bt_bdaddr_t *bd_addr)
196{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700197 int i;
198 for (i = 0; i < btif_max_hf_clients; ++i)
199 {
200 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
201 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
202 ((bd_addr == NULL) || (bdcmp(bd_addr->address,
203 btif_hf_cb[i].connected_bda.address) == 0)))
204 return TRUE;
205 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800206 return FALSE;
207}
208
209/*******************************************************************************
210**
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700211** Function btif_hf_idx_by_bdaddr
212**
213** Description Internal function to get idx by bdaddr
214**
215** Returns idx
216**
217*******************************************************************************/
218static int btif_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
219{
220 int i;
221 for (i = 0; i < btif_max_hf_clients; ++i)
222 {
223 if ((bdcmp(bd_addr->address,
224 btif_hf_cb[i].connected_bda.address) == 0))
225 return i;
226 }
227 return BTIF_HF_INVALID_IDX;
228}
229
230/*******************************************************************************
231**
The Android Open Source Project5738f832012-12-12 16:00:35 -0800232** Function callstate_to_callsetup
233**
234** Description Converts HAL call state to BTA call setup indicator value
235**
236** Returns BTA call indicator value
237**
238*******************************************************************************/
239static UINT8 callstate_to_callsetup(bthf_call_state_t call_state)
240{
241 UINT8 call_setup = 0;
242 if (call_state == BTHF_CALL_STATE_INCOMING)
243 call_setup = 1;
244 if (call_state == BTHF_CALL_STATE_DIALING)
245 call_setup = 2;
246 if (call_state == BTHF_CALL_STATE_ALERTING)
247 call_setup = 3;
248
249 return call_setup;
250}
251
252/*******************************************************************************
253**
254** Function send_at_result
255**
256** Description Send AT result code (OK/ERROR)
257**
258** Returns void
259**
260*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700261static void send_at_result(UINT8 ok_flag, UINT16 errcode, int idx)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800262{
263 tBTA_AG_RES_DATA ag_res;
264 memset (&ag_res, 0, sizeof (ag_res));
265
266 ag_res.ok_flag = ok_flag;
267 if (ok_flag == BTA_AG_OK_ERROR)
268 {
269 ag_res.errcode = errcode;
270 }
271
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700272 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800273}
274
275/*******************************************************************************
276**
277** Function send_indicator_update
278**
279** Description Send indicator update (CIEV)
280**
281** Returns void
282**
283*******************************************************************************/
284static void send_indicator_update (UINT16 indicator, UINT16 value)
285{
286 tBTA_AG_RES_DATA ag_res;
287
288 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
289 ag_res.ind.id = indicator;
290 ag_res.ind.value = value;
291
292 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
293}
294
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700295void clear_phone_state_multihf(int idx)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800296{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700297 btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE;
298 btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800299}
300
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700301/*******************************************************************************
302**
303** Function btif_hf_latest_connected_idx
304**
305** Description Returns idx for latest connected HF
306**
307** Returns int
308**
309*******************************************************************************/
310static int btif_hf_latest_connected_idx()
311{
312 struct timespec now, conn_time_delta;
313 int latest_conn_idx = BTIF_HF_INVALID_IDX, i;
314
315 clock_gettime(CLOCK_MONOTONIC, &now);
316 conn_time_delta.tv_sec = now.tv_sec;
317
318 for (i = 0; i < btif_max_hf_clients; i++)
319 {
320 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)
321 {
322 if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec)
323 < conn_time_delta.tv_sec)
324 {
325 conn_time_delta.tv_sec =
326 now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec;
327 latest_conn_idx = i;
328 }
329 }
330 }
331 return latest_conn_idx;
332}
333
334/*******************************************************************************
335**
336** Function btif_hf_check_if_slc_connected
337**
338** Description Returns BT_STATUS_SUCCESS if SLC is up for any HF
339**
340** Returns bt_status_t
341**
342*******************************************************************************/
343static bt_status_t btif_hf_check_if_slc_connected()
344{
345 if (bt_hf_callbacks == NULL)
346 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700347 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __FUNCTION__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700348 return BT_STATUS_NOT_READY;
349 }
350 else
351 {
352 int i;
353 for (i = 0; i < btif_max_hf_clients; i++)
354 {
355 if ((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED))
356 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700357 BTIF_TRACE_EVENT("BTHF: %s: slc connected for idx = %d",
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700358 __FUNCTION__, i);
359 return BT_STATUS_SUCCESS;
360 }
361 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700362 BTIF_TRACE_WARNING("BTHF: %s: No SLC connection up", __FUNCTION__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700363 return BT_STATUS_NOT_READY;
364 }
365}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800366
367/*****************************************************************************
368** Section name (Group of functions)
369*****************************************************************************/
370
371/*****************************************************************************
372**
373** btif hf api functions (no context switch)
374**
375*****************************************************************************/
376
377
378/*******************************************************************************
379**
380** Function btif_hf_upstreams_evt
381**
382** Description Executes HF UPSTREAMS events in btif context
383**
384** Returns void
385**
386*******************************************************************************/
387static void btif_hf_upstreams_evt(UINT16 event, char* p_param)
388{
389 tBTA_AG *p_data = (tBTA_AG *)p_param;
390 bdstr_t bdstr;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700391 bt_bdaddr_t addr;
392 int idx = p_data->hdr.handle - 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800393
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700394 BTIF_TRACE_DEBUG("%s: event=%s", __FUNCTION__, dump_hf_event(event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800395
396 switch (event)
397 {
398 case BTA_AG_ENABLE_EVT:
399 case BTA_AG_DISABLE_EVT:
400 break;
401
402 case BTA_AG_REGISTER_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700403 btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700404 BTIF_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT,"
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700405 "btif_hf_cb.handle = %d", __FUNCTION__, btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800406 break;
407
408 case BTA_AG_OPEN_EVT:
409 if (p_data->open.status == BTA_AG_SUCCESS)
410 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700411 bdcpy(btif_hf_cb[idx].connected_bda.address,
412 p_data->open.bd_addr);
413 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
414 btif_hf_cb[idx].peer_feat = 0;
415 clear_phone_state_multihf(idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800416 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700417 else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800418 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700419 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800420 }
421 else
422 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700423 BTIF_TRACE_WARNING("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s",
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700424 __FUNCTION__, p_data->open.status, btif_hf_cb[idx].state,
425 bd2str(&btif_hf_cb[idx].connected_bda, &bdstr));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800426 break;
427 }
428
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700429 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
430 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800431
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700432 if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
433 bdsetany(btif_hf_cb[idx].connected_bda.address);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800434
435 if (p_data->open.status != BTA_AG_SUCCESS)
436 btif_queue_advance();
437 break;
438
439 case BTA_AG_CLOSE_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700440 btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
441 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700442 BTIF_TRACE_DEBUG("%s: BTA_AG_CLOSE_EVT,"
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700443 "idx = %d, btif_hf_cb.handle = %d", __FUNCTION__, idx,
444 btif_hf_cb[idx].handle);
445 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
446 &btif_hf_cb[idx].connected_bda);
447 bdsetany(btif_hf_cb[idx].connected_bda.address);
448 btif_hf_cb[idx].peer_feat = 0;
449 clear_phone_state_multihf(idx);
450 hf_idx = btif_hf_latest_connected_idx();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800451 /* If AG_OPEN was received but SLC was not setup in a specified time (10 seconds),
452 ** then AG_CLOSE may be received. We need to advance the queue here
453 */
454 btif_queue_advance();
455 break;
456
457 case BTA_AG_CONN_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700458 clock_gettime(CLOCK_MONOTONIC,
459 &btif_hf_cb[idx].connected_timestamp);
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700460 BTIF_TRACE_DEBUG("%s: BTA_AG_CONN_EVT, idx = %d ",
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700461 __FUNCTION__, idx);
462 btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
463 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
464 hf_idx = btif_hf_latest_connected_idx();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800465
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700466 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
467 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800468 btif_queue_advance();
469 break;
470
471 case BTA_AG_AUDIO_OPEN_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700472 hf_idx = idx;
473 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
474 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800475 break;
476
477 case BTA_AG_AUDIO_CLOSE_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700478 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
479 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800480 break;
481
482 /* BTA auto-responds, silently discard */
483 case BTA_AG_SPK_EVT:
484 case BTA_AG_MIC_EVT:
485 HAL_CBACK(bt_hf_callbacks, volume_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700486 (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK :
487 BTHF_VOLUME_TYPE_MIC, p_data->val.num,
488 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800489 break;
490
491 case BTA_AG_AT_A_EVT:
Hemant Gupta4974d812014-05-05 17:45:08 +0530492 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
493 hf_idx = idx;
494 else
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700495 BTIF_TRACE_DEBUG("Donot set hf_idx for ATA since already in a call");
Hemant Gupta4974d812014-05-05 17:45:08 +0530496
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700497 HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
498 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800499 break;
500
501 /* Java needs to send OK/ERROR for these commands */
502 case BTA_AG_AT_BLDN_EVT:
503 case BTA_AG_AT_D_EVT:
Hemant Gupta4974d812014-05-05 17:45:08 +0530504 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
505 hf_idx = idx;
506 else
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700507 BTIF_TRACE_DEBUG("Donot set hf_idx for BLDN/D since already in a call");
Hemant Gupta4974d812014-05-05 17:45:08 +0530508
The Android Open Source Project5738f832012-12-12 16:00:35 -0800509 HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700510 (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
511 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800512 break;
513
514 case BTA_AG_AT_CHUP_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700515 HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
516 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800517 break;
518
519 case BTA_AG_AT_CIND_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700520 HAL_CBACK(bt_hf_callbacks, cind_cmd_cb,
521 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800522 break;
523
524 case BTA_AG_AT_VTS_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700525 HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
526 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800527 break;
528
529 case BTA_AG_AT_BVRA_EVT:
530 HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700531 (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED :
532 BTHF_VR_STATE_STOPPED, &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800533 break;
534
535 case BTA_AG_AT_NREC_EVT:
536 HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700537 (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
538 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800539 break;
540
541 /* TODO: Add a callback for CBC */
542 case BTA_AG_AT_CBC_EVT:
543 break;
544
545 case BTA_AG_AT_CKPD_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700546 HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
547 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800548 break;
549
Matthew Xie66432dc2014-04-27 05:45:32 -0700550#if (BTM_WBS_INCLUDED == TRUE )
551 case BTA_AG_WBS_EVT:
552 BTIF_TRACE_DEBUG("BTA_AG_WBS_EVT Set codec status %d codec %d 1=CVSD 2=MSBC", \
553 p_data->val.hdr.status, p_data->val.num);
554 if(p_data->val.num == BTA_AG_CODEC_CVSD)
555 { HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NO, &btif_hf_cb[idx].connected_bda);}
556 else if(p_data->val.num == BTA_AG_CODEC_MSBC)
557 {HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_YES, &btif_hf_cb[idx].connected_bda);}
558 else
559 {HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NONE, &btif_hf_cb[idx].connected_bda);}
560 break;
561#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800562 /* Java needs to send OK/ERROR for these commands */
563 case BTA_AG_AT_CHLD_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700564 HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str),
565 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800566 break;
567
568 case BTA_AG_AT_CLCC_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700569 HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb,
570 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800571 break;
572
573 case BTA_AG_AT_COPS_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700574 HAL_CBACK(bt_hf_callbacks, cops_cmd_cb,
575 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576 break;
577
578 case BTA_AG_AT_UNAT_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700579 HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
580 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800581 break;
582
583 case BTA_AG_AT_CNUM_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700584 HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb,
585 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800586 break;
587
588 /* TODO: Some of these commands may need to be sent to app. For now respond with error */
589 case BTA_AG_AT_BINP_EVT:
590 case BTA_AG_AT_BTRH_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700591 send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800592 break;
Matthew Xie66432dc2014-04-27 05:45:32 -0700593 case BTA_AG_AT_BAC_EVT:
594 BTIF_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num);
595#if (BTM_WBS_INCLUDED == TRUE )
596 /* If the peer supports mSBC and the BTIF prefferred codec is also mSBC, then
597 we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC at the time
598 of SCO connection establishment */
599 if ((btif_conf_hf_force_wbs == TRUE) && (p_data->val.num & BTA_AG_CODEC_MSBC))
600 {
601 BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to MSBC", __FUNCTION__);
602 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_MSBC);
603 }
604 else
605 {
606 BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to CVSD", __FUNCTION__);
607 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_CVSD);
608 }
609#endif
610 break;
611 case BTA_AG_AT_BCS_EVT:
612 BTIF_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num);
613 /* no BTHF_WBS_NONE case, becuase HF1.6 supported device can send BCS */
614 HAL_CBACK(bt_hf_callbacks, wbs_cb,(p_data->val.num == BTA_AG_CODEC_MSBC) ? \
615 BTHF_WBS_YES : BTHF_WBS_NO, &btif_hf_cb[idx].connected_bda);
616 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800617
618 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700619 BTIF_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800620 break;
621 }
622}
623
624/*******************************************************************************
625**
626** Function bte_hf_evt
627**
628** Description Switches context from BTE to BTIF for all HF events
629**
630** Returns void
631**
632*******************************************************************************/
633
634static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *p_data)
635{
636 bt_status_t status;
637 int param_len = 0;
638
639 /* TODO: BTA sends the union members and not tBTA_AG. If using param_len=sizeof(tBTA_AG), we get a crash on memcpy */
640 if (BTA_AG_REGISTER_EVT == event)
641 param_len = sizeof(tBTA_AG_REGISTER);
642 else if (BTA_AG_OPEN_EVT == event)
643 param_len = sizeof(tBTA_AG_OPEN);
644 else if (BTA_AG_CONN_EVT == event)
645 param_len = sizeof(tBTA_AG_CONN);
646 else if ( (BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) || (BTA_AG_AUDIO_CLOSE_EVT == event))
647 param_len = sizeof(tBTA_AG_HDR);
648 else if (p_data)
649 param_len = sizeof(tBTA_AG_VAL);
650
651 /* switch context to btif task context (copy full union size for convenience) */
652 status = btif_transfer_context(btif_hf_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL);
653
654 /* catch any failed context transfers */
655 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
656}
657
658
659/*******************************************************************************
660**
661** Function btif_in_hf_generic_evt
662**
663** Description Processes generic events to be sent to JNI that are not triggered from the BTA.
664** Always runs in BTIF context
665**
666** Returns void
667**
668*******************************************************************************/
669static void btif_in_hf_generic_evt(UINT16 event, char *p_param)
670{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700671 int idx = btif_hf_idx_by_bdaddr((bt_bdaddr_t *)p_param);
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800672
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700673 BTIF_TRACE_EVENT("%s: event=%d", __FUNCTION__, event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800674 switch (event) {
675 case BTIF_HFP_CB_AUDIO_CONNECTING:
676 {
677 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700678 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800679 } break;
680 default:
681 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700682 BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __FUNCTION__, event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800683 }
684 break;
685 }
686}
687
688
689/*******************************************************************************
690**
691** Function btif_hf_init
692**
693** Description initializes the hf interface
694**
695** Returns bt_status_t
696**
697*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700698static bt_status_t init( bthf_callbacks_t* callbacks, int max_hf_clients)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800699{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700700 BTIF_TRACE_EVENT("%s", __FUNCTION__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700701 int i;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800702
703 bt_hf_callbacks = callbacks;
704
705 /* Invoke the enable service API to the core to set the appropriate service_id
706 * Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled (phone)
707 * othwerwise only HSP is enabled (tablet)
708 */
709#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
710 btif_enable_service(BTA_HFP_SERVICE_ID);
711#else
712 btif_enable_service(BTA_HSP_SERVICE_ID);
713#endif
714
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700715 memset(&btif_hf_cb, 0, sizeof(btif_hf_cb));
716 btif_max_hf_clients = max_hf_clients;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700717 BTIF_TRACE_DEBUG("btif_max_hf_clients = %d", btif_max_hf_clients);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700718 for (i = 0; i < btif_max_hf_clients; i++)
719 {
720 clear_phone_state_multihf(i);
721 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800722
723 return BT_STATUS_SUCCESS;
724}
725
726/*******************************************************************************
727**
728** Function connect
729**
730** Description connect to headset
731**
732** Returns bt_status_t
733**
734*******************************************************************************/
Hemant Guptacc355592013-10-24 15:37:17 +0530735static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800736{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700737 CHECK_BTHF_INIT();
738 int i;
739 for (i = 0; i < btif_max_hf_clients;)
740 {
741 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
742 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)))
743 i++;
744 else
745 break;
746 }
747
748 if (i == btif_max_hf_clients)
749 return BT_STATUS_BUSY;
750
The Android Open Source Project5738f832012-12-12 16:00:35 -0800751 if (!is_connected(bd_addr))
752 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700753 btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
754 bdcpy(btif_hf_cb[i].connected_bda.address, bd_addr->address);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800755
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700756 BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda.address,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800757 BTIF_HF_SECURITY, BTIF_HF_SERVICES);
758 return BT_STATUS_SUCCESS;
759 }
760
761 return BT_STATUS_BUSY;
762}
763
764static bt_status_t connect( bt_bdaddr_t *bd_addr )
765{
766 CHECK_BTHF_INIT();
767 return btif_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_int);
768}
769
770/*******************************************************************************
771**
772** Function disconnect
773**
774** Description disconnect from headset
775**
776** Returns bt_status_t
777**
778*******************************************************************************/
779static bt_status_t disconnect( bt_bdaddr_t *bd_addr )
780{
781 CHECK_BTHF_INIT();
782
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700783 int idx = btif_hf_idx_by_bdaddr(bd_addr);
784
785 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800786 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700787 BTA_AgClose(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800788 return BT_STATUS_SUCCESS;
789 }
790
791 return BT_STATUS_FAIL;
792}
793
794/*******************************************************************************
795**
796** Function connect_audio
797**
798** Description create an audio connection
799**
800** Returns bt_status_t
801**
802*******************************************************************************/
803static bt_status_t connect_audio( bt_bdaddr_t *bd_addr )
804{
805 CHECK_BTHF_INIT();
806
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700807 int idx = btif_hf_idx_by_bdaddr(bd_addr);
808
809 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800810 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700811 BTA_AgAudioOpen(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800812
813 /* Inform the application that the audio connection has been initiated successfully */
814 btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING,
815 (char *)bd_addr, sizeof(bt_bdaddr_t), NULL);
816 return BT_STATUS_SUCCESS;
817 }
818
819 return BT_STATUS_FAIL;
820}
821
822/*******************************************************************************
823**
824** Function disconnect_audio
825**
826** Description close the audio connection
827**
828** Returns bt_status_t
829**
830*******************************************************************************/
831static bt_status_t disconnect_audio( bt_bdaddr_t *bd_addr )
832{
833 CHECK_BTHF_INIT();
834
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700835 int idx = btif_hf_idx_by_bdaddr(bd_addr);
836
837 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800838 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700839 BTA_AgAudioClose(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800840 return BT_STATUS_SUCCESS;
841 }
842
843 return BT_STATUS_FAIL;
844}
845
846/*******************************************************************************
847**
848** Function start_voice_recognition
849**
850** Description start voice recognition
851**
852** Returns bt_status_t
853**
854*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700855static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800856{
857 CHECK_BTHF_INIT();
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700858
859 int idx = btif_hf_idx_by_bdaddr(bd_addr);
860
861 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800862 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700863 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800864 {
865 tBTA_AG_RES_DATA ag_res;
866 memset(&ag_res, 0, sizeof(ag_res));
867 ag_res.state = 1;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700868 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800869
870 return BT_STATUS_SUCCESS;
871 }
872 else
873 {
874 return BT_STATUS_UNSUPPORTED;
875 }
876 }
877
878 return BT_STATUS_NOT_READY;
879}
880
881/*******************************************************************************
882**
883** Function stop_voice_recognition
884**
885** Description stop voice recognition
886**
887** Returns bt_status_t
888**
889*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700890static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800891{
892 CHECK_BTHF_INIT();
893
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700894 int idx = btif_hf_idx_by_bdaddr(bd_addr);
895
896 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800897 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700898 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800899 {
900 tBTA_AG_RES_DATA ag_res;
901 memset(&ag_res, 0, sizeof(ag_res));
902 ag_res.state = 0;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700903 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800904
905 return BT_STATUS_SUCCESS;
906 }
907 else
908 {
909 return BT_STATUS_UNSUPPORTED;
910 }
911 }
912
913 return BT_STATUS_NOT_READY;
914}
915
916/*******************************************************************************
917**
918** Function volume_control
919**
920** Description volume control
921**
922** Returns bt_status_t
923**
924*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700925static bt_status_t volume_control(bthf_volume_type_t type, int volume,
926 bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800927{
928 CHECK_BTHF_INIT();
929
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700930 int idx = btif_hf_idx_by_bdaddr(bd_addr);
931
The Android Open Source Project5738f832012-12-12 16:00:35 -0800932 tBTA_AG_RES_DATA ag_res;
933 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700934 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800935 {
936 ag_res.num = volume;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700937 BTA_AgResult(btif_hf_cb[idx].handle,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800938 (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
939 &ag_res);
940 return BT_STATUS_SUCCESS;
941 }
942
943 return BT_STATUS_FAIL;
944}
945
946/*******************************************************************************
947**
948** Function device_status_notification
949**
950** Description Combined device status change notification
951**
952** Returns bt_status_t
953**
954*******************************************************************************/
955static bt_status_t device_status_notification(bthf_network_state_t ntk_state,
956 bthf_service_type_t svc_type, int signal, int batt_chg)
957{
958 CHECK_BTHF_INIT();
959
960 if (is_connected(NULL))
961 {
962 /* send all indicators to BTA.
963 ** BTA will make sure no duplicates are sent out
964 */
965 send_indicator_update(BTA_AG_IND_SERVICE,
966 (ntk_state == BTHF_NETWORK_STATE_AVAILABLE) ? 1 : 0);
967 send_indicator_update(BTA_AG_IND_ROAM,
968 (svc_type == BTHF_SERVICE_TYPE_HOME) ? 0 : 1);
969 send_indicator_update(BTA_AG_IND_SIGNAL, signal);
970 send_indicator_update(BTA_AG_IND_BATTCHG, batt_chg);
971 return BT_STATUS_SUCCESS;
972 }
973
974 return BT_STATUS_SUCCESS;
975}
976
977/*******************************************************************************
978**
979** Function cops_response
980**
981** Description Response for COPS command
982**
983** Returns bt_status_t
984**
985*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700986static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800987{
988 CHECK_BTHF_INIT();
989
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700990 int idx = btif_hf_idx_by_bdaddr(bd_addr);
991
992 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800993 {
994 tBTA_AG_RES_DATA ag_res;
995
996 /* Format the response */
997 sprintf (ag_res.str, "0,0,\"%s\"", cops);
998 ag_res.ok_flag = BTA_AG_OK_DONE;
999
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001000 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001001 return BT_STATUS_SUCCESS;
1002 }
1003 return BT_STATUS_FAIL;
1004}
1005
1006/*******************************************************************************
1007**
1008** Function cind_response
1009**
1010** Description Response for CIND command
1011**
1012** Returns bt_status_t
1013**
1014*******************************************************************************/
1015static bt_status_t cind_response(int svc, int num_active, int num_held,
1016 bthf_call_state_t call_setup_state,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001017 int signal, int roam, int batt_chg,
1018 bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001019{
1020 CHECK_BTHF_INIT();
1021
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001022 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1023
1024 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001025 {
1026 tBTA_AG_RES_DATA ag_res;
1027
1028 memset (&ag_res, 0, sizeof (ag_res));
1029 /* per the errata 2043, call=1 implies atleast one call is in progress (active/held)
1030 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1031 **/
1032 sprintf (ag_res.str, "%d,%d,%d,%d,%d,%d,%d",
1033 (num_active + num_held) ? 1 : 0, /* Call state */
1034 callstate_to_callsetup(call_setup_state), /* Callsetup state */
1035 svc, /* network service */
1036 signal, /* Signal strength */
1037 roam, /* Roaming indicator */
1038 batt_chg, /* Battery level */
1039 ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
1040
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001041 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001042
1043 return BT_STATUS_SUCCESS;
1044 }
1045
1046 return BT_STATUS_FAIL;
1047}
1048
1049/*******************************************************************************
1050**
1051** Function formatted_at_response
1052**
1053** Description Pre-formatted AT response, typically in response to unknown AT cmd
1054**
1055** Returns bt_status_t
1056**
1057*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001058static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001059{
1060 CHECK_BTHF_INIT();
1061 tBTA_AG_RES_DATA ag_res;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001062 int idx = btif_hf_idx_by_bdaddr(bd_addr);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001063
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001064 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001065 {
1066 /* Format the response and send */
1067 memset (&ag_res, 0, sizeof (ag_res));
1068 strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001069 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001070
1071 return BT_STATUS_SUCCESS;
1072 }
1073
1074 return BT_STATUS_FAIL;
1075}
1076
1077/*******************************************************************************
1078**
1079** Function at_response
1080**
1081** Description ok/error response
1082**
1083** Returns bt_status_t
1084**
1085*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001086static bt_status_t at_response(bthf_at_response_t response_code,
1087 int error_code, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001088{
1089 CHECK_BTHF_INIT();
1090
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001091 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1092
1093 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001094 {
1095 send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001096 : BTA_AG_OK_ERROR, error_code, idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001097 return BT_STATUS_SUCCESS;
1098 }
1099
1100
1101 return BT_STATUS_FAIL;
1102}
1103
1104/*******************************************************************************
1105**
1106** Function clcc_response
1107**
1108** Description response for CLCC command
1109** Can be iteratively called for each call index. Call index
1110** of 0 will be treated as NULL termination (Completes response)
1111**
1112** Returns bt_status_t
1113**
1114*******************************************************************************/
1115static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001116 bthf_call_state_t state, bthf_call_mode_t mode,
1117 bthf_call_mpty_type_t mpty, const char *number,
1118 bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001119{
1120 CHECK_BTHF_INIT();
1121
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001122 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1123
1124 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001125 {
1126 tBTA_AG_RES_DATA ag_res;
1127 int xx;
1128
1129 memset (&ag_res, 0, sizeof (ag_res));
1130
1131 /* Format the response */
1132 if (index == 0)
1133 {
1134 ag_res.ok_flag = BTA_AG_OK_DONE;
1135 }
1136 else
1137 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001138 BTIF_TRACE_EVENT("clcc_response: [%d] dir %d state %d mode %d number = %s type = %d",
The Android Open Source Project5738f832012-12-12 16:00:35 -08001139 index, dir, state, mode, number, type);
1140 xx = sprintf (ag_res.str, "%d,%d,%d,%d,%d",
1141 index, dir, state, mode, mpty);
1142
1143 if (number)
1144 {
1145 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+'))
1146 sprintf (&ag_res.str[xx], ",\"+%s\",%d", number, type);
1147 else
1148 sprintf (&ag_res.str[xx], ",\"%s\",%d", number, type);
1149 }
1150 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001151 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001152
1153 return BT_STATUS_SUCCESS;
1154 }
1155
1156 return BT_STATUS_FAIL;
1157}
1158
1159/*******************************************************************************
1160**
1161** Function phone_state_change
1162**
1163** Description notify of a call state change
1164** number & type: valid only for incoming & waiting call
1165**
1166** Returns bt_status_t
1167**
1168*******************************************************************************/
1169
1170static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_state_t call_setup_state,
1171 const char *number, bthf_call_addrtype_t type)
1172{
1173 tBTA_AG_RES res = 0xff;
1174 tBTA_AG_RES_DATA ag_res;
1175 bt_status_t status = BT_STATUS_SUCCESS;
1176 BOOLEAN activeCallUpdated = FALSE;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001177 int idx, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001178
Hemant Gupta4974d812014-05-05 17:45:08 +05301179 /* hf_idx is index of connected HS that sent ATA/BLDN,
1180 otherwise index of latest connected HS */
1181 if (hf_idx != BTIF_HF_INVALID_IDX)
1182 idx = hf_idx;
1183 else
1184 idx = btif_hf_latest_connected_idx();
1185
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001186 BTIF_TRACE_DEBUG("phone_state_change: idx = %d", idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001187
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001188 /* Check if SLC is connected */
1189 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
1190 return BT_STATUS_NOT_READY;
1191
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001192 BTIF_TRACE_DEBUG("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001193 " call_setup=%s [prev: %s]", num_active, btif_hf_cb[idx].num_active,
1194 num_held, btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
1195 dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001196
1197 /* if all indicators are 0, send end call and return */
1198 if (num_active == 0 && num_held == 0 && call_setup_state == BTHF_CALL_STATE_IDLE)
1199 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001200 BTIF_TRACE_DEBUG("%s: Phone on hook", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001201
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001202 /* record call termination timestamp if there was an active/held call or
1203 callsetup state > BTHF_CALL_STATE_IDLE */
1204 if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE ) ||
1205 (btif_hf_cb[idx].num_active) ||(btif_hf_cb[idx].num_held))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001206 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001207 BTIF_TRACE_DEBUG("%s: Record call termination timestamp", __FUNCTION__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001208 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001209 }
1210 BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001211 hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001212
1213 /* if held call was present, reset that as well */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001214 if (btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001215 send_indicator_update(BTA_AG_IND_CALLHELD, 0);
1216
1217 goto update_call_states;
1218 }
1219
1220 /* active state can change when:
1221 ** 1. an outgoing/incoming call was answered
1222 ** 2. an held was resumed
1223 ** 3. without callsetup notifications, call became active
1224 ** (3) can happen if call is active and a headset connects to us
1225 **
1226 ** In the case of (3), we will have to notify the stack of an active
1227 ** call, instead of sending an indicator update. This will also
1228 ** force the SCO to be setup. Handle this special case here prior to
1229 ** call setup handling
1230 */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001231 if ( (num_active == 1) && (btif_hf_cb[idx].num_active == 0) && (btif_hf_cb[idx].num_held == 0)
1232 && (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001233 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001234 BTIF_TRACE_DEBUG("%s: Active call notification received without call setup update",
The Android Open Source Project5738f832012-12-12 16:00:35 -08001235 __FUNCTION__);
1236
1237 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001238 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001239 res = BTA_AG_OUT_CALL_CONN_RES;
1240 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
1241 activeCallUpdated = TRUE;
1242 }
1243
1244 /* Ringing call changed? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001245 if (call_setup_state != btif_hf_cb[idx].call_setup_state)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001246 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001247 BTIF_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s",
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001248 __FUNCTION__, dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001249 dump_hf_call_state(call_setup_state));
1250 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1251
1252 switch (call_setup_state)
1253 {
1254 case BTHF_CALL_STATE_IDLE:
1255 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001256 switch (btif_hf_cb[idx].call_setup_state)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001257 {
1258 case BTHF_CALL_STATE_INCOMING:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001259 if (num_active > btif_hf_cb[idx].num_active)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001260 {
1261 res = BTA_AG_IN_CALL_CONN_RES;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001262 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001263 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001264 else if (num_held > btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001265 res = BTA_AG_IN_CALL_HELD_RES;
1266 else
1267 res = BTA_AG_CALL_CANCEL_RES;
1268 break;
1269 case BTHF_CALL_STATE_DIALING:
1270 case BTHF_CALL_STATE_ALERTING:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001271 if (num_active > btif_hf_cb[idx].num_active)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001272 {
1273 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
1274 res = BTA_AG_OUT_CALL_CONN_RES;
1275 }
1276 else
1277 res = BTA_AG_CALL_CANCEL_RES;
1278 break;
1279 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001280 BTIF_TRACE_ERROR("%s: Incorrect Call setup state transition", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001281 status = BT_STATUS_PARM_INVALID;
1282 break;
1283 }
1284 } break;
1285
1286 case BTHF_CALL_STATE_INCOMING:
1287 if (num_active || num_held)
1288 res = BTA_AG_CALL_WAIT_RES;
1289 else
1290 res = BTA_AG_IN_CALL_RES;
1291 if (number)
1292 {
1293 int xx = 0;
1294 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+'))
1295 xx = sprintf (ag_res.str, "\"+%s\"", number);
1296 else
1297 xx = sprintf (ag_res.str, "\"%s\"", number);
1298 ag_res.num = type;
1299
1300 if (res == BTA_AG_CALL_WAIT_RES)
1301 sprintf(&ag_res.str[xx], ",%d", type);
1302 }
1303 break;
1304 case BTHF_CALL_STATE_DIALING:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001305 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001306 res = BTA_AG_OUT_CALL_ORIG_RES;
1307 break;
1308 case BTHF_CALL_STATE_ALERTING:
1309 /* if we went from idle->alert, force SCO setup here. dialing usually triggers it */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001310 if (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE)
1311 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001312 res = BTA_AG_OUT_CALL_ALERT_RES;
1313 break;
1314 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001315 BTIF_TRACE_ERROR("%s: Incorrect new ringing call state", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001316 status = BT_STATUS_PARM_INVALID;
1317 break;
1318 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001319 BTIF_TRACE_DEBUG("%s: Call setup state changed. res=%d, audio_handle=%d", __FUNCTION__, res, ag_res.audio_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001320
1321 if (res)
1322 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
1323
1324 /* if call setup is idle, we have already updated call indicator, jump out */
1325 if (call_setup_state == BTHF_CALL_STATE_IDLE)
1326 {
1327 /* check & update callheld */
1328 if ((num_held > 0) && (num_active > 0))
1329 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
1330 goto update_call_states;
1331 }
1332 }
1333
1334 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1335
1336 /* per the errata 2043, call=1 implies atleast one call is in progress (active/held)
1337 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1338 ** Handle call indicator change
1339 **/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001340 if (!activeCallUpdated && ((num_active + num_held) !=
1341 (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held)) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001342 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001343 BTIF_TRACE_DEBUG("%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 -08001344 send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
1345 }
1346
1347 /* Held Changed? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001348 if (num_held != btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001349 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001350 BTIF_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d",
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001351 __FUNCTION__, btif_hf_cb[idx].num_held, num_held);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001352 send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
1353 }
1354
1355 /* Calls Swapped? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001356 if ( (call_setup_state == btif_hf_cb[idx].call_setup_state) &&
The Android Open Source Project5738f832012-12-12 16:00:35 -08001357 (num_active && num_held) &&
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001358 (num_active == btif_hf_cb[idx].num_active) &&
1359 (num_held == btif_hf_cb[idx].num_held) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001360 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001361 BTIF_TRACE_DEBUG("%s: Calls swapped", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001362 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
1363 }
1364
1365update_call_states:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001366 for (i = 0; i < btif_max_hf_clients; i++)
1367 {
1368 btif_hf_cb[i].num_active = num_active;
1369 btif_hf_cb[i].num_held = num_held;
1370 btif_hf_cb[i].call_setup_state = call_setup_state;
1371 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001372 return status;
1373}
1374
1375
1376/*******************************************************************************
1377**
1378** Function btif_hf_call_terminated_recently
1379**
1380** Description Checks if a call has been terminated
1381**
1382** Returns bt_status_t
1383**
1384*******************************************************************************/
1385BOOLEAN btif_hf_call_terminated_recently()
1386{
1387 struct timespec now;
1388
1389 clock_gettime(CLOCK_MONOTONIC, &now);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001390 if (now.tv_sec < btif_hf_cb[0].call_end_timestamp.tv_sec +
1391 BTIF_HF_CALL_END_TIMEOUT)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001392 {
1393 return TRUE;
1394 }
1395 else
1396 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001397 btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001398 return FALSE;
1399 }
1400}
1401
1402/*******************************************************************************
1403**
1404** Function cleanup
1405**
1406** Description Closes the HF interface
1407**
1408** Returns bt_status_t
1409**
1410*******************************************************************************/
1411static void cleanup( void )
1412{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001413 BTIF_TRACE_EVENT("%s", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001414
1415 if (bt_hf_callbacks)
1416 {
1417 btif_disable_service(BTA_HFP_SERVICE_ID);
1418 bt_hf_callbacks = NULL;
1419 }
1420}
1421
Matthew Xie66432dc2014-04-27 05:45:32 -07001422/*******************************************************************************
1423**
1424** Function configure_wbs
1425**
1426** Description set to over-ride the current WBS configuration.
1427** It will not send codec setting cmd to the controller now.
1428** It just change the configure.
1429**
1430** Returns bt_status_t
1431**
1432*******************************************************************************/
1433static bt_status_t configure_wbs( bt_bdaddr_t *bd_addr , bthf_wbs_config_t config )
1434{
1435 CHECK_BTHF_INIT();
1436
1437 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1438
1439 BTIF_TRACE_EVENT("%s config is %d", __FUNCTION__,config);
1440 if (config == BTHF_WBS_YES)
1441 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_MSBC);
1442 else if(config == BTHF_WBS_NO)
1443 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_CVSD);
1444 else
1445 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_NONE);
1446
1447 return BT_STATUS_SUCCESS;
1448}
1449
The Android Open Source Project5738f832012-12-12 16:00:35 -08001450static const bthf_interface_t bthfInterface = {
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001451 sizeof(bthfInterface),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001452 init,
1453 connect,
1454 disconnect,
1455 connect_audio,
1456 disconnect_audio,
1457 start_voice_recognition,
1458 stop_voice_recognition,
1459 volume_control,
1460 device_status_notification,
1461 cops_response,
1462 cind_response,
1463 formatted_at_response,
1464 at_response,
1465 clcc_response,
1466 phone_state_change,
1467 cleanup,
Matthew Xie66432dc2014-04-27 05:45:32 -07001468 configure_wbs,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001469};
1470
1471/*******************************************************************************
1472**
1473** Function btif_hf_execute_service
1474**
1475** Description Initializes/Shuts down the service
1476**
1477** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1478**
1479*******************************************************************************/
1480bt_status_t btif_hf_execute_service(BOOLEAN b_enable)
1481{
1482 char * p_service_names[] = BTIF_HF_SERVICE_NAMES;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001483 int i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001484 if (b_enable)
1485 {
1486 /* Enable and register with BTA-AG */
1487 BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001488 for (i = 0; i < btif_max_hf_clients; i++)
1489 {
1490 BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY,
1491 BTIF_HF_FEATURES, p_service_names, bthf_hf_id[i]);
1492 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001493 }
1494 else {
1495 /* De-register AG */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001496 for (i = 0; i < btif_max_hf_clients; i++)
1497 {
1498 BTA_AgDeregister(btif_hf_cb[i].handle);
1499 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001500 /* Disable AG */
1501 BTA_AgDisable();
1502 }
1503 return BT_STATUS_SUCCESS;
1504}
1505
1506/*******************************************************************************
1507**
1508** Function btif_hf_get_interface
1509**
1510** Description Get the hf callback interface
1511**
1512** Returns bthf_interface_t
1513**
1514*******************************************************************************/
1515const bthf_interface_t *btif_hf_get_interface()
1516{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001517 BTIF_TRACE_EVENT("%s", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001518 return &bthfInterface;
1519}