blob: 4ff41cf9fdcaf7a9ec2e5948f06c8d7de2a64d9e [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
Myles Watsonee96a3c2016-11-23 14:49:54 -080019/*******************************************************************************
The Android Open Source Project5738f832012-12-12 16:00:35 -080020 *
21 * Filename: btif_hf.c
22 *
23 * Description: Handsfree Profile Bluetooth Interface
24 *
25 *
Myles Watsonee96a3c2016-11-23 14:49:54 -080026 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080027
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
Satish Kodishalac75a71d2016-06-22 14:22:41 +053037#include "bta/include/utl.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080038#include "bta_ag_api.h"
Marie Janssen49a86702015-07-08 11:48:57 -070039#include "btcore/include/bdaddr.h"
40#include "btif_common.h"
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -070041#include "btif_hf.h"
Marie Janssen49a86702015-07-08 11:48:57 -070042#include "btif_profile_queue.h"
43#include "btif_util.h"
Jack He7a9892c2017-02-02 17:42:40 -080044#include "osi/include/properties.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080045
Myles Watsonee96a3c2016-11-23 14:49:54 -080046/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -070047 * Constants & Macros
Myles Watsonee96a3c2016-11-23 14:49:54 -080048 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080049#ifndef BTIF_HSAG_SERVICE_NAME
50#define BTIF_HSAG_SERVICE_NAME ("Headset Gateway")
51#endif
52
53#ifndef BTIF_HFAG_SERVICE_NAME
54#define BTIF_HFAG_SERVICE_NAME ("Handsfree Gateway")
55#endif
56
57#ifndef BTIF_HF_SERVICES
Myles Watson6bd442f2016-10-19 09:50:22 -070058#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK | BTA_HFP_SERVICE_MASK)
The Android Open Source Project5738f832012-12-12 16:00:35 -080059#endif
60
61#ifndef BTIF_HF_SERVICE_NAMES
Myles Watson6bd442f2016-10-19 09:50:22 -070062#define BTIF_HF_SERVICE_NAMES \
63 { BTIF_HSAG_SERVICE_NAME, BTIF_HFAG_SERVICE_NAME }
The Android Open Source Project5738f832012-12-12 16:00:35 -080064#endif
65
66#ifndef BTIF_HF_SECURITY
Myles Watson6bd442f2016-10-19 09:50:22 -070067#define BTIF_HF_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
The Android Open Source Project5738f832012-12-12 16:00:35 -080068#endif
69
Matthew Xie66432dc2014-04-27 05:45:32 -070070#ifndef BTIF_HF_FEATURES
Myles Watson6bd442f2016-10-19 09:50:22 -070071#define BTIF_HF_FEATURES \
72 (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | BTA_AG_FEAT_REJECT | \
Yoshiharu Kuritaa25ef0b2015-11-25 18:00:30 +090073 BTA_AG_FEAT_ECS | BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_VREC | \
74 BTA_AG_FEAT_CODEC | BTA_AG_FEAT_HF_IND | BTA_AG_FEAT_ESCO | \
75 BTA_AG_FEAT_UNAT)
Matthew Xie66432dc2014-04-27 05:45:32 -070076#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -080077
Jack He7a9892c2017-02-02 17:42:40 -080078/* HF features supported at runtime */
79static uint32_t btif_hf_features = BTIF_HF_FEATURES;
80
Myles Watson6bd442f2016-10-19 09:50:22 -070081#define BTIF_HF_CALL_END_TIMEOUT 6
The Android Open Source Project5738f832012-12-12 16:00:35 -080082
Myles Watson6bd442f2016-10-19 09:50:22 -070083#define BTIF_HF_INVALID_IDX (-1)
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070084
85/* Number of BTIF-HF control blocks */
Myles Watson6bd442f2016-10-19 09:50:22 -070086#define BTIF_HF_NUM_CB 2
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070087
88/* Max HF clients supported from App */
Marie Janssenb7f64bc2016-06-22 12:52:19 -070089uint16_t btif_max_hf_clients = 1;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070090
91/* HF app ids for service registration */
92typedef enum {
Myles Watson6bd442f2016-10-19 09:50:22 -070093 BTIF_HF_ID_1 = 0,
94 BTIF_HF_ID_2,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070095#if (BTIF_HF_NUM_CB == 3)
Myles Watson6bd442f2016-10-19 09:50:22 -070096 BTIF_HF_ID_3
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070097#endif
98} bthf_hf_id_t;
99
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700100uint16_t bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2,
Myles Watson6bd442f2016-10-19 09:50:22 -0700101#if (BTIF_HF_NUM_CB == 3)
102 BTIF_HF_ID_3
103#endif
104};
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700105
Myles Watsonee96a3c2016-11-23 14:49:54 -0800106/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700107 * Local type definitions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800108 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800109
Myles Watsonee96a3c2016-11-23 14:49:54 -0800110/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700111 * Static variables
Myles Watsonee96a3c2016-11-23 14:49:54 -0800112 ******************************************************************************/
Myles Watson6bd442f2016-10-19 09:50:22 -0700113static bthf_callbacks_t* bt_hf_callbacks = NULL;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700114static int hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800115
Myles Watson40cde562016-10-21 09:39:13 -0700116#define CHECK_BTHF_INIT() \
117 do { \
118 if (bt_hf_callbacks == NULL) { \
119 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__); \
120 return BT_STATUS_NOT_READY; \
121 } else { \
122 BTIF_TRACE_EVENT("BTHF: %s", __func__); \
123 } \
124 } while (0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800125
The Android Open Source Project5738f832012-12-12 16:00:35 -0800126/* BTIF-HF control block to map bdaddr to BTA handle */
Myles Watson6bd442f2016-10-19 09:50:22 -0700127typedef struct _btif_hf_cb {
128 uint16_t handle;
129 bt_bdaddr_t connected_bda;
130 bthf_connection_state_t state;
131 bthf_vr_state_t vr_state;
132 tBTA_AG_PEER_FEAT peer_feat;
133 int num_active;
134 int num_held;
135 struct timespec call_end_timestamp;
136 struct timespec connected_timestamp;
137 bthf_call_state_t call_setup_state;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800138} btif_hf_cb_t;
139
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700140static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800141
Myles Watsonee96a3c2016-11-23 14:49:54 -0800142/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700143 * Static functions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800144 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800145
Myles Watsonee96a3c2016-11-23 14:49:54 -0800146/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700147 * Externs
Myles Watsonee96a3c2016-11-23 14:49:54 -0800148 ******************************************************************************/
Myles Watson6bd442f2016-10-19 09:50:22 -0700149/* By default, even though codec negotiation is enabled, we will not use WBS as
150* the default
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700151* codec unless this variable is set to true.
Matthew Xie66432dc2014-04-27 05:45:32 -0700152*/
153#ifndef BTIF_HF_WBS_PREFERRED
Myles Watson6bd442f2016-10-19 09:50:22 -0700154#define BTIF_HF_WBS_PREFERRED false
Matthew Xie66432dc2014-04-27 05:45:32 -0700155#endif
156
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700157bool btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800158
Myles Watsonee96a3c2016-11-23 14:49:54 -0800159/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700160 * Functions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800161 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800162
163/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700164 *
165 * Function is_connected
166 *
167 * Description Internal function to check if HF is connected
168 *
169 * Returns true if connected
170 *
171 ******************************************************************************/
172static bool is_connected(bt_bdaddr_t* bd_addr) {
173 int i;
174 for (i = 0; i < btif_max_hf_clients; ++i) {
175 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
176 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
177 ((bd_addr == NULL) ||
178 (bdcmp(bd_addr->address, btif_hf_cb[i].connected_bda.address) == 0)))
179 return true;
180 }
181 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800182}
183
184/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700185 *
186 * Function btif_hf_idx_by_bdaddr
187 *
188 * Description Internal function to get idx by bdaddr
189 *
190 * Returns idx
191 *
192 ******************************************************************************/
193static int btif_hf_idx_by_bdaddr(bt_bdaddr_t* bd_addr) {
194 int i;
195 for (i = 0; i < btif_max_hf_clients; ++i) {
196 if ((bdcmp(bd_addr->address, btif_hf_cb[i].connected_bda.address) == 0))
197 return i;
198 }
199 return BTIF_HF_INVALID_IDX;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700200}
201
202/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700203 *
204 * Function callstate_to_callsetup
205 *
206 * Description Converts HAL call state to BTA call setup indicator value
207 *
208 * Returns BTA call indicator value
209 *
210 ******************************************************************************/
211static uint8_t callstate_to_callsetup(bthf_call_state_t call_state) {
212 uint8_t call_setup = 0;
213 if (call_state == BTHF_CALL_STATE_INCOMING) call_setup = 1;
214 if (call_state == BTHF_CALL_STATE_DIALING) call_setup = 2;
215 if (call_state == BTHF_CALL_STATE_ALERTING) call_setup = 3;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800216
Myles Watson6bd442f2016-10-19 09:50:22 -0700217 return call_setup;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800218}
219
220/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700221 *
222 * Function send_at_result
223 *
224 * Description Send AT result code (OK/ERROR)
225 *
226 * Returns void
227 *
228 ******************************************************************************/
229static void send_at_result(uint8_t ok_flag, uint16_t errcode, int idx) {
230 tBTA_AG_RES_DATA ag_res;
231 memset(&ag_res, 0, sizeof(ag_res));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800232
Myles Watson6bd442f2016-10-19 09:50:22 -0700233 ag_res.ok_flag = ok_flag;
234 if (ok_flag == BTA_AG_OK_ERROR) {
235 ag_res.errcode = errcode;
236 }
237
238 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
239}
240
241/*******************************************************************************
242 *
243 * Function send_indicator_update
244 *
245 * Description Send indicator update (CIEV)
246 *
247 * Returns void
248 *
249 ******************************************************************************/
250static void send_indicator_update(uint16_t indicator, uint16_t value) {
251 tBTA_AG_RES_DATA ag_res;
252
253 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
254 ag_res.ind.id = indicator;
255 ag_res.ind.value = value;
256
257 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
258}
259
260void clear_phone_state_multihf(int idx) {
261 btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE;
262 btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0;
263}
264
265/*******************************************************************************
266 *
267 * Function btif_hf_latest_connected_idx
268 *
269 * Description Returns idx for latest connected HF
270 *
271 * Returns int
272 *
273 ******************************************************************************/
274static int btif_hf_latest_connected_idx() {
275 struct timespec now, conn_time_delta;
276 int latest_conn_idx = BTIF_HF_INVALID_IDX, i;
277
278 clock_gettime(CLOCK_MONOTONIC, &now);
279 conn_time_delta.tv_sec = now.tv_sec;
280
281 for (i = 0; i < btif_max_hf_clients; i++) {
282 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
283 if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec) <
284 conn_time_delta.tv_sec) {
285 conn_time_delta.tv_sec =
286 now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec;
287 latest_conn_idx = i;
288 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800289 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700290 }
291 return latest_conn_idx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800292}
293
294/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700295 *
296 * Function btif_hf_check_if_slc_connected
297 *
298 * Description Returns BT_STATUS_SUCCESS if SLC is up for any HF
299 *
300 * Returns bt_status_t
301 *
302 ******************************************************************************/
303static bt_status_t btif_hf_check_if_slc_connected() {
304 if (bt_hf_callbacks == NULL) {
305 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__);
306 return BT_STATUS_NOT_READY;
307 } else {
308 int i;
309 for (i = 0; i < btif_max_hf_clients; i++) {
310 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
311 BTIF_TRACE_EVENT("BTHF: %s: slc connected for idx = %d", __func__, i);
312 return BT_STATUS_SUCCESS;
313 }
314 }
315 BTIF_TRACE_WARNING("BTHF: %s: No SLC connection up", __func__);
316 return BT_STATUS_NOT_READY;
317 }
318}
319
320/*****************************************************************************
321 * Section name (Group of functions)
322 ****************************************************************************/
323
324/*****************************************************************************
325 *
326 * btif hf api functions (no context switch)
327 *
328 ****************************************************************************/
329
330/*******************************************************************************
331 *
332 * Function btif_hf_upstreams_evt
333 *
334 * Description Executes HF UPSTREAMS events in btif context
335 *
336 * Returns void
337 *
338 ******************************************************************************/
339static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
340 tBTA_AG* p_data = (tBTA_AG*)p_param;
341 bdstr_t bdstr;
342 int idx = p_data->hdr.handle - 1;
343
344 BTIF_TRACE_DEBUG("%s: event=%s", __func__, dump_hf_event(event));
345
346 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
347 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
348 return;
349 }
350
351 switch (event) {
352 case BTA_AG_ENABLE_EVT:
353 case BTA_AG_DISABLE_EVT:
354 break;
355
356 case BTA_AG_REGISTER_EVT:
357 btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
358 BTIF_TRACE_DEBUG(
359 "%s: BTA_AG_REGISTER_EVT,"
360 "btif_hf_cb.handle = %d",
361 __func__, btif_hf_cb[idx].handle);
362 break;
363
364 case BTA_AG_OPEN_EVT:
365 if (p_data->open.status == BTA_AG_SUCCESS) {
366 bdcpy(btif_hf_cb[idx].connected_bda.address, p_data->open.bd_addr);
367 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
368 btif_hf_cb[idx].peer_feat = 0;
369 clear_phone_state_multihf(idx);
370 } else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING) {
371 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
372 } else {
373 BTIF_TRACE_WARNING(
374 "%s: AG open failed, but another device connected. status=%d "
375 "state=%d connected device=%s",
376 __func__, p_data->open.status, btif_hf_cb[idx].state,
377 bdaddr_to_string(&btif_hf_cb[idx].connected_bda, bdstr,
378 sizeof(bdstr)));
379 break;
380 }
381
382 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
383 &btif_hf_cb[idx].connected_bda);
384
385 if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
386 bdsetany(btif_hf_cb[idx].connected_bda.address);
387
388 if (p_data->open.status != BTA_AG_SUCCESS) btif_queue_advance();
389 break;
390
391 case BTA_AG_CLOSE_EVT:
392 btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
393 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
394 BTIF_TRACE_DEBUG(
395 "%s: BTA_AG_CLOSE_EVT,"
396 "idx = %d, btif_hf_cb.handle = %d",
397 __func__, idx, btif_hf_cb[idx].handle);
398 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
399 &btif_hf_cb[idx].connected_bda);
400 bdsetany(btif_hf_cb[idx].connected_bda.address);
401 btif_hf_cb[idx].peer_feat = 0;
402 clear_phone_state_multihf(idx);
403 hf_idx = btif_hf_latest_connected_idx();
404 /* If AG_OPEN was received but SLC was not setup in a specified time (10
405 *seconds),
406 ** then AG_CLOSE may be received. We need to advance the queue here
407 */
408 btif_queue_advance();
409 break;
410
411 case BTA_AG_CONN_EVT:
412 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[idx].connected_timestamp);
413 BTIF_TRACE_DEBUG("%s: BTA_AG_CONN_EVT, idx = %d ", __func__, idx);
414 btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
415 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
416 hf_idx = btif_hf_latest_connected_idx();
417
418 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
419 &btif_hf_cb[idx].connected_bda);
420 btif_queue_advance();
421 break;
422
423 case BTA_AG_AUDIO_OPEN_EVT:
424 hf_idx = idx;
425 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
426 &btif_hf_cb[idx].connected_bda);
427 break;
428
429 case BTA_AG_AUDIO_CLOSE_EVT:
430 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
431 &btif_hf_cb[idx].connected_bda);
432 break;
433
434 /* BTA auto-responds, silently discard */
435 case BTA_AG_SPK_EVT:
436 case BTA_AG_MIC_EVT:
437 HAL_CBACK(bt_hf_callbacks, volume_cmd_cb,
438 (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK
439 : BTHF_VOLUME_TYPE_MIC,
440 p_data->val.num, &btif_hf_cb[idx].connected_bda);
441 break;
442
443 case BTA_AG_AT_A_EVT:
444 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
445 hf_idx = idx;
446 else
447 BTIF_TRACE_DEBUG("Donot set hf_idx for ATA since already in a call");
448
449 HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
450 &btif_hf_cb[idx].connected_bda);
451 break;
452
453 /* Java needs to send OK/ERROR for these commands */
454 case BTA_AG_AT_BLDN_EVT:
455 case BTA_AG_AT_D_EVT:
456 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
457 hf_idx = idx;
458 else
459 BTIF_TRACE_DEBUG("Donot set hf_idx for BLDN/D since already in a call");
460
461 HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
462 (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
463 &btif_hf_cb[idx].connected_bda);
464 break;
465
466 case BTA_AG_AT_CHUP_EVT:
467 HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
468 &btif_hf_cb[idx].connected_bda);
469 break;
470
471 case BTA_AG_AT_CIND_EVT:
472 HAL_CBACK(bt_hf_callbacks, cind_cmd_cb, &btif_hf_cb[idx].connected_bda);
473 break;
474
475 case BTA_AG_AT_VTS_EVT:
476 HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
477 &btif_hf_cb[idx].connected_bda);
478 break;
479
480 case BTA_AG_AT_BVRA_EVT:
481 HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
482 (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED
483 : BTHF_VR_STATE_STOPPED,
484 &btif_hf_cb[idx].connected_bda);
485 break;
486
487 case BTA_AG_AT_NREC_EVT:
488 HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
489 (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
490 &btif_hf_cb[idx].connected_bda);
491 break;
492
493 /* TODO: Add a callback for CBC */
494 case BTA_AG_AT_CBC_EVT:
495 break;
496
497 case BTA_AG_AT_CKPD_EVT:
498 HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
499 &btif_hf_cb[idx].connected_bda);
500 break;
501
Myles Watson6bd442f2016-10-19 09:50:22 -0700502 case BTA_AG_WBS_EVT:
503 BTIF_TRACE_DEBUG(
504 "BTA_AG_WBS_EVT Set codec status %d codec %d 1=CVSD 2=MSBC",
505 p_data->val.hdr.status, p_data->val.num);
506 if (p_data->val.num == BTA_AG_CODEC_CVSD) {
507 HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NO,
508 &btif_hf_cb[idx].connected_bda);
509 } else if (p_data->val.num == BTA_AG_CODEC_MSBC) {
510 HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_YES,
511 &btif_hf_cb[idx].connected_bda);
512 } else {
513 HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NONE,
514 &btif_hf_cb[idx].connected_bda);
515 }
516 break;
Myles Watson3e634d62017-02-09 16:26:34 -0800517
Myles Watson6bd442f2016-10-19 09:50:22 -0700518 /* Java needs to send OK/ERROR for these commands */
519 case BTA_AG_AT_CHLD_EVT:
520 HAL_CBACK(bt_hf_callbacks, chld_cmd_cb,
521 (bthf_chld_type_t)atoi(p_data->val.str),
522 &btif_hf_cb[idx].connected_bda);
523 break;
524
525 case BTA_AG_AT_CLCC_EVT:
526 HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb, &btif_hf_cb[idx].connected_bda);
527 break;
528
529 case BTA_AG_AT_COPS_EVT:
530 HAL_CBACK(bt_hf_callbacks, cops_cmd_cb, &btif_hf_cb[idx].connected_bda);
531 break;
532
533 case BTA_AG_AT_UNAT_EVT:
534 HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
535 &btif_hf_cb[idx].connected_bda);
536 break;
537
538 case BTA_AG_AT_CNUM_EVT:
539 HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb, &btif_hf_cb[idx].connected_bda);
540 break;
541
542 /* TODO: Some of these commands may need to be sent to app. For now respond
543 * with error */
544 case BTA_AG_AT_BINP_EVT:
545 case BTA_AG_AT_BTRH_EVT:
546 send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx);
547 break;
548 case BTA_AG_AT_BAC_EVT:
549 BTIF_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num);
Jack Hefe695a52017-05-07 17:27:47 -0700550 /* If the peer supports mSBC and the BTIF preferred codec is also mSBC,
Myles Watson6bd442f2016-10-19 09:50:22 -0700551 then
552 we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC
553 at the time
554 of SCO connection establishment */
555 if ((btif_conf_hf_force_wbs == true) &&
556 (p_data->val.num & BTA_AG_CODEC_MSBC)) {
Jack Hefe695a52017-05-07 17:27:47 -0700557 BTIF_TRACE_EVENT("%s: btif_hf override-Preferred Codec to MSBC",
Myles Watson6bd442f2016-10-19 09:50:22 -0700558 __func__);
559 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_MSBC);
560 } else {
561 BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to CVSD",
562 __func__);
563 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_CVSD);
564 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700565 break;
566 case BTA_AG_AT_BCS_EVT:
Jack Hefe695a52017-05-07 17:27:47 -0700567 BTIF_TRACE_DEBUG("%s: AG final selected codec is 0x%02x 1=CVSD 2=MSBC",
568 __func__, p_data->val.num);
569 /* No BTHF_WBS_NONE case, because HF1.6 supported device can send BCS */
570 /* Only CVSD is considered narrow band speech */
Myles Watson6bd442f2016-10-19 09:50:22 -0700571 HAL_CBACK(
572 bt_hf_callbacks, wbs_cb,
Jack Hefe695a52017-05-07 17:27:47 -0700573 (p_data->val.num == BTA_AG_CODEC_CVSD) ? BTHF_WBS_NO : BTHF_WBS_YES,
Myles Watson6bd442f2016-10-19 09:50:22 -0700574 &btif_hf_cb[idx].connected_bda);
575 break;
576
577 case BTA_AG_AT_BIND_EVT:
578 if (p_data->val.hdr.status == BTA_AG_SUCCESS) {
579 HAL_CBACK(bt_hf_callbacks, bind_cb, p_data->val.str,
580 &btif_hf_cb[idx].connected_bda);
581 }
582 break;
583
584 case BTA_AG_AT_BIEV_EVT:
585 if (p_data->val.hdr.status == BTA_AG_SUCCESS) {
586 HAL_CBACK(bt_hf_callbacks, biev_cb,
587 (bthf_hf_ind_type_t)p_data->val.lidx, (int)p_data->val.num,
588 &btif_hf_cb[idx].connected_bda);
589 }
590 break;
591 default:
592 BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
593 break;
594 }
595}
596
597/*******************************************************************************
598 *
599 * Function bte_hf_evt
600 *
601 * Description Switches context from BTE to BTIF for all HF events
602 *
603 * Returns void
604 *
605 ******************************************************************************/
606
607static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG* p_data) {
608 bt_status_t status;
609 int param_len = 0;
610
611 /* TODO: BTA sends the union members and not tBTA_AG. If using
612 * param_len=sizeof(tBTA_AG), we get a crash on memcpy */
613 if (BTA_AG_REGISTER_EVT == event)
614 param_len = sizeof(tBTA_AG_REGISTER);
615 else if (BTA_AG_OPEN_EVT == event)
616 param_len = sizeof(tBTA_AG_OPEN);
617 else if (BTA_AG_CONN_EVT == event)
618 param_len = sizeof(tBTA_AG_CONN);
619 else if ((BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) ||
620 (BTA_AG_AUDIO_CLOSE_EVT == event))
621 param_len = sizeof(tBTA_AG_HDR);
622 else if (p_data)
623 param_len = sizeof(tBTA_AG_VAL);
624
625 /* switch context to btif task context (copy full union size for convenience)
626 */
627 status = btif_transfer_context(btif_hf_upstreams_evt, (uint16_t)event,
628 (char*)p_data, param_len, NULL);
629
630 /* catch any failed context transfers */
631 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
632}
633
634/*******************************************************************************
635 *
636 * Function btif_in_hf_generic_evt
637 *
638 * Description Processes generic events to be sent to JNI that are not
Myles Watsonf4548162016-10-19 09:53:56 -0700639 * triggered from the BTA.
Myles Watson6bd442f2016-10-19 09:50:22 -0700640 * Always runs in BTIF context
641 *
642 * Returns void
643 *
644 ******************************************************************************/
645static void btif_in_hf_generic_evt(uint16_t event, char* p_param) {
646 int idx = btif_hf_idx_by_bdaddr((bt_bdaddr_t*)p_param);
647
648 BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
649
650 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
651 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
652 return;
653 }
654
655 switch (event) {
656 case BTIF_HFP_CB_AUDIO_CONNECTING: {
657 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
658 &btif_hf_cb[idx].connected_bda);
659 } break;
660 default: {
661 BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
662 } break;
663 }
664}
665
Jack He7a9892c2017-02-02 17:42:40 -0800666static bool inband_ringing_property_enabled() {
667 char inband_ringing_flag[PROPERTY_VALUE_MAX] = {0};
668 osi_property_get("persist.bluetooth.enableinbandringing", inband_ringing_flag,
669 "false");
670 if (strncmp(inband_ringing_flag, "true", 4) == 0) {
671 BTIF_TRACE_DEBUG("%s: In-band ringing enabled by property", __func__);
672 return true;
673 }
674 return false;
675}
676
Myles Watson6bd442f2016-10-19 09:50:22 -0700677/*******************************************************************************
678 *
679 * Function btif_hf_init
680 *
681 * Description initializes the hf interface
682 *
683 * Returns bt_status_t
684 *
685 ******************************************************************************/
Jack He7a9892c2017-02-02 17:42:40 -0800686static bt_status_t init(bthf_callbacks_t* callbacks, int max_hf_clients,
687 bool inband_ringing_supported) {
688 bool inband_ringing_property_enable = inband_ringing_property_enabled();
689 if (inband_ringing_supported && inband_ringing_property_enable) {
690 btif_hf_features |= BTA_AG_FEAT_INBAND;
691 } else {
692 btif_hf_features &= ~BTA_AG_FEAT_INBAND;
693 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700694 btif_max_hf_clients = max_hf_clients;
Jack He7a9892c2017-02-02 17:42:40 -0800695 BTIF_TRACE_DEBUG(
696 "%s: btif_hf_features=%zu, max_hf_clients=%d, "
697 "inband_ringing=[supported=%d, enabled=%d]",
698 __func__, btif_hf_features, btif_max_hf_clients, inband_ringing_supported,
699 inband_ringing_property_enable);
Myles Watson6bd442f2016-10-19 09:50:22 -0700700 bt_hf_callbacks = callbacks;
701 memset(&btif_hf_cb, 0, sizeof(btif_hf_cb));
702
703/* Invoke the enable service API to the core to set the appropriate service_id
704 * Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled
705 * (phone)
706 * othwerwise only HSP is enabled (tablet)
707*/
708#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
709 btif_enable_service(BTA_HFP_SERVICE_ID);
710#else
711 btif_enable_service(BTA_HSP_SERVICE_ID);
712#endif
713
714 for (int i = 0; i < btif_max_hf_clients; i++) clear_phone_state_multihf(i);
715
716 return BT_STATUS_SUCCESS;
717}
718
719/*******************************************************************************
720 *
721 * Function connect
722 *
723 * Description connect to headset
724 *
725 * Returns bt_status_t
726 *
727 ******************************************************************************/
728static bt_status_t connect_int(bt_bdaddr_t* bd_addr, uint16_t uuid) {
729 CHECK_BTHF_INIT();
730 int i;
731 for (i = 0; i < btif_max_hf_clients;) {
732 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
733 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)))
734 i++;
735 else
736 break;
737 }
738
739 if (i == btif_max_hf_clients) return BT_STATUS_BUSY;
740
741 if (!is_connected(bd_addr)) {
742 btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
743 bdcpy(btif_hf_cb[i].connected_bda.address, bd_addr->address);
744
745 BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda.address,
746 BTIF_HF_SECURITY, BTIF_HF_SERVICES);
747 return BT_STATUS_SUCCESS;
748 }
749
750 return BT_STATUS_BUSY;
751}
752
753static bt_status_t connect(bt_bdaddr_t* bd_addr) {
754 CHECK_BTHF_INIT();
755 return btif_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_int);
756}
757
758/*******************************************************************************
759 *
760 * Function disconnect
761 *
762 * Description disconnect from headset
763 *
764 * Returns bt_status_t
765 *
766 ******************************************************************************/
767static bt_status_t disconnect(bt_bdaddr_t* bd_addr) {
768 CHECK_BTHF_INIT();
769
770 int idx = btif_hf_idx_by_bdaddr(bd_addr);
771
772 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
773 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
774 return BT_STATUS_FAIL;
775 }
776
777 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
778 BTA_AgClose(btif_hf_cb[idx].handle);
779 return BT_STATUS_SUCCESS;
780 }
781
782 return BT_STATUS_FAIL;
783}
784
785/*******************************************************************************
786 *
787 * Function connect_audio
788 *
789 * Description create an audio connection
790 *
791 * Returns bt_status_t
792 *
793 ******************************************************************************/
794static bt_status_t connect_audio(bt_bdaddr_t* bd_addr) {
795 CHECK_BTHF_INIT();
796
797 int idx = btif_hf_idx_by_bdaddr(bd_addr);
798
799 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
800 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
801 return BT_STATUS_FAIL;
802 }
803
804 /* Check if SLC is connected */
805 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
806 return BT_STATUS_NOT_READY;
807
808 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
809 BTA_AgAudioOpen(btif_hf_cb[idx].handle);
810
811 /* Inform the application that the audio connection has been initiated
812 * successfully */
813 btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING,
814 (char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
815 return BT_STATUS_SUCCESS;
816 }
817
818 return BT_STATUS_FAIL;
819}
820
821/*******************************************************************************
822 *
823 * Function disconnect_audio
824 *
825 * Description close the audio connection
826 *
827 * Returns bt_status_t
828 *
829 ******************************************************************************/
830static bt_status_t disconnect_audio(bt_bdaddr_t* bd_addr) {
831 CHECK_BTHF_INIT();
832
833 int idx = btif_hf_idx_by_bdaddr(bd_addr);
834
835 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
836 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
837 return BT_STATUS_FAIL;
838 }
839
840 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
841 BTA_AgAudioClose(btif_hf_cb[idx].handle);
842 return BT_STATUS_SUCCESS;
843 }
844
845 return BT_STATUS_FAIL;
846}
847
848/*******************************************************************************
849 *
850 * Function start_voice_recognition
851 *
852 * Description start voice recognition
853 *
854 * Returns bt_status_t
855 *
856 ******************************************************************************/
857static bt_status_t start_voice_recognition(bt_bdaddr_t* bd_addr) {
858 CHECK_BTHF_INIT();
859
860 int idx = btif_hf_idx_by_bdaddr(bd_addr);
861
862 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
863 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
864 return BT_STATUS_FAIL;
865 }
866
867 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
868 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) {
869 tBTA_AG_RES_DATA ag_res;
870 memset(&ag_res, 0, sizeof(ag_res));
871 ag_res.state = 1;
872 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
873
874 return BT_STATUS_SUCCESS;
875 } else {
876 return BT_STATUS_UNSUPPORTED;
877 }
878 }
879
880 return BT_STATUS_NOT_READY;
881}
882
883/*******************************************************************************
884 *
885 * Function stop_voice_recognition
886 *
887 * Description stop voice recognition
888 *
889 * Returns bt_status_t
890 *
891 ******************************************************************************/
892static bt_status_t stop_voice_recognition(bt_bdaddr_t* bd_addr) {
893 CHECK_BTHF_INIT();
894
895 int idx = btif_hf_idx_by_bdaddr(bd_addr);
896
897 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
898 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
899 return BT_STATUS_FAIL;
900 }
901
902 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
903 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) {
904 tBTA_AG_RES_DATA ag_res;
905 memset(&ag_res, 0, sizeof(ag_res));
906 ag_res.state = 0;
907 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
908
909 return BT_STATUS_SUCCESS;
910 } else {
911 return BT_STATUS_UNSUPPORTED;
912 }
913 }
914
915 return BT_STATUS_NOT_READY;
916}
917
918/*******************************************************************************
919 *
920 * Function volume_control
921 *
922 * Description volume control
923 *
924 * Returns bt_status_t
925 *
926 ******************************************************************************/
927static bt_status_t volume_control(bthf_volume_type_t type, int volume,
928 bt_bdaddr_t* bd_addr) {
929 CHECK_BTHF_INIT();
930
931 int idx = btif_hf_idx_by_bdaddr(bd_addr);
932
933 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
934 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
935 return BT_STATUS_FAIL;
936 }
937
938 tBTA_AG_RES_DATA ag_res;
939 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
940 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
941 ag_res.num = volume;
942 BTA_AgResult(
943 btif_hf_cb[idx].handle,
944 (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
945 &ag_res);
946 return BT_STATUS_SUCCESS;
947 }
948
949 return BT_STATUS_FAIL;
950}
951
952/*******************************************************************************
953 *
954 * Function device_status_notification
955 *
956 * Description Combined device status change notification
957 *
958 * Returns bt_status_t
959 *
960 ******************************************************************************/
961static bt_status_t device_status_notification(bthf_network_state_t ntk_state,
962 bthf_service_type_t svc_type,
963 int signal, int batt_chg) {
964 CHECK_BTHF_INIT();
965
966 if (is_connected(NULL)) {
967 /* send all indicators to BTA.
968 ** BTA will make sure no duplicates are sent out
969 */
970 send_indicator_update(BTA_AG_IND_SERVICE,
971 (ntk_state == BTHF_NETWORK_STATE_AVAILABLE) ? 1 : 0);
972 send_indicator_update(BTA_AG_IND_ROAM,
973 (svc_type == BTHF_SERVICE_TYPE_HOME) ? 0 : 1);
974 send_indicator_update(BTA_AG_IND_SIGNAL, signal);
975 send_indicator_update(BTA_AG_IND_BATTCHG, batt_chg);
976 return BT_STATUS_SUCCESS;
977 }
978
979 return BT_STATUS_SUCCESS;
980}
981
982/*******************************************************************************
983 *
984 * Function cops_response
985 *
986 * Description Response for COPS command
987 *
988 * Returns bt_status_t
989 *
990 ******************************************************************************/
991static bt_status_t cops_response(const char* cops, bt_bdaddr_t* bd_addr) {
992 CHECK_BTHF_INIT();
993
994 int idx = btif_hf_idx_by_bdaddr(bd_addr);
995
996 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
997 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
998 return BT_STATUS_FAIL;
999 }
1000
1001 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001002 tBTA_AG_RES_DATA ag_res;
1003
Myles Watson6bd442f2016-10-19 09:50:22 -07001004 /* Format the response */
1005 snprintf(ag_res.str, sizeof(ag_res.str), "0,0,\"%.16s\"", cops);
1006 ag_res.ok_flag = BTA_AG_OK_DONE;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001007
Myles Watson6bd442f2016-10-19 09:50:22 -07001008 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
1009 return BT_STATUS_SUCCESS;
1010 }
1011 return BT_STATUS_FAIL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001012}
1013
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001014/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001015 *
1016 * Function cind_response
1017 *
1018 * Description Response for CIND command
1019 *
1020 * Returns bt_status_t
1021 *
1022 ******************************************************************************/
1023static bt_status_t cind_response(int svc, int num_active, int num_held,
1024 bthf_call_state_t call_setup_state, int signal,
1025 int roam, int batt_chg, bt_bdaddr_t* bd_addr) {
1026 CHECK_BTHF_INIT();
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001027
Myles Watson6bd442f2016-10-19 09:50:22 -07001028 int idx = btif_hf_idx_by_bdaddr(bd_addr);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001029
Myles Watson6bd442f2016-10-19 09:50:22 -07001030 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1031 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1032 return BT_STATUS_FAIL;
1033 }
1034
1035 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1036 tBTA_AG_RES_DATA ag_res;
1037
1038 memset(&ag_res, 0, sizeof(ag_res));
1039 /* per the errata 2043, call=1 implies atleast one call is in progress
1040 *(active/held)
1041 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1042 **/
1043 snprintf(
1044 ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d,%d,%d",
1045 (num_active + num_held) ? 1 : 0, /* Call state */
1046 callstate_to_callsetup(call_setup_state), /* Callsetup state */
1047 svc, /* network service */
1048 signal, /* Signal strength */
1049 roam, /* Roaming indicator */
1050 batt_chg, /* Battery level */
1051 ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
1052
1053 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
1054
1055 return BT_STATUS_SUCCESS;
1056 }
1057
1058 return BT_STATUS_FAIL;
1059}
1060
1061/*******************************************************************************
1062 *
1063 * Function bind_response
1064 *
1065 * Description Send +BIND response
1066 *
1067 * Returns bt_status_t
1068 *
1069 ******************************************************************************/
1070static bt_status_t bind_response(bthf_hf_ind_type_t ind_id,
1071 bthf_hf_ind_status_t ind_status,
1072 bt_bdaddr_t* bd_addr) {
1073 CHECK_BTHF_INIT();
1074
1075 int index = btif_hf_idx_by_bdaddr(bd_addr);
1076 if (!is_connected(bd_addr) || index == BTIF_HF_INVALID_IDX)
1077 return BT_STATUS_FAIL;
1078
1079 tBTA_AG_RES_DATA ag_res;
1080 memset(&ag_res, 0, sizeof(ag_res));
1081 ag_res.ind.id = ind_id;
1082 ag_res.ind.on_demand = (ind_status == BTHF_HF_IND_ENABLED);
1083
1084 BTA_AgResult(btif_hf_cb[index].handle, BTA_AG_BIND_RES, &ag_res);
1085 return BT_STATUS_SUCCESS;
1086}
1087
Zach Johnsonacdc11c2017-04-18 21:03:07 -07001088static bt_status_t set_sco_allowed(bool value) {
1089 CHECK_BTHF_INIT();
1090
1091 BTA_AgSetScoAllowed(value);
1092 return BT_STATUS_SUCCESS;
1093}
1094
Myles Watson6bd442f2016-10-19 09:50:22 -07001095/*******************************************************************************
1096 *
1097 * Function formatted_at_response
1098 *
1099 * Description Pre-formatted AT response, typically in response to unknown
Myles Watsonf4548162016-10-19 09:53:56 -07001100 * AT cmd
Myles Watson6bd442f2016-10-19 09:50:22 -07001101 *
1102 * Returns bt_status_t
1103 *
1104 ******************************************************************************/
1105static bt_status_t formatted_at_response(const char* rsp,
1106 bt_bdaddr_t* bd_addr) {
1107 CHECK_BTHF_INIT();
1108 tBTA_AG_RES_DATA ag_res;
1109 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1110
1111 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1112 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1113 return BT_STATUS_FAIL;
1114 }
1115
1116 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1117 /* Format the response and send */
1118 memset(&ag_res, 0, sizeof(ag_res));
1119 strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
1120 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
1121
1122 return BT_STATUS_SUCCESS;
1123 }
1124
1125 return BT_STATUS_FAIL;
1126}
1127
1128/*******************************************************************************
1129 *
1130 * Function at_response
1131 *
1132 * Description ok/error response
1133 *
1134 * Returns bt_status_t
1135 *
1136 ******************************************************************************/
1137static bt_status_t at_response(bthf_at_response_t response_code, int error_code,
1138 bt_bdaddr_t* bd_addr) {
1139 CHECK_BTHF_INIT();
1140
1141 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1142
1143 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1144 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1145 return BT_STATUS_FAIL;
1146 }
1147
1148 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1149 send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
1150 : BTA_AG_OK_ERROR,
1151 error_code, idx);
1152 return BT_STATUS_SUCCESS;
1153 }
1154
1155 return BT_STATUS_FAIL;
1156}
1157
1158/*******************************************************************************
1159 *
1160 * Function clcc_response
1161 *
1162 * Description response for CLCC command
1163 * Can be iteratively called for each call index. Call index
1164 * of 0 will be treated as NULL termination (Completes
Myles Watsonf4548162016-10-19 09:53:56 -07001165 * response)
Myles Watson6bd442f2016-10-19 09:50:22 -07001166 *
1167 * Returns bt_status_t
1168 *
1169 ******************************************************************************/
1170static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
1171 bthf_call_state_t state, bthf_call_mode_t mode,
1172 bthf_call_mpty_type_t mpty, const char* number,
1173 bthf_call_addrtype_t type,
1174 bt_bdaddr_t* bd_addr) {
1175 CHECK_BTHF_INIT();
1176
1177 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1178
1179 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1180 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1181 return BT_STATUS_FAIL;
1182 }
1183
1184 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1185 tBTA_AG_RES_DATA ag_res;
Myles Watson6bd442f2016-10-19 09:50:22 -07001186 memset(&ag_res, 0, sizeof(ag_res));
1187
1188 /* Format the response */
1189 if (index == 0) {
1190 ag_res.ok_flag = BTA_AG_OK_DONE;
1191 } else {
1192 BTIF_TRACE_EVENT(
1193 "clcc_response: [%d] dir %d state %d mode %d number = %s type = %d",
1194 index, dir, state, mode, number, type);
Myles Watson90088882016-11-15 16:33:22 -08001195 int res_strlen =
1196 snprintf(ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d", index, dir,
1197 state, mode, mpty);
Myles Watson6bd442f2016-10-19 09:50:22 -07001198
1199 if (number) {
Satish Kodishalac75a71d2016-06-22 14:22:41 +05301200 size_t rem_bytes = sizeof(ag_res.str) - res_strlen;
1201 char dialnum[sizeof(ag_res.str)];
1202 size_t newidx = 0;
1203 if (type == BTHF_CALL_ADDRTYPE_INTERNATIONAL && *number != '+') {
1204 dialnum[newidx++] = '+';
1205 }
1206 for (size_t i = 0; number[i] != 0; i++) {
1207 if (utl_isdialchar(number[i])) {
1208 dialnum[newidx++] = number[i];
1209 }
1210 }
1211 dialnum[newidx] = 0;
1212 snprintf(&ag_res.str[res_strlen], rem_bytes, ",\"%s\",%d", dialnum,
1213 type);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001214 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001215 }
1216 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
1217
1218 return BT_STATUS_SUCCESS;
1219 }
1220
1221 return BT_STATUS_FAIL;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001222}
1223
1224/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001225 *
1226 * Function phone_state_change
1227 *
1228 * Description notify of a call state change
1229 * number & type: valid only for incoming & waiting call
1230 *
1231 * Returns bt_status_t
1232 *
1233 ******************************************************************************/
1234
1235static bt_status_t phone_state_change(int num_active, int num_held,
1236 bthf_call_state_t call_setup_state,
1237 const char* number,
1238 bthf_call_addrtype_t type) {
1239 tBTA_AG_RES res = 0xff;
1240 tBTA_AG_RES_DATA ag_res;
1241 bt_status_t status = BT_STATUS_SUCCESS;
1242 bool activeCallUpdated = false;
1243 int idx, i;
1244
1245 /* hf_idx is index of connected HS that sent ATA/BLDN,
1246 otherwise index of latest connected HS */
1247 if (hf_idx != BTIF_HF_INVALID_IDX)
1248 idx = hf_idx;
1249 else
1250 idx = btif_hf_latest_connected_idx();
1251
1252 BTIF_TRACE_DEBUG("phone_state_change: idx = %d", idx);
1253
1254 /* Check if SLC is connected */
1255 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
1256 return BT_STATUS_NOT_READY;
1257
1258 BTIF_TRACE_DEBUG(
1259 "phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"
1260 " call_setup=%s [prev: %s]",
1261 num_active, btif_hf_cb[idx].num_active, num_held,
1262 btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
1263 dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
1264
1265 /* if all indicators are 0, send end call and return */
1266 if (num_active == 0 && num_held == 0 &&
1267 call_setup_state == BTHF_CALL_STATE_IDLE) {
1268 BTIF_TRACE_DEBUG("%s: Phone on hook", __func__);
1269
1270 /* record call termination timestamp if there was an active/held call or
1271 callsetup state > BTHF_CALL_STATE_IDLE */
1272 if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE) ||
1273 (btif_hf_cb[idx].num_active) || (btif_hf_cb[idx].num_held)) {
1274 BTIF_TRACE_DEBUG("%s: Record call termination timestamp", __func__);
1275 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001276 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001277 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
1278 hf_idx = BTIF_HF_INVALID_IDX;
1279
1280 /* if held call was present, reset that as well */
1281 if (btif_hf_cb[idx].num_held) send_indicator_update(BTA_AG_IND_CALLHELD, 0);
1282
1283 goto update_call_states;
1284 }
1285
1286 /* active state can change when:
1287 ** 1. an outgoing/incoming call was answered
1288 ** 2. an held was resumed
1289 ** 3. without callsetup notifications, call became active
1290 ** (3) can happen if call is active and a headset connects to us
1291 **
1292 ** In the case of (3), we will have to notify the stack of an active
1293 ** call, instead of sending an indicator update. This will also
1294 ** force the SCO to be setup. Handle this special case here prior to
1295 ** call setup handling
1296 */
1297 if (((num_active + num_held) > 0) && (btif_hf_cb[idx].num_active == 0) &&
1298 (btif_hf_cb[idx].num_held == 0) &&
1299 (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE)) {
1300 BTIF_TRACE_DEBUG(
1301 "%s: Active/Held call notification received without call setup update",
1302 __func__);
1303
1304 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1305 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
1306 /* Addition call setup with the Active call
1307 ** CIND response should have been updated.
Jack Hefe695a52017-05-07 17:27:47 -07001308 ** just open SCO connection.
Myles Watson6bd442f2016-10-19 09:50:22 -07001309 */
1310 if (call_setup_state != BTHF_CALL_STATE_IDLE)
1311 res = BTA_AG_MULTI_CALL_RES;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001312 else
Myles Watson6bd442f2016-10-19 09:50:22 -07001313 res = BTA_AG_OUT_CALL_CONN_RES;
1314 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
1315 activeCallUpdated = true;
1316 }
1317
1318 /* Ringing call changed? */
1319 if (call_setup_state != btif_hf_cb[idx].call_setup_state) {
1320 BTIF_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s", __func__,
1321 dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
1322 dump_hf_call_state(call_setup_state));
1323 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1324
1325 switch (call_setup_state) {
1326 case BTHF_CALL_STATE_IDLE: {
1327 switch (btif_hf_cb[idx].call_setup_state) {
1328 case BTHF_CALL_STATE_INCOMING:
1329 if (num_active > btif_hf_cb[idx].num_active) {
1330 res = BTA_AG_IN_CALL_CONN_RES;
1331 ag_res.audio_handle = btif_hf_cb[idx].handle;
1332 } else if (num_held > btif_hf_cb[idx].num_held)
1333 res = BTA_AG_IN_CALL_HELD_RES;
1334 else
1335 res = BTA_AG_CALL_CANCEL_RES;
1336 break;
1337 case BTHF_CALL_STATE_DIALING:
1338 case BTHF_CALL_STATE_ALERTING:
1339 if (num_active > btif_hf_cb[idx].num_active) {
1340 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
1341 res = BTA_AG_OUT_CALL_CONN_RES;
1342 } else
1343 res = BTA_AG_CALL_CANCEL_RES;
1344 break;
1345 default:
1346 BTIF_TRACE_ERROR("%s: Incorrect Call setup state transition",
1347 __func__);
1348 status = BT_STATUS_PARM_INVALID;
1349 break;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001350 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001351 } break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001352
Myles Watson6bd442f2016-10-19 09:50:22 -07001353 case BTHF_CALL_STATE_INCOMING:
Jack He7a9892c2017-02-02 17:42:40 -08001354 if (num_active || num_held) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001355 res = BTA_AG_CALL_WAIT_RES;
Jack He7a9892c2017-02-02 17:42:40 -08001356 } else {
Myles Watson6bd442f2016-10-19 09:50:22 -07001357 res = BTA_AG_IN_CALL_RES;
Jack He7a9892c2017-02-02 17:42:40 -08001358 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001359 if (number) {
1360 int xx = 0;
1361 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+'))
1362 xx = snprintf(ag_res.str, sizeof(ag_res.str), "\"+%s\"", number);
1363 else
1364 xx = snprintf(ag_res.str, sizeof(ag_res.str), "\"%s\"", number);
1365 ag_res.num = type;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001366
Myles Watson6bd442f2016-10-19 09:50:22 -07001367 if (res == BTA_AG_CALL_WAIT_RES)
1368 snprintf(&ag_res.str[xx], sizeof(ag_res.str) - xx, ",%d", type);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001369 }
1370 break;
Myles Watson6bd442f2016-10-19 09:50:22 -07001371 case BTHF_CALL_STATE_DIALING:
1372 if (!(num_active + num_held))
1373 ag_res.audio_handle = btif_hf_cb[idx].handle;
1374 res = BTA_AG_OUT_CALL_ORIG_RES;
1375 break;
1376 case BTHF_CALL_STATE_ALERTING:
1377 /* if we went from idle->alert, force SCO setup here. dialing usually
1378 * triggers it */
1379 if ((btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) &&
1380 !(num_active + num_held))
1381 ag_res.audio_handle = btif_hf_cb[idx].handle;
1382 res = BTA_AG_OUT_CALL_ALERT_RES;
1383 break;
1384 default:
1385 BTIF_TRACE_ERROR("%s: Incorrect new ringing call state", __func__);
1386 status = BT_STATUS_PARM_INVALID;
1387 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001388 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001389 BTIF_TRACE_DEBUG("%s: Call setup state changed. res=%d, audio_handle=%d",
1390 __func__, res, ag_res.audio_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001391
Myles Watson6bd442f2016-10-19 09:50:22 -07001392 if (res) BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001393
Myles Watson6bd442f2016-10-19 09:50:22 -07001394 /* if call setup is idle, we have already updated call indicator, jump out
1395 */
1396 if (call_setup_state == BTHF_CALL_STATE_IDLE) {
1397 /* check & update callheld */
1398 if ((num_held > 0) && (num_active > 0))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001399 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
Myles Watson6bd442f2016-10-19 09:50:22 -07001400 goto update_call_states;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001401 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001402 }
1403
1404 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1405
1406 /* per the errata 2043, call=1 implies atleast one call is in progress
1407 *(active/held)
1408 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1409 ** Handle call indicator change
1410 **/
1411 if (!activeCallUpdated &&
1412 ((num_active + num_held) !=
1413 (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held))) {
1414 BTIF_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d",
1415 __func__, btif_hf_cb[idx].num_active, num_active);
1416 send_indicator_update(BTA_AG_IND_CALL,
1417 ((num_active + num_held) > 0) ? 1 : 0);
1418 }
1419
1420 /* Held Changed? */
1421 if (num_held != btif_hf_cb[idx].num_held ||
1422 ((num_active == 0) && ((num_held + btif_hf_cb[idx].num_held) > 1))) {
1423 BTIF_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d", __func__,
1424 btif_hf_cb[idx].num_held, num_held);
1425 send_indicator_update(BTA_AG_IND_CALLHELD,
1426 ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
1427 }
1428
1429 /* Calls Swapped? */
1430 if ((call_setup_state == btif_hf_cb[idx].call_setup_state) &&
1431 (num_active && num_held) && (num_active == btif_hf_cb[idx].num_active) &&
1432 (num_held == btif_hf_cb[idx].num_held)) {
1433 BTIF_TRACE_DEBUG("%s: Calls swapped", __func__);
1434 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
1435 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001436
1437update_call_states:
Myles Watson6bd442f2016-10-19 09:50:22 -07001438 for (i = 0; i < btif_max_hf_clients; i++) {
1439 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
1440 btif_hf_cb[i].num_active = num_active;
1441 btif_hf_cb[i].num_held = num_held;
1442 btif_hf_cb[i].call_setup_state = call_setup_state;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001443 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001444 }
1445 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001446}
1447
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301448/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001449 *
1450 * Function btif_hf_is_call_idle
1451 *
1452 * Description returns true if no call is in progress
1453 *
1454 * Returns bt_status_t
1455 *
1456 ******************************************************************************/
1457bool btif_hf_is_call_idle(void) {
1458 if (bt_hf_callbacks == NULL) return true;
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301459
Myles Watson6bd442f2016-10-19 09:50:22 -07001460 for (int i = 0; i < btif_max_hf_clients; ++i) {
1461 if ((btif_hf_cb[i].call_setup_state != BTHF_CALL_STATE_IDLE) ||
1462 ((btif_hf_cb[i].num_held + btif_hf_cb[i].num_active) > 0))
1463 return false;
1464 }
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301465
Myles Watson6bd442f2016-10-19 09:50:22 -07001466 return true;
1467}
1468
1469/*******************************************************************************
1470 *
1471 * Function btif_hf_call_terminated_recently
1472 *
1473 * Description Checks if a call has been terminated
1474 *
1475 * Returns bt_status_t
1476 *
1477 ******************************************************************************/
1478bool btif_hf_call_terminated_recently() {
1479 struct timespec now;
1480
1481 clock_gettime(CLOCK_MONOTONIC, &now);
1482 if (now.tv_sec <
1483 btif_hf_cb[0].call_end_timestamp.tv_sec + BTIF_HF_CALL_END_TIMEOUT) {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001484 return true;
Myles Watson6bd442f2016-10-19 09:50:22 -07001485 } else {
1486 btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
1487 return false;
1488 }
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301489}
The Android Open Source Project5738f832012-12-12 16:00:35 -08001490
1491/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001492 *
1493 * Function cleanup
1494 *
1495 * Description Closes the HF interface
1496 *
1497 * Returns bt_status_t
1498 *
1499 ******************************************************************************/
1500static void cleanup(void) {
1501 BTIF_TRACE_EVENT("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001502
Myles Watson6bd442f2016-10-19 09:50:22 -07001503 if (bt_hf_callbacks) {
Satish Kodishala0ff1dd72016-03-09 18:57:01 +05301504#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
Myles Watson6bd442f2016-10-19 09:50:22 -07001505 btif_disable_service(BTA_HFP_SERVICE_ID);
Satish Kodishala0ff1dd72016-03-09 18:57:01 +05301506#else
1507 btif_disable_service(BTA_HSP_SERVICE_ID);
1508#endif
Myles Watson6bd442f2016-10-19 09:50:22 -07001509 bt_hf_callbacks = NULL;
1510 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001511}
1512
1513/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001514 *
1515 * Function configure_wbs
1516 *
1517 * Description set to over-ride the current WBS configuration.
1518 * It will not send codec setting cmd to the controller now.
1519 * It just change the configure.
1520 *
1521 * Returns bt_status_t
1522 *
1523 ******************************************************************************/
1524static bt_status_t configure_wbs(bt_bdaddr_t* bd_addr,
1525 bthf_wbs_config_t config) {
1526 CHECK_BTHF_INIT();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001527
Myles Watson6bd442f2016-10-19 09:50:22 -07001528 int idx = btif_hf_idx_by_bdaddr(bd_addr);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001529
Myles Watson6bd442f2016-10-19 09:50:22 -07001530 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1531 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1532 return BT_STATUS_FAIL;
1533 }
Matthew Xie66432dc2014-04-27 05:45:32 -07001534
Myles Watson6bd442f2016-10-19 09:50:22 -07001535 BTIF_TRACE_EVENT("%s config is %d", __func__, config);
1536 if (config == BTHF_WBS_YES)
1537 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_MSBC);
1538 else if (config == BTHF_WBS_NO)
1539 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_CVSD);
1540 else
1541 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_NONE);
Matthew Xie66432dc2014-04-27 05:45:32 -07001542
Myles Watson6bd442f2016-10-19 09:50:22 -07001543 return BT_STATUS_SUCCESS;
Matthew Xie66432dc2014-04-27 05:45:32 -07001544}
1545
The Android Open Source Project5738f832012-12-12 16:00:35 -08001546static const bthf_interface_t bthfInterface = {
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001547 sizeof(bthfInterface),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001548 init,
1549 connect,
1550 disconnect,
1551 connect_audio,
1552 disconnect_audio,
1553 start_voice_recognition,
1554 stop_voice_recognition,
1555 volume_control,
1556 device_status_notification,
1557 cops_response,
1558 cind_response,
1559 formatted_at_response,
1560 at_response,
1561 clcc_response,
1562 phone_state_change,
1563 cleanup,
Matthew Xie66432dc2014-04-27 05:45:32 -07001564 configure_wbs,
Mudumba Ananth4de9bbc2016-02-29 02:21:43 -08001565 bind_response,
Zach Johnsonacdc11c2017-04-18 21:03:07 -07001566 set_sco_allowed,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001567};
1568
1569/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001570 *
1571 * Function btif_hf_execute_service
1572 *
1573 * Description Initializes/Shuts down the service
1574 *
1575 * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1576 *
1577 ******************************************************************************/
1578bt_status_t btif_hf_execute_service(bool b_enable) {
1579 const char* p_service_names[] = BTIF_HF_SERVICE_NAMES;
1580 int i;
1581 if (b_enable) {
1582 /* Enable and register with BTA-AG */
1583 BTA_AgEnable(BTA_AG_PARSE, bte_hf_evt);
1584 for (i = 0; i < btif_max_hf_clients; i++) {
Jack He7a9892c2017-02-02 17:42:40 -08001585 BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY, btif_hf_features,
Myles Watson6bd442f2016-10-19 09:50:22 -07001586 p_service_names, bthf_hf_id[i]);
1587 }
1588 } else {
1589 /* De-register AG */
1590 for (i = 0; i < btif_max_hf_clients; i++) {
1591 BTA_AgDeregister(btif_hf_cb[i].handle);
1592 }
1593 /* Disable AG */
1594 BTA_AgDisable();
1595 }
1596 return BT_STATUS_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001597}
1598
1599/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001600 *
1601 * Function btif_hf_get_interface
1602 *
1603 * Description Get the hf callback interface
1604 *
1605 * Returns bthf_interface_t
1606 *
1607 ******************************************************************************/
1608const bthf_interface_t* btif_hf_get_interface() {
1609 BTIF_TRACE_EVENT("%s", __func__);
1610 return &bthfInterface;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001611}