summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNitin Srivastava <nitinsr@codeaurora.org>2014-03-14 16:19:58 -0700
committerMatthew Xie <mattx@google.com>2014-05-06 01:14:24 -0700
commit90a32530e8b9908f2af64ce98931684fa20c061b (patch)
tree4dbffd3226070d3f80d4eccf9adb9207855fa49d
parent68c53ded6523113ddcc1932fa5bcb7d378b12209 (diff)
downloadandroid_system_bt-90a32530e8b9908f2af64ce98931684fa20c061b.tar.gz
android_system_bt-90a32530e8b9908f2af64ce98931684fa20c061b.tar.bz2
android_system_bt-90a32530e8b9908f2af64ce98931684fa20c061b.zip
Add support for Multi-HFP devices
1. Add multi headset support in stack. 2. Each HS will be associated with unique CB in BTIF and also corresponding SCB in BTA. 3. Upstream event callbacks will be sent to specific HS based on BD_ADDR. 4. Similiarly all commands to BTIF will be for specific HS. Change-Id: I0dc6b1b54f16244b802d818ae60944877a41d020
-rw-r--r--bta/ag/bta_ag_act.c10
-rw-r--r--bta/ag/bta_ag_cmd.c1
-rw-r--r--bta/ag/bta_ag_main.c7
-rw-r--r--bta/include/bta_ag_api.h10
-rw-r--r--btif/src/btif_hf.c481
-rw-r--r--include/bt_target.h2
6 files changed, 374 insertions, 137 deletions
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c
index 11fc85c92..cedbb3dcb 100644
--- a/bta/ag/bta_ag_act.c
+++ b/bta/ag/bta_ag_act.c
@@ -406,7 +406,7 @@ void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
*******************************************************************************/
void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
{
- tBTA_AG_HDR close;
+ tBTA_AG_CLOSE close;
tBTA_SERVICE_MASK services;
int i, num_active_conn = 0;
UNUSED(p_data);
@@ -436,13 +436,14 @@ void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
bta_sys_stop_timer(&p_scb->cn_timer);
#endif
- close.handle = bta_ag_scb_to_idx(p_scb);
- close.app_id = p_scb->app_id;
+ close.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ close.hdr.app_id = p_scb->app_id;
+ bdcpy(close.bd_addr, p_scb->peer_addr);
bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
/* call close call-out */
- bta_ag_co_data_close(close.handle);
+ bta_ag_co_data_close(close.hdr.handle);
/* call close cback */
(*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close);
@@ -819,6 +820,7 @@ void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
evt.hdr.app_id = p_scb->app_id;
evt.peer_feat = p_scb->peer_features;
+ bdcpy(evt.bd_addr, p_scb->peer_addr);
#if (BTM_WBS_INCLUDED == TRUE )
evt.peer_codec = p_scb->peer_codecs;
#endif
diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c
index 54cd4d3d8..073deebe9 100644
--- a/bta/ag/bta_ag_cmd.c
+++ b/bta/ag/bta_ag_cmd.c
@@ -867,6 +867,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
val.hdr.handle = bta_ag_scb_to_idx(p_scb);
val.hdr.app_id = p_scb->app_id;
val.num = int_arg;
+ bdcpy(val.bd_addr, p_scb->peer_addr);
BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
val.str[BTA_AG_AT_MAX_LEN] = 0;
diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c
index bae992b99..712e50e80 100644
--- a/bta/ag/bta_ag_main.c
+++ b/bta/ag/bta_ag_main.c
@@ -753,6 +753,7 @@ static void bta_ag_api_register(tBTA_AG_DATA *p_data)
/* allocate an scb */
if ((p_scb = bta_ag_scb_alloc()) != NULL)
{
+ APPL_TRACE_DEBUG1("bta_ag_api_register: p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, p_data->hdr.event, p_data);
}
else
@@ -781,6 +782,7 @@ static void bta_ag_api_result(tBTA_AG_DATA *p_data)
{
if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL)
{
+ APPL_TRACE_DEBUG1("bta_ag_api_result: p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
}
}
@@ -788,8 +790,9 @@ static void bta_ag_api_result(tBTA_AG_DATA *p_data)
{
for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++)
{
- if (p_scb->in_use)
+ if (p_scb->in_use && p_scb->svc_conn)
{
+ APPL_TRACE_DEBUG1("bta_ag_api_result p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
}
}
@@ -879,6 +882,7 @@ BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg)
{
tBTA_AG_SCB *p_scb;
+ APPL_TRACE_DEBUG1("bta_ag_hdl_event: Event 0x%04x ", p_msg->event);
switch (p_msg->event)
{
/* handle enable event */
@@ -905,6 +909,7 @@ BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg)
default:
if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
{
+ APPL_TRACE_DEBUG1("bta_ag_hdl_event: p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg);
}
break;
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
index f16687c54..85f82a0e5 100644
--- a/bta/include/bta_ag_api.h
+++ b/bta/include/bta_ag_api.h
@@ -275,11 +275,19 @@ typedef struct
tBTA_AG_STATUS status;
} tBTA_AG_OPEN;
+/* data associated with BTA_AG_CLOSE_EVT */
+typedef struct
+{
+ tBTA_AG_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_AG_CLOSE;
+
/* data associated with BTA_AG_CONN_EVT */
typedef struct
{
tBTA_AG_HDR hdr;
tBTA_AG_PEER_FEAT peer_feat;
+ BD_ADDR bd_addr;
tBTA_AG_PEER_CODEC peer_codec;
} tBTA_AG_CONN;
@@ -287,6 +295,7 @@ typedef struct
typedef struct
{
tBTA_AG_HDR hdr;
+ BD_ADDR bd_addr;
char str[BTA_AG_AT_MAX_LEN+1];
UINT16 num;
UINT8 idx; /* call number used by CLCC and CHLD */
@@ -298,6 +307,7 @@ typedef union
tBTA_AG_HDR hdr;
tBTA_AG_REGISTER reg;
tBTA_AG_OPEN open;
+ tBTA_AG_CLOSE close;
tBTA_AG_CONN conn;
tBTA_AG_VAL val;
} tBTA_AG;
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
index b4ade0d73..418156d50 100644
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -71,10 +71,31 @@
BTA_AG_FEAT_UNAT)
#endif
-#define BTIF_HF_ID_1 0
-
#define BTIF_HF_CALL_END_TIMEOUT 6
+#define BTIF_HF_INVALID_IDX -1
+
+/* Number of BTIF-HF control blocks */
+#define BTIF_HF_NUM_CB 2
+
+/* Max HF clients supported from App */
+UINT16 btif_max_hf_clients = -1;
+
+/* HF app ids for service registration */
+typedef enum {
+ BTIF_HF_ID_1 = 0,
+ BTIF_HF_ID_2,
+#if (BTIF_HF_NUM_CB == 3)
+ BTIF_HF_ID_3
+#endif
+} bthf_hf_id_t;
+
+UINT16 bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2,
+ #if (BTIF_HF_NUM_CB == 3)
+ BTIF_HF_ID_3
+ #endif
+ };
+
/************************************************************************************
** Local type definitions
************************************************************************************/
@@ -83,6 +104,7 @@
** Static variables
************************************************************************************/
static bthf_callbacks_t *bt_hf_callbacks = NULL;
+static int hf_idx = BTIF_HF_INVALID_IDX;
#define CHECK_BTHF_INIT() if (bt_hf_callbacks == NULL)\
{\
@@ -120,10 +142,11 @@ typedef struct _btif_hf_cb
int num_active;
int num_held;
struct timespec call_end_timestamp;
+ struct timespec connected_timestamp;
bthf_call_state_t call_setup_state;
} btif_hf_cb_t;
-static btif_hf_cb_t btif_hf_cb;
+static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
/************************************************************************************
@@ -149,15 +172,41 @@ static btif_hf_cb_t btif_hf_cb;
*******************************************************************************/
static BOOLEAN is_connected(bt_bdaddr_t *bd_addr)
{
- if (((btif_hf_cb.state == BTHF_CONNECTION_STATE_CONNECTED) || (btif_hf_cb.state == BTHF_CONNECTION_STATE_SLC_CONNECTED))&&
- ((bd_addr == NULL) || (bdcmp(bd_addr->address, btif_hf_cb.connected_bda.address) == 0)))
- return TRUE;
- else
+ int i;
+ for (i = 0; i < btif_max_hf_clients; ++i)
+ {
+ if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+ (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
+ ((bd_addr == NULL) || (bdcmp(bd_addr->address,
+ btif_hf_cb[i].connected_bda.address) == 0)))
+ return TRUE;
+ }
return FALSE;
}
/*******************************************************************************
**
+** Function btif_hf_idx_by_bdaddr
+**
+** Description Internal function to get idx by bdaddr
+**
+** Returns idx
+**
+*******************************************************************************/
+static int btif_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
+{
+ int i;
+ for (i = 0; i < btif_max_hf_clients; ++i)
+ {
+ if ((bdcmp(bd_addr->address,
+ btif_hf_cb[i].connected_bda.address) == 0))
+ return i;
+ }
+ return BTIF_HF_INVALID_IDX;
+}
+
+/*******************************************************************************
+**
** Function callstate_to_callsetup
**
** Description Converts HAL call state to BTA call setup indicator value
@@ -187,7 +236,7 @@ static UINT8 callstate_to_callsetup(bthf_call_state_t call_state)
** Returns void
**
*******************************************************************************/
-static void send_at_result(UINT8 ok_flag, UINT16 errcode)
+static void send_at_result(UINT8 ok_flag, UINT16 errcode, int idx)
{
tBTA_AG_RES_DATA ag_res;
memset (&ag_res, 0, sizeof (ag_res));
@@ -198,7 +247,7 @@ static void send_at_result(UINT8 ok_flag, UINT16 errcode)
ag_res.errcode = errcode;
}
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
}
/*******************************************************************************
@@ -221,12 +270,77 @@ static void send_indicator_update (UINT16 indicator, UINT16 value)
BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
}
-void clear_phone_state()
+void clear_phone_state_multihf(int idx)
{
- btif_hf_cb.call_setup_state = BTHF_CALL_STATE_IDLE;
- btif_hf_cb.num_active = btif_hf_cb.num_held = 0;
+ btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE;
+ btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0;
}
+/*******************************************************************************
+**
+** Function btif_hf_latest_connected_idx
+**
+** Description Returns idx for latest connected HF
+**
+** Returns int
+**
+*******************************************************************************/
+static int btif_hf_latest_connected_idx()
+{
+ struct timespec now, conn_time_delta;
+ int latest_conn_idx = BTIF_HF_INVALID_IDX, i;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ conn_time_delta.tv_sec = now.tv_sec;
+
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)
+ {
+ if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec)
+ < conn_time_delta.tv_sec)
+ {
+ conn_time_delta.tv_sec =
+ now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec;
+ latest_conn_idx = i;
+ }
+ }
+ }
+ return latest_conn_idx;
+}
+
+/*******************************************************************************
+**
+** Function btif_hf_check_if_slc_connected
+**
+** Description Returns BT_STATUS_SUCCESS if SLC is up for any HF
+**
+** Returns bt_status_t
+**
+*******************************************************************************/
+static bt_status_t btif_hf_check_if_slc_connected()
+{
+ if (bt_hf_callbacks == NULL)
+ {
+ BTIF_TRACE_WARNING1("BTHF: %s: BTHF not initialized", __FUNCTION__);
+ return BT_STATUS_NOT_READY;
+ }
+ else
+ {
+ int i;
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ if ((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED))
+ {
+ BTIF_TRACE_EVENT2("BTHF: %s: slc connected for idx = %d",
+ __FUNCTION__, i);
+ return BT_STATUS_SUCCESS;
+ }
+ }
+ BTIF_TRACE_WARNING1("BTHF: %s: No SLC connection up", __FUNCTION__);
+ return BT_STATUS_NOT_READY;
+ }
+}
/*****************************************************************************
** Section name (Group of functions)
@@ -252,6 +366,8 @@ static void btif_hf_upstreams_evt(UINT16 event, char* p_param)
{
tBTA_AG *p_data = (tBTA_AG *)p_param;
bdstr_t bdstr;
+ bt_bdaddr_t addr;
+ int idx = p_data->hdr.handle - 1;
BTIF_TRACE_DEBUG2("%s: event=%s", __FUNCTION__, dump_hf_event(event));
@@ -262,43 +378,54 @@ static void btif_hf_upstreams_evt(UINT16 event, char* p_param)
break;
case BTA_AG_REGISTER_EVT:
- btif_hf_cb.handle = p_data->reg.hdr.handle;
+ btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
+ BTIF_TRACE_DEBUG2("%s: BTA_AG_REGISTER_EVT,"
+ "btif_hf_cb.handle = %d", __FUNCTION__, btif_hf_cb[idx].handle);
break;
case BTA_AG_OPEN_EVT:
if (p_data->open.status == BTA_AG_SUCCESS)
{
- bdcpy(btif_hf_cb.connected_bda.address, p_data->open.bd_addr);
- btif_hf_cb.state = BTHF_CONNECTION_STATE_CONNECTED;
- btif_hf_cb.peer_feat = 0;
- clear_phone_state();
+ bdcpy(btif_hf_cb[idx].connected_bda.address,
+ p_data->open.bd_addr);
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
+ btif_hf_cb[idx].peer_feat = 0;
+ clear_phone_state_multihf(idx);
}
- else if (btif_hf_cb.state == BTHF_CONNECTION_STATE_CONNECTING)
+ else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING)
{
- btif_hf_cb.state = BTHF_CONNECTION_STATE_DISCONNECTED;
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
}
else
{
BTIF_TRACE_WARNING4("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s",
- __FUNCTION__, p_data->open.status, btif_hf_cb.state, bd2str(&btif_hf_cb.connected_bda, &bdstr));
+ __FUNCTION__, p_data->open.status, btif_hf_cb[idx].state,
+ bd2str(&btif_hf_cb[idx].connected_bda, &bdstr));
break;
}
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state, &btif_hf_cb.connected_bda);
+ HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
+ &btif_hf_cb[idx].connected_bda);
- if (btif_hf_cb.state == BTHF_CONNECTION_STATE_DISCONNECTED)
- bdsetany(btif_hf_cb.connected_bda.address);
+ if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
+ bdsetany(btif_hf_cb[idx].connected_bda.address);
if (p_data->open.status != BTA_AG_SUCCESS)
btif_queue_advance();
break;
case BTA_AG_CLOSE_EVT:
- btif_hf_cb.state = BTHF_CONNECTION_STATE_DISCONNECTED;
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state, &btif_hf_cb.connected_bda);
- bdsetany(btif_hf_cb.connected_bda.address);
- btif_hf_cb.peer_feat = 0;
- clear_phone_state();
+ btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
+ BTIF_TRACE_DEBUG3("%s: BTA_AG_CLOSE_EVT,"
+ "idx = %d, btif_hf_cb.handle = %d", __FUNCTION__, idx,
+ btif_hf_cb[idx].handle);
+ HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
+ &btif_hf_cb[idx].connected_bda);
+ bdsetany(btif_hf_cb[idx].connected_bda.address);
+ btif_hf_cb[idx].peer_feat = 0;
+ clear_phone_state_multihf(idx);
+ hf_idx = btif_hf_latest_connected_idx();
/* If AG_OPEN was received but SLC was not setup in a specified time (10 seconds),
** then AG_CLOSE may be received. We need to advance the queue here
*/
@@ -306,60 +433,79 @@ static void btif_hf_upstreams_evt(UINT16 event, char* p_param)
break;
case BTA_AG_CONN_EVT:
- btif_hf_cb.peer_feat = p_data->conn.peer_feat;
- btif_hf_cb.state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
-
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state,
- &btif_hf_cb.connected_bda);
+ clock_gettime(CLOCK_MONOTONIC,
+ &btif_hf_cb[idx].connected_timestamp);
+ BTIF_TRACE_DEBUG2("%s: BTA_AG_CONN_EVT, idx = %d ",
+ __FUNCTION__, idx);
+ btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
+ hf_idx = btif_hf_latest_connected_idx();
+
+ HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
+ &btif_hf_cb[idx].connected_bda);
btif_queue_advance();
break;
case BTA_AG_AUDIO_OPEN_EVT:
- HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED, &btif_hf_cb.connected_bda);
+ hf_idx = idx;
+ HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AUDIO_CLOSE_EVT:
- HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED, &btif_hf_cb.connected_bda);
+ HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
+ &btif_hf_cb[idx].connected_bda);
break;
/* BTA auto-responds, silently discard */
case BTA_AG_SPK_EVT:
case BTA_AG_MIC_EVT:
HAL_CBACK(bt_hf_callbacks, volume_cmd_cb,
- (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK : BTHF_VOLUME_TYPE_MIC, p_data->val.num);
+ (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK :
+ BTHF_VOLUME_TYPE_MIC, p_data->val.num,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_A_EVT:
- HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb);
+ hf_idx = idx;
+ HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
/* Java needs to send OK/ERROR for these commands */
case BTA_AG_AT_BLDN_EVT:
case BTA_AG_AT_D_EVT:
+ hf_idx = idx;
HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
- (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL);
+ (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CHUP_EVT:
- HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CIND_EVT:
- HAL_CBACK(bt_hf_callbacks, cind_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, cind_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_VTS_EVT:
- HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0]);
+ HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_BVRA_EVT:
HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
- (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED : BTHF_VR_STATE_STOPPED);
+ (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED :
+ BTHF_VR_STATE_STOPPED, &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_NREC_EVT:
HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
- (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP);
+ (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
+ &btif_hf_cb[idx].connected_bda);
break;
/* TODO: Add a callback for CBC */
@@ -367,35 +513,40 @@ static void btif_hf_upstreams_evt(UINT16 event, char* p_param)
break;
case BTA_AG_AT_CKPD_EVT:
- HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
/* Java needs to send OK/ERROR for these commands */
case BTA_AG_AT_CHLD_EVT:
- HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str));
+ HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str),
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CLCC_EVT:
- HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb, p_data->val.num);
+ HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_COPS_EVT:
- HAL_CBACK(bt_hf_callbacks, cops_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, cops_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_UNAT_EVT:
- HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb,
- p_data->val.str);
+ HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CNUM_EVT:
- HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
/* TODO: Some of these commands may need to be sent to app. For now respond with error */
case BTA_AG_AT_BINP_EVT:
case BTA_AG_AT_BTRH_EVT:
- send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx);
break;
@@ -452,14 +603,14 @@ static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *p_data)
*******************************************************************************/
static void btif_in_hf_generic_evt(UINT16 event, char *p_param)
{
- UNUSED(p_param);
+ int idx = btif_hf_idx_by_bdaddr((bt_bdaddr_t *)p_param);
BTIF_TRACE_EVENT2("%s: event=%d", __FUNCTION__, event);
switch (event) {
case BTIF_HFP_CB_AUDIO_CONNECTING:
{
HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
- &btif_hf_cb.connected_bda);
+ &btif_hf_cb[idx].connected_bda);
} break;
default:
{
@@ -479,9 +630,10 @@ static void btif_in_hf_generic_evt(UINT16 event, char *p_param)
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t init( bthf_callbacks_t* callbacks )
+static bt_status_t init( bthf_callbacks_t* callbacks, int max_hf_clients)
{
BTIF_TRACE_EVENT1("%s", __FUNCTION__);
+ int i;
bt_hf_callbacks = callbacks;
@@ -495,8 +647,13 @@ static bt_status_t init( bthf_callbacks_t* callbacks )
btif_enable_service(BTA_HSP_SERVICE_ID);
#endif
- memset(&btif_hf_cb, 0, sizeof(btif_hf_cb_t));
- clear_phone_state();
+ memset(&btif_hf_cb, 0, sizeof(btif_hf_cb));
+ btif_max_hf_clients = max_hf_clients;
+ BTIF_TRACE_DEBUG1("btif_max_hf_clients = %d", btif_max_hf_clients);
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ clear_phone_state_multihf(i);
+ }
return BT_STATUS_SUCCESS;
}
@@ -512,12 +669,26 @@ static bt_status_t init( bthf_callbacks_t* callbacks )
*******************************************************************************/
static bt_status_t connect_int( bt_bdaddr_t *bd_addr )
{
+ CHECK_BTHF_INIT();
+ int i;
+ for (i = 0; i < btif_max_hf_clients;)
+ {
+ if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+ (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)))
+ i++;
+ else
+ break;
+ }
+
+ if (i == btif_max_hf_clients)
+ return BT_STATUS_BUSY;
+
if (!is_connected(bd_addr))
{
- btif_hf_cb.state = BTHF_CONNECTION_STATE_CONNECTING;
- bdcpy(btif_hf_cb.connected_bda.address, bd_addr->address);
+ btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
+ bdcpy(btif_hf_cb[i].connected_bda.address, bd_addr->address);
- BTA_AgOpen(btif_hf_cb.handle, btif_hf_cb.connected_bda.address,
+ BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda.address,
BTIF_HF_SECURITY, BTIF_HF_SERVICES);
return BT_STATUS_SUCCESS;
}
@@ -544,9 +715,11 @@ static bt_status_t disconnect( bt_bdaddr_t *bd_addr )
{
CHECK_BTHF_INIT();
- if (is_connected(bd_addr))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- BTA_AgClose(btif_hf_cb.handle);
+ BTA_AgClose(btif_hf_cb[idx].handle);
return BT_STATUS_SUCCESS;
}
@@ -566,9 +739,11 @@ static bt_status_t connect_audio( bt_bdaddr_t *bd_addr )
{
CHECK_BTHF_INIT();
- if (is_connected(bd_addr))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- BTA_AgAudioOpen(btif_hf_cb.handle);
+ BTA_AgAudioOpen(btif_hf_cb[idx].handle);
/* Inform the application that the audio connection has been initiated successfully */
btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING,
@@ -592,9 +767,11 @@ static bt_status_t disconnect_audio( bt_bdaddr_t *bd_addr )
{
CHECK_BTHF_INIT();
- if (is_connected(bd_addr))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- BTA_AgAudioClose(btif_hf_cb.handle);
+ BTA_AgAudioClose(btif_hf_cb[idx].handle);
return BT_STATUS_SUCCESS;
}
@@ -610,17 +787,20 @@ static bt_status_t disconnect_audio( bt_bdaddr_t *bd_addr )
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t start_voice_recognition()
+static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- if (btif_hf_cb.peer_feat & BTA_AG_PEER_FEAT_VREC)
+ if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
{
tBTA_AG_RES_DATA ag_res;
memset(&ag_res, 0, sizeof(ag_res));
ag_res.state = 1;
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -642,18 +822,20 @@ static bt_status_t start_voice_recognition()
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t stop_voice_recognition()
+static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- if (btif_hf_cb.peer_feat & BTA_AG_PEER_FEAT_VREC)
+ if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
{
tBTA_AG_RES_DATA ag_res;
memset(&ag_res, 0, sizeof(ag_res));
ag_res.state = 0;
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -675,16 +857,19 @@ static bt_status_t stop_voice_recognition()
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t volume_control(bthf_volume_type_t type, int volume)
+static bt_status_t volume_control(bthf_volume_type_t type, int volume,
+ bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
tBTA_AG_RES_DATA ag_res;
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
- if (is_connected(NULL))
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
ag_res.num = volume;
- BTA_AgResult(btif_hf_cb.handle,
+ BTA_AgResult(btif_hf_cb[idx].handle,
(type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
&ag_res);
return BT_STATUS_SUCCESS;
@@ -733,11 +918,13 @@ static bt_status_t device_status_notification(bthf_network_state_t ntk_state,
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t cops_response(const char *cops)
+static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
tBTA_AG_RES_DATA ag_res;
@@ -745,7 +932,7 @@ static bt_status_t cops_response(const char *cops)
sprintf (ag_res.str, "0,0,\"%s\"", cops);
ag_res.ok_flag = BTA_AG_OK_DONE;
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_COPS_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
return BT_STATUS_FAIL;
@@ -762,11 +949,14 @@ static bt_status_t cops_response(const char *cops)
*******************************************************************************/
static bt_status_t cind_response(int svc, int num_active, int num_held,
bthf_call_state_t call_setup_state,
- int signal, int roam, int batt_chg)
+ int signal, int roam, int batt_chg,
+ bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
tBTA_AG_RES_DATA ag_res;
@@ -783,7 +973,7 @@ static bt_status_t cind_response(int svc, int num_active, int num_held,
batt_chg, /* Battery level */
((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_CIND_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -800,17 +990,18 @@ static bt_status_t cind_response(int svc, int num_active, int num_held,
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t formatted_at_response(const char *rsp)
+static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
tBTA_AG_RES_DATA ag_res;
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
- if (is_connected(NULL))
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
/* Format the response and send */
memset (&ag_res, 0, sizeof (ag_res));
strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -827,14 +1018,17 @@ static bt_status_t formatted_at_response(const char *rsp)
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t at_response(bthf_at_response_t response_code, int error_code)
+static bt_status_t at_response(bthf_at_response_t response_code,
+ int error_code, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
- : BTA_AG_OK_ERROR, error_code);
+ : BTA_AG_OK_ERROR, error_code, idx);
return BT_STATUS_SUCCESS;
}
@@ -854,13 +1048,15 @@ static bt_status_t at_response(bthf_at_response_t response_code, int error_code)
**
*******************************************************************************/
static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
- bthf_call_state_t state, bthf_call_mode_t mode,
- bthf_call_mpty_type_t mpty, const char *number,
- bthf_call_addrtype_t type)
+ bthf_call_state_t state, bthf_call_mode_t mode,
+ bthf_call_mpty_type_t mpty, const char *number,
+ bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
tBTA_AG_RES_DATA ag_res;
int xx;
@@ -887,7 +1083,7 @@ static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
sprintf (&ag_res.str[xx], ",\"%s\",%d", number, type);
}
}
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_CLCC_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -913,29 +1109,40 @@ static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_st
tBTA_AG_RES_DATA ag_res;
bt_status_t status = BT_STATUS_SUCCESS;
BOOLEAN activeCallUpdated = FALSE;
+ int idx, i;
+
+ /* Set idx to index of HF which sent ATA/BLDN else latest connected HF */
+ idx = (hf_idx == BTIF_HF_INVALID_IDX) ?
+ btif_hf_latest_connected_idx(): hf_idx;
+ BTIF_TRACE_DEBUG1("phone_state_change: idx = %d", idx);
- CHECK_BTHF_SLC_CONNECTED();
+ /* Check if SLC is connected */
+ if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
+ return BT_STATUS_NOT_READY;
- BTIF_TRACE_DEBUG6("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"\
- " call_setup=%s [prev: %s]", num_active, btif_hf_cb.num_active,
- num_held, btif_hf_cb.num_held,
- dump_hf_call_state(call_setup_state), dump_hf_call_state(btif_hf_cb.call_setup_state));
+ BTIF_TRACE_DEBUG6("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"
+ " call_setup=%s [prev: %s]", num_active, btif_hf_cb[idx].num_active,
+ num_held, btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
+ dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
/* if all indicators are 0, send end call and return */
if (num_active == 0 && num_held == 0 && call_setup_state == BTHF_CALL_STATE_IDLE)
{
BTIF_TRACE_DEBUG1("%s: Phone on hook", __FUNCTION__);
- /* record call termination timestamp if there was an active/held call or callsetup state > BTHF_CALL_STATE_IDLE */
- if ((btif_hf_cb.call_setup_state != BTHF_CALL_STATE_IDLE ) || (btif_hf_cb.num_active) ||(btif_hf_cb.num_held))
+ /* record call termination timestamp if there was an active/held call or
+ callsetup state > BTHF_CALL_STATE_IDLE */
+ if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE ) ||
+ (btif_hf_cb[idx].num_active) ||(btif_hf_cb[idx].num_held))
{
BTIF_TRACE_DEBUG1("%s: Record call termination timestamp", __FUNCTION__);
- clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb.call_end_timestamp);
+ clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
}
BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
+ hf_idx = BTIF_HF_INVALID_IDX;
/* if held call was present, reset that as well */
- if (btif_hf_cb.num_held)
+ if (btif_hf_cb[idx].num_held)
send_indicator_update(BTA_AG_IND_CALLHELD, 0);
goto update_call_states;
@@ -952,24 +1159,24 @@ static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_st
** force the SCO to be setup. Handle this special case here prior to
** call setup handling
*/
- if ( (num_active == 1) && (btif_hf_cb.num_active == 0) && (btif_hf_cb.num_held == 0) &&
- (btif_hf_cb.call_setup_state == BTHF_CALL_STATE_IDLE) )
+ if ( (num_active == 1) && (btif_hf_cb[idx].num_active == 0) && (btif_hf_cb[idx].num_held == 0)
+ && (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) )
{
BTIF_TRACE_DEBUG1("%s: Active call notification received without call setup update",
__FUNCTION__);
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
- ag_res.audio_handle = btif_hf_cb.handle;
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
res = BTA_AG_OUT_CALL_CONN_RES;
BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
activeCallUpdated = TRUE;
}
/* Ringing call changed? */
- if (call_setup_state != btif_hf_cb.call_setup_state)
+ if (call_setup_state != btif_hf_cb[idx].call_setup_state)
{
BTIF_TRACE_DEBUG3("%s: Call setup states changed. old: %s new: %s",
- __FUNCTION__, dump_hf_call_state(btif_hf_cb.call_setup_state),
+ __FUNCTION__, dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
dump_hf_call_state(call_setup_state));
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
@@ -977,22 +1184,22 @@ static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_st
{
case BTHF_CALL_STATE_IDLE:
{
- switch (btif_hf_cb.call_setup_state)
+ switch (btif_hf_cb[idx].call_setup_state)
{
case BTHF_CALL_STATE_INCOMING:
- if (num_active > btif_hf_cb.num_active)
+ if (num_active > btif_hf_cb[idx].num_active)
{
res = BTA_AG_IN_CALL_CONN_RES;
- ag_res.audio_handle = btif_hf_cb.handle;
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
}
- else if (num_held > btif_hf_cb.num_held)
+ else if (num_held > btif_hf_cb[idx].num_held)
res = BTA_AG_IN_CALL_HELD_RES;
else
res = BTA_AG_CALL_CANCEL_RES;
break;
case BTHF_CALL_STATE_DIALING:
case BTHF_CALL_STATE_ALERTING:
- if (num_active > btif_hf_cb.num_active)
+ if (num_active > btif_hf_cb[idx].num_active)
{
ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
res = BTA_AG_OUT_CALL_CONN_RES;
@@ -1026,13 +1233,13 @@ static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_st
}
break;
case BTHF_CALL_STATE_DIALING:
- ag_res.audio_handle = btif_hf_cb.handle;
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
res = BTA_AG_OUT_CALL_ORIG_RES;
break;
case BTHF_CALL_STATE_ALERTING:
/* if we went from idle->alert, force SCO setup here. dialing usually triggers it */
- if (btif_hf_cb.call_setup_state == BTHF_CALL_STATE_IDLE)
- ag_res.audio_handle = btif_hf_cb.handle;
+ if (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE)
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
res = BTA_AG_OUT_CALL_ALERT_RES;
break;
default:
@@ -1061,34 +1268,38 @@ static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_st
** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
** Handle call indicator change
**/
- if (!activeCallUpdated && ((num_active + num_held) != (btif_hf_cb.num_active + btif_hf_cb.num_held)) )
+ if (!activeCallUpdated && ((num_active + num_held) !=
+ (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held)) )
{
- BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_active, num_active);
+ BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb[idx].num_active, num_active);
send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
}
/* Held Changed? */
- if (num_held != btif_hf_cb.num_held)
+ if (num_held != btif_hf_cb[idx].num_held)
{
- BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_held, num_held);
+ BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d",
+ __FUNCTION__, btif_hf_cb[idx].num_held, num_held);
send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
}
/* Calls Swapped? */
- if ( (call_setup_state == btif_hf_cb.call_setup_state) &&
+ if ( (call_setup_state == btif_hf_cb[idx].call_setup_state) &&
(num_active && num_held) &&
- (num_active == btif_hf_cb.num_active) &&
- (num_held == btif_hf_cb.num_held) )
+ (num_active == btif_hf_cb[idx].num_active) &&
+ (num_held == btif_hf_cb[idx].num_held) )
{
BTIF_TRACE_DEBUG1("%s: Calls swapped", __FUNCTION__);
send_indicator_update(BTA_AG_IND_CALLHELD, 1);
}
update_call_states:
- btif_hf_cb.num_active = num_active;
- btif_hf_cb.num_held = num_held;
- btif_hf_cb.call_setup_state = call_setup_state;
-
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ btif_hf_cb[i].num_active = num_active;
+ btif_hf_cb[i].num_held = num_held;
+ btif_hf_cb[i].call_setup_state = call_setup_state;
+ }
return status;
}
@@ -1107,13 +1318,14 @@ BOOLEAN btif_hf_call_terminated_recently()
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
- if (now.tv_sec < btif_hf_cb.call_end_timestamp.tv_sec + BTIF_HF_CALL_END_TIMEOUT)
+ if (now.tv_sec < btif_hf_cb[0].call_end_timestamp.tv_sec +
+ BTIF_HF_CALL_END_TIMEOUT)
{
return TRUE;
}
else
{
- btif_hf_cb.call_end_timestamp.tv_sec = 0;
+ btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
return FALSE;
}
}
@@ -1170,16 +1382,23 @@ static const bthf_interface_t bthfInterface = {
bt_status_t btif_hf_execute_service(BOOLEAN b_enable)
{
char * p_service_names[] = BTIF_HF_SERVICE_NAMES;
+ int i;
if (b_enable)
{
/* Enable and register with BTA-AG */
BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt);
- BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY, BTIF_HF_FEATURES,
- p_service_names, BTIF_HF_ID_1);
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY,
+ BTIF_HF_FEATURES, p_service_names, bthf_hf_id[i]);
+ }
}
else {
/* De-register AG */
- BTA_AgDeregister(btif_hf_cb.handle);
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ BTA_AgDeregister(btif_hf_cb[i].handle);
+ }
/* Disable AG */
BTA_AgDisable();
}
diff --git a/include/bt_target.h b/include/bt_target.h
index 5ac668cbe..c81cbe529 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -1026,7 +1026,7 @@ and USER_HW_DISABLE_API macros */
/* The number of SCO links. */
#ifndef BTM_MAX_SCO_LINKS
-#define BTM_MAX_SCO_LINKS 2
+#define BTM_MAX_SCO_LINKS 3
#endif
/* The preferred type of SCO links (2-eSCO, 0-SCO). */