blob: 8c925b87d5d3aefd030b9e6f0dd2b467df616b8d [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
Marie Janssen49a86702015-07-08 11:48:57 -070028#define LOG_TAG "bt_btif_hf"
29
The Android Open Source Project5738f832012-12-12 16:00:35 -080030#include <stdlib.h>
Ian Coolidgec7503db2015-01-24 02:01:26 -080031#include <string.h>
Arman Ugurayd30195c2015-05-29 15:27:58 -070032#include <time.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080033
Marie Janssen49a86702015-07-08 11:48:57 -070034#include <hardware/bluetooth.h>
35#include <hardware/bt_hf.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080036
The Android Open Source Project5738f832012-12-12 16:00:35 -080037#include "bta_ag_api.h"
Marie Janssen49a86702015-07-08 11:48:57 -070038#include "btcore/include/bdaddr.h"
39#include "btif_common.h"
40#include "btif_profile_queue.h"
41#include "btif_util.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080042
43/************************************************************************************
44** Constants & Macros
45************************************************************************************/
46#ifndef BTIF_HSAG_SERVICE_NAME
47#define BTIF_HSAG_SERVICE_NAME ("Headset Gateway")
48#endif
49
50#ifndef BTIF_HFAG_SERVICE_NAME
51#define BTIF_HFAG_SERVICE_NAME ("Handsfree Gateway")
52#endif
53
54#ifndef BTIF_HF_SERVICES
55#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK | BTA_HFP_SERVICE_MASK )
56#endif
57
58#ifndef BTIF_HF_SERVICE_NAMES
59#define BTIF_HF_SERVICE_NAMES {BTIF_HSAG_SERVICE_NAME , BTIF_HFAG_SERVICE_NAME}
60#endif
61
62#ifndef BTIF_HF_SECURITY
63#define BTIF_HF_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
64#endif
65
Marie Janssenb7f64bc2016-06-22 12:52:19 -070066#if (BTM_WBS_INCLUDED == TRUE)
Matthew Xie66432dc2014-04-27 05:45:32 -070067#ifndef BTIF_HF_FEATURES
68#define BTIF_HF_FEATURES ( BTA_AG_FEAT_3WAY | \
69 BTA_AG_FEAT_ECNR | \
70 BTA_AG_FEAT_REJECT | \
71 BTA_AG_FEAT_ECS | \
72 BTA_AG_FEAT_EXTERR | \
73 BTA_AG_FEAT_BTRH | \
74 BTA_AG_FEAT_VREC | \
75 BTA_AG_FEAT_CODEC |\
Mudumba Ananth4de9bbc2016-02-29 02:21:43 -080076 BTA_AG_FEAT_HF_IND | \
77 BTA_AG_FEAT_ESCO | \
Matthew Xie66432dc2014-04-27 05:45:32 -070078 BTA_AG_FEAT_UNAT)
79#endif
80#else
The Android Open Source Project5738f832012-12-12 16:00:35 -080081#ifndef BTIF_HF_FEATURES
82#define BTIF_HF_FEATURES ( BTA_AG_FEAT_3WAY | \
83 BTA_AG_FEAT_ECNR | \
84 BTA_AG_FEAT_REJECT | \
85 BTA_AG_FEAT_ECS | \
86 BTA_AG_FEAT_EXTERR | \
87 BTA_AG_FEAT_BTRH | \
88 BTA_AG_FEAT_VREC | \
Mudumba Ananth4de9bbc2016-02-29 02:21:43 -080089 BTA_AG_FEAT_HF_IND | \
90 BTA_AG_FEAT_ESCO | \
The Android Open Source Project5738f832012-12-12 16:00:35 -080091 BTA_AG_FEAT_UNAT)
92#endif
Matthew Xie66432dc2014-04-27 05:45:32 -070093#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -080094
The Android Open Source Project5738f832012-12-12 16:00:35 -080095#define BTIF_HF_CALL_END_TIMEOUT 6
96
Chih-Hung Hsieh63b05192016-05-20 10:29:31 -070097#define BTIF_HF_INVALID_IDX (-1)
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070098
99/* Number of BTIF-HF control blocks */
100#define BTIF_HF_NUM_CB 2
101
102/* Max HF clients supported from App */
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700103uint16_t btif_max_hf_clients = 1;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700104
105/* HF app ids for service registration */
106typedef enum {
107 BTIF_HF_ID_1 = 0,
108 BTIF_HF_ID_2,
109#if (BTIF_HF_NUM_CB == 3)
110 BTIF_HF_ID_3
111#endif
112} bthf_hf_id_t;
113
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700114uint16_t bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700115 #if (BTIF_HF_NUM_CB == 3)
116 BTIF_HF_ID_3
117 #endif
118 };
119
The Android Open Source Project5738f832012-12-12 16:00:35 -0800120/************************************************************************************
121** Local type definitions
122************************************************************************************/
123
124/************************************************************************************
125** Static variables
126************************************************************************************/
127static bthf_callbacks_t *bt_hf_callbacks = NULL;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700128static int hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800129
130#define CHECK_BTHF_INIT() if (bt_hf_callbacks == NULL)\
131 {\
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700132 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800133 return BT_STATUS_NOT_READY;\
134 }\
135 else\
136 {\
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700137 BTIF_TRACE_EVENT("BTHF: %s", __func__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800138 }
139
140#define CHECK_BTHF_SLC_CONNECTED() if (bt_hf_callbacks == NULL)\
141 {\
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700142 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800143 return BT_STATUS_NOT_READY;\
144 }\
145 else if (btif_hf_cb.state != BTHF_CONNECTION_STATE_SLC_CONNECTED)\
146 {\
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700147 BTIF_TRACE_WARNING("BTHF: %s: SLC connection not up. state=%s", __func__, dump_hf_conn_state(btif_hf_cb.state));\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800148 return BT_STATUS_NOT_READY;\
149 }\
150 else\
151 {\
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700152 BTIF_TRACE_EVENT("BTHF: %s", __func__);\
The Android Open Source Project5738f832012-12-12 16:00:35 -0800153 }
154
155/* BTIF-HF control block to map bdaddr to BTA handle */
156typedef struct _btif_hf_cb
157{
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700158 uint16_t handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800159 bt_bdaddr_t connected_bda;
160 bthf_connection_state_t state;
161 bthf_vr_state_t vr_state;
162 tBTA_AG_PEER_FEAT peer_feat;
163 int num_active;
164 int num_held;
165 struct timespec call_end_timestamp;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700166 struct timespec connected_timestamp;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800167 bthf_call_state_t call_setup_state;
168} btif_hf_cb_t;
169
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700170static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800171
The Android Open Source Project5738f832012-12-12 16:00:35 -0800172/************************************************************************************
173** Static functions
174************************************************************************************/
175
176/************************************************************************************
177** Externs
178************************************************************************************/
Matthew Xie66432dc2014-04-27 05:45:32 -0700179/* By default, even though codec negotiation is enabled, we will not use WBS as the default
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700180* codec unless this variable is set to true.
Matthew Xie66432dc2014-04-27 05:45:32 -0700181*/
182#ifndef BTIF_HF_WBS_PREFERRED
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700183#define BTIF_HF_WBS_PREFERRED false
Matthew Xie66432dc2014-04-27 05:45:32 -0700184#endif
185
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700186bool btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800187
188/************************************************************************************
189** Functions
190************************************************************************************/
191
192/*******************************************************************************
193**
194** Function is_connected
195**
196** Description Internal function to check if HF is connected
197**
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700198** Returns true if connected
The Android Open Source Project5738f832012-12-12 16:00:35 -0800199**
200*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700201static bool is_connected(bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800202{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700203 int i;
204 for (i = 0; i < btif_max_hf_clients; ++i)
205 {
206 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
207 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
208 ((bd_addr == NULL) || (bdcmp(bd_addr->address,
209 btif_hf_cb[i].connected_bda.address) == 0)))
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700210 return true;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700211 }
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700212 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800213}
214
215/*******************************************************************************
216**
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700217** Function btif_hf_idx_by_bdaddr
218**
219** Description Internal function to get idx by bdaddr
220**
221** Returns idx
222**
223*******************************************************************************/
224static int btif_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
225{
226 int i;
227 for (i = 0; i < btif_max_hf_clients; ++i)
228 {
229 if ((bdcmp(bd_addr->address,
230 btif_hf_cb[i].connected_bda.address) == 0))
231 return i;
232 }
233 return BTIF_HF_INVALID_IDX;
234}
235
236/*******************************************************************************
237**
The Android Open Source Project5738f832012-12-12 16:00:35 -0800238** Function callstate_to_callsetup
239**
240** Description Converts HAL call state to BTA call setup indicator value
241**
242** Returns BTA call indicator value
243**
244*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700245static uint8_t callstate_to_callsetup(bthf_call_state_t call_state)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800246{
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700247 uint8_t call_setup = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800248 if (call_state == BTHF_CALL_STATE_INCOMING)
249 call_setup = 1;
250 if (call_state == BTHF_CALL_STATE_DIALING)
251 call_setup = 2;
252 if (call_state == BTHF_CALL_STATE_ALERTING)
253 call_setup = 3;
254
255 return call_setup;
256}
257
258/*******************************************************************************
259**
260** Function send_at_result
261**
262** Description Send AT result code (OK/ERROR)
263**
264** Returns void
265**
266*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700267static void send_at_result(uint8_t ok_flag, uint16_t errcode, int idx)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800268{
269 tBTA_AG_RES_DATA ag_res;
270 memset (&ag_res, 0, sizeof (ag_res));
271
272 ag_res.ok_flag = ok_flag;
273 if (ok_flag == BTA_AG_OK_ERROR)
274 {
275 ag_res.errcode = errcode;
276 }
277
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700278 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800279}
280
281/*******************************************************************************
282**
283** Function send_indicator_update
284**
285** Description Send indicator update (CIEV)
286**
287** Returns void
288**
289*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700290static void send_indicator_update (uint16_t indicator, uint16_t value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800291{
292 tBTA_AG_RES_DATA ag_res;
293
294 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
295 ag_res.ind.id = indicator;
296 ag_res.ind.value = value;
297
298 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
299}
300
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700301void clear_phone_state_multihf(int idx)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800302{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700303 btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE;
304 btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800305}
306
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700307/*******************************************************************************
308**
309** Function btif_hf_latest_connected_idx
310**
311** Description Returns idx for latest connected HF
312**
313** Returns int
314**
315*******************************************************************************/
316static int btif_hf_latest_connected_idx()
317{
318 struct timespec now, conn_time_delta;
319 int latest_conn_idx = BTIF_HF_INVALID_IDX, i;
320
321 clock_gettime(CLOCK_MONOTONIC, &now);
322 conn_time_delta.tv_sec = now.tv_sec;
323
324 for (i = 0; i < btif_max_hf_clients; i++)
325 {
326 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)
327 {
328 if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec)
329 < conn_time_delta.tv_sec)
330 {
331 conn_time_delta.tv_sec =
332 now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec;
333 latest_conn_idx = i;
334 }
335 }
336 }
337 return latest_conn_idx;
338}
339
340/*******************************************************************************
341**
342** Function btif_hf_check_if_slc_connected
343**
344** Description Returns BT_STATUS_SUCCESS if SLC is up for any HF
345**
346** Returns bt_status_t
347**
348*******************************************************************************/
349static bt_status_t btif_hf_check_if_slc_connected()
350{
351 if (bt_hf_callbacks == NULL)
352 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700353 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700354 return BT_STATUS_NOT_READY;
355 }
356 else
357 {
358 int i;
359 for (i = 0; i < btif_max_hf_clients; i++)
360 {
Bernhard Rosenkränzer104e3f22014-11-12 21:53:08 +0100361 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700362 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700363 BTIF_TRACE_EVENT("BTHF: %s: slc connected for idx = %d",
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700364 __func__, i);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700365 return BT_STATUS_SUCCESS;
366 }
367 }
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700368 BTIF_TRACE_WARNING("BTHF: %s: No SLC connection up", __func__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700369 return BT_STATUS_NOT_READY;
370 }
371}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800372
373/*****************************************************************************
374** Section name (Group of functions)
375*****************************************************************************/
376
377/*****************************************************************************
378**
379** btif hf api functions (no context switch)
380**
381*****************************************************************************/
382
The Android Open Source Project5738f832012-12-12 16:00:35 -0800383/*******************************************************************************
384**
385** Function btif_hf_upstreams_evt
386**
387** Description Executes HF UPSTREAMS events in btif context
388**
389** Returns void
390**
391*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700392static void btif_hf_upstreams_evt(uint16_t event, char* p_param)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800393{
394 tBTA_AG *p_data = (tBTA_AG *)p_param;
395 bdstr_t bdstr;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700396 int idx = p_data->hdr.handle - 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800397
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700398 BTIF_TRACE_DEBUG("%s: event=%s", __func__, dump_hf_event(event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800399
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530400 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
401 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700402 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530403 return;
404 }
405
The Android Open Source Project5738f832012-12-12 16:00:35 -0800406 switch (event)
407 {
408 case BTA_AG_ENABLE_EVT:
409 case BTA_AG_DISABLE_EVT:
410 break;
411
412 case BTA_AG_REGISTER_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700413 btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700414 BTIF_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT,"
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700415 "btif_hf_cb.handle = %d", __func__, btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800416 break;
417
418 case BTA_AG_OPEN_EVT:
419 if (p_data->open.status == BTA_AG_SUCCESS)
420 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700421 bdcpy(btif_hf_cb[idx].connected_bda.address,
422 p_data->open.bd_addr);
423 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
424 btif_hf_cb[idx].peer_feat = 0;
425 clear_phone_state_multihf(idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800426 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700427 else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800428 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700429 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800430 }
431 else
432 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700433 BTIF_TRACE_WARNING("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s",
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700434 __func__, p_data->open.status, btif_hf_cb[idx].state,
Sharvil Nanavati8a6a89f2014-08-20 09:39:25 -0700435 bdaddr_to_string(&btif_hf_cb[idx].connected_bda, bdstr, sizeof(bdstr)));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800436 break;
437 }
438
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700439 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
440 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800441
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700442 if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
443 bdsetany(btif_hf_cb[idx].connected_bda.address);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800444
445 if (p_data->open.status != BTA_AG_SUCCESS)
446 btif_queue_advance();
447 break;
448
449 case BTA_AG_CLOSE_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700450 btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
451 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700452 BTIF_TRACE_DEBUG("%s: BTA_AG_CLOSE_EVT,"
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700453 "idx = %d, btif_hf_cb.handle = %d", __func__, idx,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700454 btif_hf_cb[idx].handle);
455 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
456 &btif_hf_cb[idx].connected_bda);
457 bdsetany(btif_hf_cb[idx].connected_bda.address);
458 btif_hf_cb[idx].peer_feat = 0;
459 clear_phone_state_multihf(idx);
460 hf_idx = btif_hf_latest_connected_idx();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800461 /* If AG_OPEN was received but SLC was not setup in a specified time (10 seconds),
462 ** then AG_CLOSE may be received. We need to advance the queue here
463 */
464 btif_queue_advance();
465 break;
466
467 case BTA_AG_CONN_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700468 clock_gettime(CLOCK_MONOTONIC,
469 &btif_hf_cb[idx].connected_timestamp);
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700470 BTIF_TRACE_DEBUG("%s: BTA_AG_CONN_EVT, idx = %d ",
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700471 __func__, idx);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700472 btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
473 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
474 hf_idx = btif_hf_latest_connected_idx();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800475
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700476 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
477 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800478 btif_queue_advance();
479 break;
480
481 case BTA_AG_AUDIO_OPEN_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700482 hf_idx = idx;
483 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
484 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800485 break;
486
487 case BTA_AG_AUDIO_CLOSE_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700488 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
489 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800490 break;
491
492 /* BTA auto-responds, silently discard */
493 case BTA_AG_SPK_EVT:
494 case BTA_AG_MIC_EVT:
495 HAL_CBACK(bt_hf_callbacks, volume_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700496 (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK :
497 BTHF_VOLUME_TYPE_MIC, p_data->val.num,
498 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800499 break;
500
501 case BTA_AG_AT_A_EVT:
Hemant Gupta4974d812014-05-05 17:45:08 +0530502 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
503 hf_idx = idx;
504 else
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700505 BTIF_TRACE_DEBUG("Donot set hf_idx for ATA since already in a call");
Hemant Gupta4974d812014-05-05 17:45:08 +0530506
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700507 HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
508 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800509 break;
510
511 /* Java needs to send OK/ERROR for these commands */
512 case BTA_AG_AT_BLDN_EVT:
513 case BTA_AG_AT_D_EVT:
Hemant Gupta4974d812014-05-05 17:45:08 +0530514 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
515 hf_idx = idx;
516 else
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700517 BTIF_TRACE_DEBUG("Donot set hf_idx for BLDN/D since already in a call");
Hemant Gupta4974d812014-05-05 17:45:08 +0530518
The Android Open Source Project5738f832012-12-12 16:00:35 -0800519 HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700520 (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
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_CHUP_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700525 HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
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_CIND_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700530 HAL_CBACK(bt_hf_callbacks, cind_cmd_cb,
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_VTS_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700535 HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
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_BVRA_EVT:
540 HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700541 (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED :
542 BTHF_VR_STATE_STOPPED, &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800543 break;
544
545 case BTA_AG_AT_NREC_EVT:
546 HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700547 (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
548 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800549 break;
550
551 /* TODO: Add a callback for CBC */
552 case BTA_AG_AT_CBC_EVT:
553 break;
554
555 case BTA_AG_AT_CKPD_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700556 HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
557 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800558 break;
559
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700560#if (BTM_WBS_INCLUDED == TRUE)
Matthew Xie66432dc2014-04-27 05:45:32 -0700561 case BTA_AG_WBS_EVT:
562 BTIF_TRACE_DEBUG("BTA_AG_WBS_EVT Set codec status %d codec %d 1=CVSD 2=MSBC", \
563 p_data->val.hdr.status, p_data->val.num);
564 if(p_data->val.num == BTA_AG_CODEC_CVSD)
565 { HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NO, &btif_hf_cb[idx].connected_bda);}
566 else if(p_data->val.num == BTA_AG_CODEC_MSBC)
567 {HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_YES, &btif_hf_cb[idx].connected_bda);}
568 else
569 {HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NONE, &btif_hf_cb[idx].connected_bda);}
570 break;
571#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800572 /* Java needs to send OK/ERROR for these commands */
573 case BTA_AG_AT_CHLD_EVT:
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700574 HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, (bthf_chld_type_t)atoi(p_data->val.str),
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700575 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576 break;
577
578 case BTA_AG_AT_CLCC_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700579 HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb,
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_COPS_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700584 HAL_CBACK(bt_hf_callbacks, cops_cmd_cb,
585 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800586 break;
587
588 case BTA_AG_AT_UNAT_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700589 HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
590 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800591 break;
592
593 case BTA_AG_AT_CNUM_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700594 HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb,
595 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800596 break;
597
598 /* TODO: Some of these commands may need to be sent to app. For now respond with error */
599 case BTA_AG_AT_BINP_EVT:
600 case BTA_AG_AT_BTRH_EVT:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700601 send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800602 break;
Matthew Xie66432dc2014-04-27 05:45:32 -0700603 case BTA_AG_AT_BAC_EVT:
604 BTIF_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num);
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700605#if (BTM_WBS_INCLUDED == TRUE)
Matthew Xie66432dc2014-04-27 05:45:32 -0700606 /* If the peer supports mSBC and the BTIF prefferred codec is also mSBC, then
607 we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC at the time
608 of SCO connection establishment */
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700609 if ((btif_conf_hf_force_wbs == true) && (p_data->val.num & BTA_AG_CODEC_MSBC))
Matthew Xie66432dc2014-04-27 05:45:32 -0700610 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700611 BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to MSBC", __func__);
Matthew Xie66432dc2014-04-27 05:45:32 -0700612 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_MSBC);
613 }
614 else
615 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700616 BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to CVSD", __func__);
Matthew Xie66432dc2014-04-27 05:45:32 -0700617 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_CVSD);
618 }
619#endif
620 break;
621 case BTA_AG_AT_BCS_EVT:
622 BTIF_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num);
623 /* no BTHF_WBS_NONE case, becuase HF1.6 supported device can send BCS */
624 HAL_CBACK(bt_hf_callbacks, wbs_cb,(p_data->val.num == BTA_AG_CODEC_MSBC) ? \
625 BTHF_WBS_YES : BTHF_WBS_NO, &btif_hf_cb[idx].connected_bda);
626 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800627
Mudumba Ananth4de9bbc2016-02-29 02:21:43 -0800628 case BTA_AG_AT_BIND_EVT:
629 if (p_data->val.hdr.status == BTA_AG_SUCCESS)
630 {
631 HAL_CBACK(bt_hf_callbacks, bind_cb,p_data->val.str,
632 &btif_hf_cb[idx].connected_bda);
633 }
634 break;
635
636 case BTA_AG_AT_BIEV_EVT:
637 if (p_data->val.hdr.status == BTA_AG_SUCCESS)
638 {
639 HAL_CBACK(bt_hf_callbacks, biev_cb, (bthf_hf_ind_type_t)p_data->val.lidx, (int)p_data->val.num,
640 &btif_hf_cb[idx].connected_bda);
641 }
642 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800643 default:
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700644 BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800645 break;
646 }
647}
648
649/*******************************************************************************
650**
651** Function bte_hf_evt
652**
653** Description Switches context from BTE to BTIF for all HF events
654**
655** Returns void
656**
657*******************************************************************************/
658
659static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *p_data)
660{
661 bt_status_t status;
662 int param_len = 0;
663
664 /* TODO: BTA sends the union members and not tBTA_AG. If using param_len=sizeof(tBTA_AG), we get a crash on memcpy */
665 if (BTA_AG_REGISTER_EVT == event)
666 param_len = sizeof(tBTA_AG_REGISTER);
667 else if (BTA_AG_OPEN_EVT == event)
668 param_len = sizeof(tBTA_AG_OPEN);
669 else if (BTA_AG_CONN_EVT == event)
670 param_len = sizeof(tBTA_AG_CONN);
671 else if ( (BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) || (BTA_AG_AUDIO_CLOSE_EVT == event))
672 param_len = sizeof(tBTA_AG_HDR);
673 else if (p_data)
674 param_len = sizeof(tBTA_AG_VAL);
675
676 /* switch context to btif task context (copy full union size for convenience) */
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700677 status = btif_transfer_context(btif_hf_upstreams_evt, (uint16_t)event, (char*)p_data, param_len, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800678
679 /* catch any failed context transfers */
680 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
681}
682
The Android Open Source Project5738f832012-12-12 16:00:35 -0800683/*******************************************************************************
684**
685** Function btif_in_hf_generic_evt
686**
687** Description Processes generic events to be sent to JNI that are not triggered from the BTA.
688** Always runs in BTIF context
689**
690** Returns void
691**
692*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700693static void btif_in_hf_generic_evt(uint16_t event, char *p_param)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800694{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700695 int idx = btif_hf_idx_by_bdaddr((bt_bdaddr_t *)p_param);
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800696
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700697 BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530698
699 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
700 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700701 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530702 return;
703 }
704
The Android Open Source Project5738f832012-12-12 16:00:35 -0800705 switch (event) {
706 case BTIF_HFP_CB_AUDIO_CONNECTING:
707 {
708 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700709 &btif_hf_cb[idx].connected_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800710 } break;
711 default:
712 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700713 BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800714 }
715 break;
716 }
717}
718
The Android Open Source Project5738f832012-12-12 16:00:35 -0800719/*******************************************************************************
720**
721** Function btif_hf_init
722**
723** Description initializes the hf interface
724**
725** Returns bt_status_t
726**
727*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700728static bt_status_t init( bthf_callbacks_t* callbacks, int max_hf_clients)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800729{
Andre Eisenbach44348762015-04-22 19:21:03 -0700730 btif_max_hf_clients = max_hf_clients;
Andre Eisenbached578862015-04-23 10:54:10 -0700731 BTIF_TRACE_DEBUG("%s - max_hf_clients=%d", __func__, btif_max_hf_clients);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800732
733 bt_hf_callbacks = callbacks;
Andre Eisenbach44348762015-04-22 19:21:03 -0700734 memset(&btif_hf_cb, 0, sizeof(btif_hf_cb));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800735
736 /* Invoke the enable service API to the core to set the appropriate service_id
737 * Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled (phone)
738 * othwerwise only HSP is enabled (tablet)
739 */
740#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
741 btif_enable_service(BTA_HFP_SERVICE_ID);
742#else
743 btif_enable_service(BTA_HSP_SERVICE_ID);
744#endif
745
Andre Eisenbach44348762015-04-22 19:21:03 -0700746 for (int i = 0; i < btif_max_hf_clients; i++)
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700747 clear_phone_state_multihf(i);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800748
749 return BT_STATUS_SUCCESS;
750}
751
752/*******************************************************************************
753**
754** Function connect
755**
756** Description connect to headset
757**
758** Returns bt_status_t
759**
760*******************************************************************************/
Hemant Guptacc355592013-10-24 15:37:17 +0530761static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800762{
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700763 CHECK_BTHF_INIT();
764 int i;
765 for (i = 0; i < btif_max_hf_clients;)
766 {
767 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
768 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)))
769 i++;
770 else
771 break;
772 }
773
774 if (i == btif_max_hf_clients)
775 return BT_STATUS_BUSY;
776
The Android Open Source Project5738f832012-12-12 16:00:35 -0800777 if (!is_connected(bd_addr))
778 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700779 btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
780 bdcpy(btif_hf_cb[i].connected_bda.address, bd_addr->address);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800781
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700782 BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda.address,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800783 BTIF_HF_SECURITY, BTIF_HF_SERVICES);
784 return BT_STATUS_SUCCESS;
785 }
786
787 return BT_STATUS_BUSY;
788}
789
790static bt_status_t connect( bt_bdaddr_t *bd_addr )
791{
792 CHECK_BTHF_INIT();
793 return btif_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_int);
794}
795
796/*******************************************************************************
797**
798** Function disconnect
799**
800** Description disconnect from headset
801**
802** Returns bt_status_t
803**
804*******************************************************************************/
805static bt_status_t disconnect( bt_bdaddr_t *bd_addr )
806{
807 CHECK_BTHF_INIT();
808
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700809 int idx = btif_hf_idx_by_bdaddr(bd_addr);
810
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530811 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
812 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700813 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530814 return BT_STATUS_FAIL;
815 }
816
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700817 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800818 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700819 BTA_AgClose(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800820 return BT_STATUS_SUCCESS;
821 }
822
823 return BT_STATUS_FAIL;
824}
825
826/*******************************************************************************
827**
828** Function connect_audio
829**
830** Description create an audio connection
831**
832** Returns bt_status_t
833**
834*******************************************************************************/
835static bt_status_t connect_audio( bt_bdaddr_t *bd_addr )
836{
837 CHECK_BTHF_INIT();
838
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700839 int idx = btif_hf_idx_by_bdaddr(bd_addr);
840
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530841 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
842 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700843 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530844 return BT_STATUS_FAIL;
845 }
846
Mallikarjuna GBc8c082b2014-10-08 14:01:16 +0530847 /* Check if SLC is connected */
848 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
849 return BT_STATUS_NOT_READY;
850
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700851 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800852 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700853 BTA_AgAudioOpen(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800854
855 /* Inform the application that the audio connection has been initiated successfully */
856 btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING,
857 (char *)bd_addr, sizeof(bt_bdaddr_t), NULL);
858 return BT_STATUS_SUCCESS;
859 }
860
861 return BT_STATUS_FAIL;
862}
863
864/*******************************************************************************
865**
866** Function disconnect_audio
867**
868** Description close the audio connection
869**
870** Returns bt_status_t
871**
872*******************************************************************************/
873static bt_status_t disconnect_audio( bt_bdaddr_t *bd_addr )
874{
875 CHECK_BTHF_INIT();
876
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700877 int idx = btif_hf_idx_by_bdaddr(bd_addr);
878
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530879 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
880 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700881 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530882 return BT_STATUS_FAIL;
883 }
884
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700885 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800886 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700887 BTA_AgAudioClose(btif_hf_cb[idx].handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800888 return BT_STATUS_SUCCESS;
889 }
890
891 return BT_STATUS_FAIL;
892}
893
894/*******************************************************************************
895**
896** Function start_voice_recognition
897**
898** Description start voice recognition
899**
900** Returns bt_status_t
901**
902*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700903static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800904{
905 CHECK_BTHF_INIT();
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700906
907 int idx = btif_hf_idx_by_bdaddr(bd_addr);
908
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530909 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
910 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700911 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530912 return BT_STATUS_FAIL;
913 }
914
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700915 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800916 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700917 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800918 {
919 tBTA_AG_RES_DATA ag_res;
920 memset(&ag_res, 0, sizeof(ag_res));
921 ag_res.state = 1;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700922 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800923
924 return BT_STATUS_SUCCESS;
925 }
926 else
927 {
928 return BT_STATUS_UNSUPPORTED;
929 }
930 }
931
932 return BT_STATUS_NOT_READY;
933}
934
935/*******************************************************************************
936**
937** Function stop_voice_recognition
938**
939** Description stop voice recognition
940**
941** Returns bt_status_t
942**
943*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700944static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800945{
946 CHECK_BTHF_INIT();
947
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700948 int idx = btif_hf_idx_by_bdaddr(bd_addr);
949
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530950 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
951 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700952 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530953 return BT_STATUS_FAIL;
954 }
955
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700956 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800957 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700958 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800959 {
960 tBTA_AG_RES_DATA ag_res;
961 memset(&ag_res, 0, sizeof(ag_res));
962 ag_res.state = 0;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700963 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800964
965 return BT_STATUS_SUCCESS;
966 }
967 else
968 {
969 return BT_STATUS_UNSUPPORTED;
970 }
971 }
972
973 return BT_STATUS_NOT_READY;
974}
975
976/*******************************************************************************
977**
978** Function volume_control
979**
980** Description volume control
981**
982** Returns bt_status_t
983**
984*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700985static bt_status_t volume_control(bthf_volume_type_t type, int volume,
986 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
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530992 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
993 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700994 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +0530995 return BT_STATUS_FAIL;
996 }
997
The Android Open Source Project5738f832012-12-12 16:00:35 -0800998 tBTA_AG_RES_DATA ag_res;
999 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001000 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001001 {
1002 ag_res.num = volume;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001003 BTA_AgResult(btif_hf_cb[idx].handle,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001004 (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
1005 &ag_res);
1006 return BT_STATUS_SUCCESS;
1007 }
1008
1009 return BT_STATUS_FAIL;
1010}
1011
1012/*******************************************************************************
1013**
1014** Function device_status_notification
1015**
1016** Description Combined device status change notification
1017**
1018** Returns bt_status_t
1019**
1020*******************************************************************************/
1021static bt_status_t device_status_notification(bthf_network_state_t ntk_state,
1022 bthf_service_type_t svc_type, int signal, int batt_chg)
1023{
1024 CHECK_BTHF_INIT();
1025
1026 if (is_connected(NULL))
1027 {
1028 /* send all indicators to BTA.
1029 ** BTA will make sure no duplicates are sent out
1030 */
1031 send_indicator_update(BTA_AG_IND_SERVICE,
1032 (ntk_state == BTHF_NETWORK_STATE_AVAILABLE) ? 1 : 0);
1033 send_indicator_update(BTA_AG_IND_ROAM,
1034 (svc_type == BTHF_SERVICE_TYPE_HOME) ? 0 : 1);
1035 send_indicator_update(BTA_AG_IND_SIGNAL, signal);
1036 send_indicator_update(BTA_AG_IND_BATTCHG, batt_chg);
1037 return BT_STATUS_SUCCESS;
1038 }
1039
1040 return BT_STATUS_SUCCESS;
1041}
1042
1043/*******************************************************************************
1044**
1045** Function cops_response
1046**
1047** Description Response for COPS command
1048**
1049** Returns bt_status_t
1050**
1051*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001052static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001053{
1054 CHECK_BTHF_INIT();
1055
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001056 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1057
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301058 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
1059 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001060 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301061 return BT_STATUS_FAIL;
1062 }
1063
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 tBTA_AG_RES_DATA ag_res;
1067
1068 /* Format the response */
Sharvil Nanavatia459df82016-01-04 17:15:18 -08001069 sprintf (ag_res.str, "0,0,\"%.16s\"", cops);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001070 ag_res.ok_flag = BTA_AG_OK_DONE;
1071
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001072 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001073 return BT_STATUS_SUCCESS;
1074 }
1075 return BT_STATUS_FAIL;
1076}
1077
1078/*******************************************************************************
1079**
1080** Function cind_response
1081**
1082** Description Response for CIND command
1083**
1084** Returns bt_status_t
1085**
1086*******************************************************************************/
1087static bt_status_t cind_response(int svc, int num_active, int num_held,
1088 bthf_call_state_t call_setup_state,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001089 int signal, int roam, int batt_chg,
1090 bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001091{
1092 CHECK_BTHF_INIT();
1093
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001094 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1095
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301096 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
1097 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001098 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301099 return BT_STATUS_FAIL;
1100 }
1101
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001102 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001103 {
1104 tBTA_AG_RES_DATA ag_res;
1105
1106 memset (&ag_res, 0, sizeof (ag_res));
1107 /* per the errata 2043, call=1 implies atleast one call is in progress (active/held)
1108 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1109 **/
1110 sprintf (ag_res.str, "%d,%d,%d,%d,%d,%d,%d",
1111 (num_active + num_held) ? 1 : 0, /* Call state */
1112 callstate_to_callsetup(call_setup_state), /* Callsetup state */
1113 svc, /* network service */
1114 signal, /* Signal strength */
1115 roam, /* Roaming indicator */
1116 batt_chg, /* Battery level */
1117 ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
1118
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001119 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001120
1121 return BT_STATUS_SUCCESS;
1122 }
1123
1124 return BT_STATUS_FAIL;
1125}
1126
1127/*******************************************************************************
1128**
Mudumba Ananth4de9bbc2016-02-29 02:21:43 -08001129** Function bind_response
1130**
1131** Description Send +BIND response
1132**
1133** Returns bt_status_t
1134**
1135*******************************************************************************/
1136static bt_status_t bind_response(bthf_hf_ind_type_t ind_id, bthf_hf_ind_status_t ind_status,
1137 bt_bdaddr_t * bd_addr)
1138{
1139 CHECK_BTHF_INIT();
1140
1141 int index = btif_hf_idx_by_bdaddr(bd_addr);
1142 if (!is_connected(bd_addr) || index == BTIF_HF_INVALID_IDX)
1143 return BT_STATUS_FAIL;
1144
1145 tBTA_AG_RES_DATA ag_res;
1146 memset(&ag_res, 0, sizeof(ag_res));
1147 ag_res.ind.id = ind_id;
1148 ag_res.ind.on_demand = (ind_status == BTHF_HF_IND_ENABLED);
1149
1150 BTA_AgResult(btif_hf_cb[index].handle, BTA_AG_BIND_RES, &ag_res);
1151 return BT_STATUS_SUCCESS;
1152}
1153
1154/*******************************************************************************
1155**
The Android Open Source Project5738f832012-12-12 16:00:35 -08001156** Function formatted_at_response
1157**
1158** Description Pre-formatted AT response, typically in response to unknown AT cmd
1159**
1160** Returns bt_status_t
1161**
1162*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001163static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001164{
1165 CHECK_BTHF_INIT();
1166 tBTA_AG_RES_DATA ag_res;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001167 int idx = btif_hf_idx_by_bdaddr(bd_addr);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001168
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301169 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
1170 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001171 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301172 return BT_STATUS_FAIL;
1173 }
1174
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001175 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001176 {
1177 /* Format the response and send */
1178 memset (&ag_res, 0, sizeof (ag_res));
1179 strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001180 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001181
1182 return BT_STATUS_SUCCESS;
1183 }
1184
1185 return BT_STATUS_FAIL;
1186}
1187
1188/*******************************************************************************
1189**
1190** Function at_response
1191**
1192** Description ok/error response
1193**
1194** Returns bt_status_t
1195**
1196*******************************************************************************/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001197static bt_status_t at_response(bthf_at_response_t response_code,
1198 int error_code, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001199{
1200 CHECK_BTHF_INIT();
1201
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001202 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1203
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301204 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
1205 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001206 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301207 return BT_STATUS_FAIL;
1208 }
1209
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001210 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001211 {
1212 send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001213 : BTA_AG_OK_ERROR, error_code, idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001214 return BT_STATUS_SUCCESS;
1215 }
1216
The Android Open Source Project5738f832012-12-12 16:00:35 -08001217 return BT_STATUS_FAIL;
1218}
1219
1220/*******************************************************************************
1221**
1222** Function clcc_response
1223**
1224** Description response for CLCC command
1225** Can be iteratively called for each call index. Call index
1226** of 0 will be treated as NULL termination (Completes response)
1227**
1228** Returns bt_status_t
1229**
1230*******************************************************************************/
1231static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001232 bthf_call_state_t state, bthf_call_mode_t mode,
1233 bthf_call_mpty_type_t mpty, const char *number,
1234 bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001235{
1236 CHECK_BTHF_INIT();
1237
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001238 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1239
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301240 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
1241 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001242 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301243 return BT_STATUS_FAIL;
1244 }
1245
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001246 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001247 {
1248 tBTA_AG_RES_DATA ag_res;
1249 int xx;
1250
1251 memset (&ag_res, 0, sizeof (ag_res));
1252
1253 /* Format the response */
1254 if (index == 0)
1255 {
1256 ag_res.ok_flag = BTA_AG_OK_DONE;
1257 }
1258 else
1259 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001260 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 -08001261 index, dir, state, mode, number, type);
1262 xx = sprintf (ag_res.str, "%d,%d,%d,%d,%d",
1263 index, dir, state, mode, mpty);
1264
1265 if (number)
1266 {
1267 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+'))
1268 sprintf (&ag_res.str[xx], ",\"+%s\",%d", number, type);
1269 else
1270 sprintf (&ag_res.str[xx], ",\"%s\",%d", number, type);
1271 }
1272 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001273 BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001274
1275 return BT_STATUS_SUCCESS;
1276 }
1277
1278 return BT_STATUS_FAIL;
1279}
1280
1281/*******************************************************************************
1282**
1283** Function phone_state_change
1284**
1285** Description notify of a call state change
1286** number & type: valid only for incoming & waiting call
1287**
1288** Returns bt_status_t
1289**
1290*******************************************************************************/
1291
1292static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_state_t call_setup_state,
1293 const char *number, bthf_call_addrtype_t type)
1294{
1295 tBTA_AG_RES res = 0xff;
1296 tBTA_AG_RES_DATA ag_res;
1297 bt_status_t status = BT_STATUS_SUCCESS;
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001298 bool activeCallUpdated = false;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001299 int idx, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001300
Hemant Gupta4974d812014-05-05 17:45:08 +05301301 /* hf_idx is index of connected HS that sent ATA/BLDN,
1302 otherwise index of latest connected HS */
1303 if (hf_idx != BTIF_HF_INVALID_IDX)
1304 idx = hf_idx;
1305 else
1306 idx = btif_hf_latest_connected_idx();
1307
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001308 BTIF_TRACE_DEBUG("phone_state_change: idx = %d", idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001309
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001310 /* Check if SLC is connected */
1311 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
1312 return BT_STATUS_NOT_READY;
1313
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001314 BTIF_TRACE_DEBUG("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001315 " call_setup=%s [prev: %s]", num_active, btif_hf_cb[idx].num_active,
1316 num_held, btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
1317 dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001318
1319 /* if all indicators are 0, send end call and return */
1320 if (num_active == 0 && num_held == 0 && call_setup_state == BTHF_CALL_STATE_IDLE)
1321 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001322 BTIF_TRACE_DEBUG("%s: Phone on hook", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001323
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001324 /* record call termination timestamp if there was an active/held call or
1325 callsetup state > BTHF_CALL_STATE_IDLE */
1326 if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE ) ||
1327 (btif_hf_cb[idx].num_active) ||(btif_hf_cb[idx].num_held))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001328 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001329 BTIF_TRACE_DEBUG("%s: Record call termination timestamp", __func__);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001330 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001331 }
1332 BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001333 hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001334
1335 /* if held call was present, reset that as well */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001336 if (btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001337 send_indicator_update(BTA_AG_IND_CALLHELD, 0);
1338
1339 goto update_call_states;
1340 }
1341
1342 /* active state can change when:
1343 ** 1. an outgoing/incoming call was answered
1344 ** 2. an held was resumed
1345 ** 3. without callsetup notifications, call became active
1346 ** (3) can happen if call is active and a headset connects to us
1347 **
1348 ** In the case of (3), we will have to notify the stack of an active
1349 ** call, instead of sending an indicator update. This will also
1350 ** force the SCO to be setup. Handle this special case here prior to
1351 ** call setup handling
1352 */
Mallikarjuna GB902ba022015-05-21 19:50:27 +05301353 if ( ((num_active + num_held) > 0) && (btif_hf_cb[idx].num_active == 0) && (btif_hf_cb[idx].num_held == 0) &&
1354 (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001355 {
Mallikarjuna GB902ba022015-05-21 19:50:27 +05301356 BTIF_TRACE_DEBUG("%s: Active/Held call notification received without call setup update",
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001357 __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001358
1359 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
Hall Liud22226b2016-02-19 17:20:08 -08001360 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
Mallikarjuna GBd345bb22015-05-22 11:56:48 +05301361 /* Addition call setup with the Active call
1362 ** CIND response should have been updated.
1363 ** just open SCO conenction.
1364 */
1365 if (call_setup_state != BTHF_CALL_STATE_IDLE)
1366 res = BTA_AG_MULTI_CALL_RES;
1367 else
1368 res = BTA_AG_OUT_CALL_CONN_RES;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001369 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001370 activeCallUpdated = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001371 }
1372
1373 /* Ringing call changed? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001374 if (call_setup_state != btif_hf_cb[idx].call_setup_state)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001375 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001376 BTIF_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s",
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001377 __func__, dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001378 dump_hf_call_state(call_setup_state));
1379 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1380
1381 switch (call_setup_state)
1382 {
1383 case BTHF_CALL_STATE_IDLE:
1384 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001385 switch (btif_hf_cb[idx].call_setup_state)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001386 {
1387 case BTHF_CALL_STATE_INCOMING:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001388 if (num_active > btif_hf_cb[idx].num_active)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001389 {
1390 res = BTA_AG_IN_CALL_CONN_RES;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001391 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001392 }
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001393 else if (num_held > btif_hf_cb[idx].num_held)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001394 res = BTA_AG_IN_CALL_HELD_RES;
1395 else
1396 res = BTA_AG_CALL_CANCEL_RES;
1397 break;
1398 case BTHF_CALL_STATE_DIALING:
1399 case BTHF_CALL_STATE_ALERTING:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001400 if (num_active > btif_hf_cb[idx].num_active)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001401 {
1402 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
1403 res = BTA_AG_OUT_CALL_CONN_RES;
1404 }
1405 else
1406 res = BTA_AG_CALL_CANCEL_RES;
1407 break;
1408 default:
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001409 BTIF_TRACE_ERROR("%s: Incorrect Call setup state transition", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001410 status = BT_STATUS_PARM_INVALID;
1411 break;
1412 }
1413 } break;
1414
1415 case BTHF_CALL_STATE_INCOMING:
1416 if (num_active || num_held)
1417 res = BTA_AG_CALL_WAIT_RES;
1418 else
1419 res = BTA_AG_IN_CALL_RES;
1420 if (number)
1421 {
1422 int xx = 0;
1423 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+'))
1424 xx = sprintf (ag_res.str, "\"+%s\"", number);
1425 else
1426 xx = sprintf (ag_res.str, "\"%s\"", number);
1427 ag_res.num = type;
1428
1429 if (res == BTA_AG_CALL_WAIT_RES)
1430 sprintf(&ag_res.str[xx], ",%d", type);
1431 }
1432 break;
1433 case BTHF_CALL_STATE_DIALING:
Mallikarjuna GB8a67ac72014-09-19 20:27:17 +05301434 if (!(num_active + num_held))
1435 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001436 res = BTA_AG_OUT_CALL_ORIG_RES;
1437 break;
1438 case BTHF_CALL_STATE_ALERTING:
1439 /* if we went from idle->alert, force SCO setup here. dialing usually triggers it */
Mallikarjuna GB8a67ac72014-09-19 20:27:17 +05301440 if ((btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) &&
1441 !(num_active + num_held))
1442 ag_res.audio_handle = btif_hf_cb[idx].handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001443 res = BTA_AG_OUT_CALL_ALERT_RES;
1444 break;
1445 default:
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001446 BTIF_TRACE_ERROR("%s: Incorrect new ringing call state", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001447 status = BT_STATUS_PARM_INVALID;
1448 break;
1449 }
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001450 BTIF_TRACE_DEBUG("%s: Call setup state changed. res=%d, audio_handle=%d", __func__, res, ag_res.audio_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001451
1452 if (res)
1453 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
1454
1455 /* if call setup is idle, we have already updated call indicator, jump out */
1456 if (call_setup_state == BTHF_CALL_STATE_IDLE)
1457 {
1458 /* check & update callheld */
1459 if ((num_held > 0) && (num_active > 0))
1460 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
1461 goto update_call_states;
1462 }
1463 }
1464
1465 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1466
1467 /* per the errata 2043, call=1 implies atleast one call is in progress (active/held)
1468 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1469 ** Handle call indicator change
1470 **/
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001471 if (!activeCallUpdated && ((num_active + num_held) !=
1472 (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held)) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001473 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001474 BTIF_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d", __func__, btif_hf_cb[idx].num_active, num_active);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001475 send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
1476 }
1477
1478 /* Held Changed? */
Mallikarjuna GBc2c8a1f2015-05-21 17:58:12 +05301479 if (num_held != btif_hf_cb[idx].num_held ||
1480 ((num_active == 0) && ((num_held + btif_hf_cb[idx].num_held) > 1)))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001481 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001482 BTIF_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d",
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001483 __func__, btif_hf_cb[idx].num_held, num_held);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001484 send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
1485 }
1486
1487 /* Calls Swapped? */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001488 if ( (call_setup_state == btif_hf_cb[idx].call_setup_state) &&
The Android Open Source Project5738f832012-12-12 16:00:35 -08001489 (num_active && num_held) &&
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001490 (num_active == btif_hf_cb[idx].num_active) &&
1491 (num_held == btif_hf_cb[idx].num_held) )
The Android Open Source Project5738f832012-12-12 16:00:35 -08001492 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001493 BTIF_TRACE_DEBUG("%s: Calls swapped", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001494 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
1495 }
1496
1497update_call_states:
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001498 for (i = 0; i < btif_max_hf_clients; i++)
1499 {
1500 btif_hf_cb[i].num_active = num_active;
1501 btif_hf_cb[i].num_held = num_held;
1502 btif_hf_cb[i].call_setup_state = call_setup_state;
1503 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001504 return status;
1505}
1506
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301507/*******************************************************************************
1508**
1509** Function btif_hf_is_call_idle
1510**
1511** Description returns true if no call is in progress
1512**
1513** Returns bt_status_t
1514**
1515*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001516bool btif_hf_is_call_idle()
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301517{
1518 if (bt_hf_callbacks == NULL)
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001519 return true;
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301520
1521 for (int i = 0; i < btif_max_hf_clients; ++i)
1522 {
1523 if ((btif_hf_cb[i].call_setup_state != BTHF_CALL_STATE_IDLE)
1524 || ((btif_hf_cb[i].num_held + btif_hf_cb[i].num_active) > 0))
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001525 return false;
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301526 }
1527
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001528 return true;
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301529}
The Android Open Source Project5738f832012-12-12 16:00:35 -08001530
1531/*******************************************************************************
1532**
1533** Function btif_hf_call_terminated_recently
1534**
1535** Description Checks if a call has been terminated
1536**
1537** Returns bt_status_t
1538**
1539*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001540bool btif_hf_call_terminated_recently()
The Android Open Source Project5738f832012-12-12 16:00:35 -08001541{
1542 struct timespec now;
1543
1544 clock_gettime(CLOCK_MONOTONIC, &now);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001545 if (now.tv_sec < btif_hf_cb[0].call_end_timestamp.tv_sec +
1546 BTIF_HF_CALL_END_TIMEOUT)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001547 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001548 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001549 }
1550 else
1551 {
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001552 btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001553 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001554 }
1555}
1556
1557/*******************************************************************************
1558**
1559** Function cleanup
1560**
1561** Description Closes the HF interface
1562**
1563** Returns bt_status_t
1564**
1565*******************************************************************************/
1566static void cleanup( void )
1567{
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001568 BTIF_TRACE_EVENT("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001569
1570 if (bt_hf_callbacks)
1571 {
1572 btif_disable_service(BTA_HFP_SERVICE_ID);
1573 bt_hf_callbacks = NULL;
1574 }
1575}
1576
Matthew Xie66432dc2014-04-27 05:45:32 -07001577/*******************************************************************************
1578**
1579** Function configure_wbs
1580**
1581** Description set to over-ride the current WBS configuration.
1582** It will not send codec setting cmd to the controller now.
1583** It just change the configure.
1584**
1585** Returns bt_status_t
1586**
1587*******************************************************************************/
1588static bt_status_t configure_wbs( bt_bdaddr_t *bd_addr , bthf_wbs_config_t config )
1589{
1590 CHECK_BTHF_INIT();
1591
1592 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1593
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301594 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB))
1595 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001596 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
Mallikarjuna GB46d706a2014-11-07 16:52:25 +05301597 return BT_STATUS_FAIL;
1598 }
1599
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001600 BTIF_TRACE_EVENT("%s config is %d", __func__,config);
Matthew Xie66432dc2014-04-27 05:45:32 -07001601 if (config == BTHF_WBS_YES)
1602 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_MSBC);
1603 else if(config == BTHF_WBS_NO)
1604 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_CVSD);
1605 else
1606 BTA_AgSetCodec(btif_hf_cb[idx].handle,BTA_AG_CODEC_NONE);
1607
1608 return BT_STATUS_SUCCESS;
1609}
1610
The Android Open Source Project5738f832012-12-12 16:00:35 -08001611static const bthf_interface_t bthfInterface = {
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001612 sizeof(bthfInterface),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001613 init,
1614 connect,
1615 disconnect,
1616 connect_audio,
1617 disconnect_audio,
1618 start_voice_recognition,
1619 stop_voice_recognition,
1620 volume_control,
1621 device_status_notification,
1622 cops_response,
1623 cind_response,
1624 formatted_at_response,
1625 at_response,
1626 clcc_response,
1627 phone_state_change,
1628 cleanup,
Matthew Xie66432dc2014-04-27 05:45:32 -07001629 configure_wbs,
Mudumba Ananth4de9bbc2016-02-29 02:21:43 -08001630 bind_response,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001631};
1632
1633/*******************************************************************************
1634**
1635** Function btif_hf_execute_service
1636**
1637** Description Initializes/Shuts down the service
1638**
1639** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1640**
1641*******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001642bt_status_t btif_hf_execute_service(bool b_enable)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001643{
Jakub Pawlowski713993d2016-04-21 13:16:45 -07001644 const char * p_service_names[] = BTIF_HF_SERVICE_NAMES;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001645 int i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001646 if (b_enable)
1647 {
1648 /* Enable and register with BTA-AG */
1649 BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001650 for (i = 0; i < btif_max_hf_clients; i++)
1651 {
1652 BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY,
1653 BTIF_HF_FEATURES, p_service_names, bthf_hf_id[i]);
1654 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001655 }
1656 else {
1657 /* De-register AG */
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001658 for (i = 0; i < btif_max_hf_clients; i++)
1659 {
1660 BTA_AgDeregister(btif_hf_cb[i].handle);
1661 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001662 /* Disable AG */
1663 BTA_AgDisable();
1664 }
1665 return BT_STATUS_SUCCESS;
1666}
1667
1668/*******************************************************************************
1669**
1670** Function btif_hf_get_interface
1671**
1672** Description Get the hf callback interface
1673**
1674** Returns bthf_interface_t
1675**
1676*******************************************************************************/
1677const bthf_interface_t *btif_hf_get_interface()
1678{
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001679 BTIF_TRACE_EVENT("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001680 return &bthfInterface;
1681}