summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGanesh Ganapathi Batta <ganeshg@broadcom.com>2013-02-05 15:22:31 -0800
committerMatthew Xie <mattx@google.com>2013-02-27 18:15:49 -0800
commitead3cde4bac0c3e32cd31f149093f004eef8ceeb (patch)
treef45b52e375e1a80e807dbbc864bb1da603965b0d
parente17bf003d4eefdc8525e55894210e9ee494972b8 (diff)
downloadandroid_system_bt-ead3cde4bac0c3e32cd31f149093f004eef8ceeb.tar.gz
android_system_bt-ead3cde4bac0c3e32cd31f149093f004eef8ceeb.tar.bz2
android_system_bt-ead3cde4bac0c3e32cd31f149093f004eef8ceeb.zip
Initial version of BLE support for Bluedroid
Change-Id: I9825a5cef9be2559c34c2a529b211b7d471147cf
-rw-r--r--bta/av/bta_av_aact.c131
-rw-r--r--bta/av/bta_av_act.c85
-rw-r--r--bta/av/bta_av_cfg.c33
-rw-r--r--bta/av/bta_av_int.h3
-rw-r--r--bta/av/bta_av_main.c10
-rw-r--r--bta/av/bta_av_ssm.c4
-rw-r--r--bta/dm/bta_dm_act.c384
-rw-r--r--bta/dm/bta_dm_api.c107
-rw-r--r--bta/dm/bta_dm_cfg.c10
-rw-r--r--bta/dm/bta_dm_int.h68
-rw-r--r--bta/dm/bta_dm_main.c6
-rw-r--r--bta/dm/bta_dm_pm.c76
-rw-r--r--bta/gatt/bta_gattc_act.c277
-rw-r--r--bta/gatt/bta_gattc_api.c110
-rw-r--r--bta/gatt/bta_gattc_cache.c46
-rw-r--r--bta/gatt/bta_gattc_int.h36
-rw-r--r--bta/gatt/bta_gattc_main.c28
-rw-r--r--bta/gatt/bta_gattc_utils.c265
-rw-r--r--bta/gatt/bta_gatts_act.c2
-rw-r--r--bta/gatt/bta_gatts_api.c23
-rw-r--r--bta/gatt/bta_gatts_int.h18
-rw-r--r--bta/hh/bta_hh_act.c58
-rw-r--r--bta/hh/bta_hh_api.c13
-rw-r--r--bta/hh/bta_hh_cfg.c7
-rw-r--r--bta/hh/bta_hh_int.h8
-rw-r--r--bta/hh/bta_hh_main.c27
-rw-r--r--bta/hh/bta_hh_utils.c136
-rw-r--r--bta/hl/bta_hl_act.c71
-rw-r--r--bta/hl/bta_hl_int.h2
-rw-r--r--bta/hl/bta_hl_main.c244
-rw-r--r--bta/hl/bta_hl_sdp.c2
-rw-r--r--bta/hl/bta_hl_utils.c27
-rw-r--r--bta/include/bta_api.h248
-rw-r--r--bta/include/bta_av_api.h3
-rw-r--r--bta/include/bta_gatt_api.h66
-rw-r--r--bta/include/bta_gattc_co.h16
-rw-r--r--bta/include/bta_hh_api.h58
-rw-r--r--btif/co/bta_dm_co.c24
-rw-r--r--btif/co/bta_gattc_co.c139
-rw-r--r--btif/co/bta_gatts_co.c243
-rw-r--r--btif/co/bta_hh_co.c9
-rw-r--r--btif/include/btif_api.h10
-rw-r--r--btif/include/btif_common.h3
-rw-r--r--btif/include/btif_dm.h73
-rw-r--r--btif/include/btif_gatt.h34
-rw-r--r--btif/include/btif_gatt_util.h39
-rw-r--r--btif/include/btif_hh.h1
-rw-r--r--btif/include/btif_storage.h57
-rw-r--r--btif/include/btif_util.h3
-rw-r--r--btif/include/uinput.h1
-rw-r--r--btif/src/bluetooth.c22
-rw-r--r--[-rwxr-xr-x]btif/src/btif_core.c4
-rw-r--r--btif/src/btif_dm.c672
-rw-r--r--btif/src/btif_gatt.c113
-rw-r--r--btif/src/btif_gatt_client.c998
-rw-r--r--btif/src/btif_gatt_server.c579
-rw-r--r--btif/src/btif_gatt_test.c293
-rw-r--r--btif/src/btif_gatt_util.c351
-rw-r--r--[-rwxr-xr-x]btif/src/btif_hf.c2
-rw-r--r--btif/src/btif_hh.c6
-rw-r--r--btif/src/btif_hl.c2
-rw-r--r--[-rwxr-xr-x]btif/src/btif_storage.c522
-rw-r--r--btif/src/btif_util.c11
-rw-r--r--conf/bt_stack.conf1
-rw-r--r--gki/common/gki_buffer.c4
-rw-r--r--gki/common/gki_common.h2
-rw-r--r--hci/src/userial.c31
-rw-r--r--[-rwxr-xr-x]include/bt_target.h53
-rw-r--r--include/bt_trace.h30
-rw-r--r--include/bte.h5
-rw-r--r--include/bte_appl.h25
-rw-r--r--main/Android.mk9
-rw-r--r--main/bte_logmsg.c4
-rw-r--r--main/bte_version.c3
-rw-r--r--stack/Android.mk5
-rw-r--r--stack/avdt/avdt_api.c50
-rw-r--r--stack/avdt/avdt_ccb_act.c8
-rw-r--r--stack/avdt/avdt_int.h1
-rw-r--r--stack/avdt/avdt_scb_act.c23
-rw-r--r--stack/btm/btm_acl.c180
-rw-r--r--stack/btm/btm_ble.c383
-rw-r--r--stack/btm/btm_ble_addr.c108
-rw-r--r--stack/btm/btm_ble_bgconn.c474
-rw-r--r--stack/btm/btm_ble_gap.c738
-rw-r--r--stack/btm/btm_ble_int.h101
-rw-r--r--stack/btm/btm_dev.c6
-rw-r--r--stack/btm/btm_devctl.c128
-rw-r--r--stack/btm/btm_inq.c58
-rw-r--r--stack/btm/btm_int.h41
-rw-r--r--stack/btm/btm_sco.c24
-rw-r--r--stack/btm/btm_sec.c294
-rw-r--r--stack/btu/btu_hcif.c72
-rw-r--r--stack/btu/btu_task.c38
-rw-r--r--stack/gap/gap_api.c903
-rw-r--r--stack/gap/gap_ble.c967
-rw-r--r--stack/gap/gap_conn.c1270
-rw-r--r--stack/gap/gap_int.h231
-rw-r--r--stack/gap/gap_utils.c432
-rw-r--r--stack/gatt/att_protocol.c15
-rw-r--r--stack/gatt/gatt_api.c61
-rw-r--r--stack/gatt/gatt_attr.c4
-rw-r--r--stack/gatt/gatt_auth.c173
-rw-r--r--stack/gatt/gatt_cl.c97
-rw-r--r--stack/gatt/gatt_db.c28
-rw-r--r--stack/gatt/gatt_int.h33
-rw-r--r--stack/gatt/gatt_main.c63
-rw-r--r--stack/gatt/gatt_sr.c12
-rw-r--r--stack/gatt/gatt_utils.c212
-rw-r--r--stack/hcic/hciblecmds.c108
-rw-r--r--stack/hcic/hcicmds.c3
-rw-r--r--stack/hid/hidh_api.c6
-rw-r--r--stack/hid/hidh_conn.c3
-rw-r--r--stack/include/avdt_api.h45
-rw-r--r--stack/include/avrc_api.h6
-rw-r--r--stack/include/bt_types.h51
-rw-r--r--stack/include/btm_api.h92
-rw-r--r--stack/include/btm_ble_api.h235
-rw-r--r--stack/include/btu.h6
-rw-r--r--stack/include/gap_api.h802
-rw-r--r--stack/include/gatt_api.h24
-rw-r--r--stack/include/gattdefs.h49
-rw-r--r--stack/include/hcidefs.h233
-rw-r--r--stack/include/hcimsgs.h10
-rw-r--r--stack/include/l2c_api.h10
-rw-r--r--stack/include/profiles_api.h71
-rw-r--r--stack/include/sdpdefs.h14
-rw-r--r--stack/include/smp_api.h1
-rw-r--r--stack/l2cap/l2c_ble.c135
-rw-r--r--stack/l2cap/l2c_fcr.c10
-rw-r--r--stack/l2cap/l2c_int.h1
-rw-r--r--stack/l2cap/l2c_link.c29
-rw-r--r--stack/l2cap/l2c_main.c25
-rw-r--r--stack/l2cap/l2c_utils.c182
-rw-r--r--stack/mcap/mca_int.h11
-rw-r--r--stack/mcap/mca_l2c.c19
-rw-r--r--stack/mcap/mca_main.c1
-rw-r--r--stack/sdp/sdp_db.c138
-rw-r--r--stack/sdp/sdp_server.c6
-rw-r--r--stack/sdp/sdp_utils.c16
-rw-r--r--stack/smp/aes.c926
-rw-r--r--stack/smp/aes.h162
-rw-r--r--stack/smp/smp_act.c30
-rw-r--r--stack/smp/smp_int.h3
-rw-r--r--stack/smp/smp_keys.c33
-rw-r--r--stack/smp/smp_l2c.c2
-rw-r--r--stack/smp/smp_main.c2
-rw-r--r--stack/smp/smp_utils.c26
-rw-r--r--test/bluedroidtest/README.txt27
-rw-r--r--test/bluedroidtest/bluedroidtest.c68
149 files changed, 15391 insertions, 2549 deletions
diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c
index 741a5a075..6a407e041 100644
--- a/bta/av/bta_av_aact.c
+++ b/bta/av/bta_av_aact.c
@@ -394,6 +394,16 @@ void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CT
/* copy config params to event message buffer */
switch (event)
{
+ case AVDT_RECONFIG_CFM_EVT:
+ APPL_TRACE_DEBUG4("reconfig cfm event codec info = 0x%06x-%06x-%06x-%02x",
+ (p_msg->msg.reconfig_cfm.p_cfg->codec_info[0]<<16)+(p_msg->msg.reconfig_cfm.p_cfg->codec_info[1]<<8)+p_msg->msg.reconfig_cfm.p_cfg->codec_info[2],
+ (p_msg->msg.reconfig_cfm.p_cfg->codec_info[3]<<16)+(p_msg->msg.reconfig_cfm.p_cfg->codec_info[4]<<8)+p_msg->msg.reconfig_cfm.p_cfg->codec_info[5],
+ (p_msg->msg.reconfig_cfm.p_cfg->codec_info[6]<<16)+(p_msg->msg.reconfig_cfm.p_cfg->codec_info[7]<<8)+p_msg->msg.reconfig_cfm.p_cfg->codec_info[8],
+ p_msg->msg.reconfig_cfm.p_cfg->codec_info[9]);
+ break;
+
+
+
case AVDT_CONFIG_IND_EVT:
/* We might have 2 SEP signallings(A2DP + VDP) with one peer device on one L2CAP.
* If we already have a signalling connection with the bd_addr and the streaming
@@ -461,17 +471,16 @@ void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CT
if (event == AVDT_SUSPEND_CFM_EVT)
p_msg->initiator = TRUE;
- APPL_TRACE_EVENT1("hndl:x%x", p_scb->hndl);
+ APPL_TRACE_VERBOSE1("hndl:x%x", p_scb->hndl);
p_msg->hdr.layer_specific = p_scb->hndl;
p_msg->handle = handle;
p_msg->avdt_event = event;
bta_sys_sendmsg(p_msg);
}
-/* coverity[var_deref_model]: Variable "p_data" tracked as NULL was passed to function "bta_av_conn_cback" that dereferences it.
- * false-positive: bta_av_conn_cback only processes AVDT_CONNECT_IND_EVT and AVDT_DISCONNECT_IND_EVT event
- * these 2 events always have associated p_data
- */
+/* coverity[var_deref_model] */
+/* false-positive: bta_av_conn_cback only processes AVDT_CONNECT_IND_EVT and AVDT_DISCONNECT_IND_EVT event
+ * these 2 events always have associated p_data */
bta_av_conn_cback(handle, bd_addr, event, p_data);
}
@@ -486,7 +495,7 @@ void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CT
*******************************************************************************/
static void bta_av_stream0_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
{
- APPL_TRACE_EVENT2("bta_av_stream0_cback avdt_handle: %d event=0x%x", handle, event);
+ APPL_TRACE_VERBOSE2("bta_av_stream0_cback avdt_handle: %d event=0x%x", handle, event);
bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 0);
}
@@ -1570,11 +1579,48 @@ void bta_av_cco_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
*******************************************************************************/
void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
{
+
+ BOOLEAN is_av_opened = FALSE;
+ tBTA_AV_SCB * p_opened_scb = NULL;
+ UINT8 idx;
+ tBTA_AV_OPEN open;
+
+ APPL_TRACE_DEBUG0("bta_av_open_failed");
p_scb->open_status = BTA_AV_FAIL_STREAM;
bta_av_cco_close(p_scb, p_data);
- AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+
+ /* check whether there is already an opened audio or video connection with the same device */
+ for (idx = 0; (idx < BTA_AV_NUM_STRS) && (is_av_opened == FALSE); idx++ )
+ {
+ p_opened_scb = bta_av_cb.p_scb[idx];
+ if (p_opened_scb && (p_opened_scb->state == BTA_AV_OPEN_SST) && (!bdcmp(p_opened_scb->peer_addr,p_scb->peer_addr )) )
+ is_av_opened = TRUE;
+
+ }
+
+ /* if there is already an active AV connnection with the same bd_addr,
+ don't send disconnect req, just report the open event with BTA_AV_FAIL_GET_CAP status */
+ if (is_av_opened == TRUE)
+ {
+ bdcpy(open.bd_addr, p_scb->peer_addr);
+ open.chnl = p_scb->chnl;
+ open.hndl = p_scb->hndl;
+ open.status = BTA_AV_FAIL_GET_CAP;
+ open.starting = bta_av_chk_start(p_scb);
+ open.edr = 0;
+ /* set the state back to initial state */
+ bta_av_set_scb_sst_init(p_scb);
+
+ (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *) &open);
+
+ }
+ else
+ {
+ AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ }
}
+
/*******************************************************************************
**
** Function bta_av_getcap_results
@@ -1798,7 +1844,8 @@ void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
AVDT_SuspendReq(&p_scb->avdt_handle, 1);
}
- if(sus_evt)
+ /* send SUSPEND_EVT event only if not in reconfiguring state and sus_evt is TRUE*/
+ if ((sus_evt)&&(p_scb->state != BTA_AV_RCFG_SST))
{
suspend_rsp.status = BTA_AV_SUCCESS;
suspend_rsp.initiator = TRUE;
@@ -1811,7 +1858,11 @@ void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
suspend_rsp.initiator = TRUE;
APPL_TRACE_EVENT1("bta_av_str_stopped status %d", suspend_rsp.status);
- (*bta_av_cb.p_cback)(BTA_AV_STOP_EVT, (tBTA_AV *) &suspend_rsp);
+ /* send STOP_EVT event only if not in reconfiguring state */
+ if (p_scb->state != BTA_AV_RCFG_SST)
+ {
+ (*bta_av_cb.p_cback)(BTA_AV_STOP_EVT, (tBTA_AV *) &suspend_rsp);
+ }
}
}
@@ -1916,6 +1967,7 @@ void bta_av_data_path (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
UINT32 timestamp;
BOOLEAN new_buf = FALSE;
UINT8 m_pt = 0x60 | p_scb->codec_type;
+ tAVDT_DATA_OPT_MASK opt;
if (!p_scb->cong)
{
@@ -1958,7 +2010,15 @@ void bta_av_data_path (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
/*
APPL_TRACE_ERROR1("qw: %d", p_scb->l2c_bufs);
*/
- AVDT_WriteReq(p_scb->avdt_handle, p_buf, timestamp, m_pt);
+
+ /* opt is a bit mask, it could have several options set */
+ opt = AVDT_DATA_OPT_NONE;
+ if (p_scb->no_rtp_hdr)
+ {
+ opt |= AVDT_DATA_OPT_NO_RTP;
+ }
+
+ AVDT_WriteReqOpt(p_scb->avdt_handle, p_buf, timestamp, m_pt, opt);
p_scb->cong = TRUE;
}
else
@@ -2008,6 +2068,8 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
UINT16 flush_to;
UINT8 new_role = p_scb->role;
BT_HDR hdr;
+ UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+ UINT8 cur_role;
APPL_TRACE_DEBUG2("bta_av_start_ok wait:x%x, role:x%x", p_scb->wait, p_scb->role);
@@ -2111,11 +2173,27 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
}
{
+ /* If sink starts stream, disable sniff mode here */
+ if (!initiator)
+ {
+ /* If souce is the master role, disable role switch during streaming.
+ * Otherwise allow role switch, if source is slave.
+ * Because it would not hurt source, if the peer device wants source to be master */
+ if ((BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
+ (cur_role == BTM_ROLE_MASTER) )
+ {
+ policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ }
+
+ bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+ }
+
p_scb->role = new_role;
p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
- p_scb->p_cos->start(p_scb->hndl, p_scb->codec_type);
+ p_scb->no_rtp_hdr = FALSE;
+ p_scb->p_cos->start(p_scb->hndl, p_scb->codec_type, p_scb->cfg.codec_info, &p_scb->no_rtp_hdr);
p_scb->co_started = TRUE;
APPL_TRACE_DEBUG3("bta_av_start_ok suspending: %d, role:x%x, init %d",
@@ -2269,9 +2347,13 @@ void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
bta_av_cb.audio_open_cnt, err_code);
suspend_rsp.status = BTA_AV_SUCCESS;
- if(err_code)
+ if (err_code)
{
- p_scb->suspend_sup = FALSE;
+ /* Disable suspend feature only with explicit rejection(not with timeout) */
+ if (err_code != AVDT_ERR_TIMEOUT)
+ {
+ p_scb->suspend_sup = FALSE;
+ }
suspend_rsp.status = BTA_AV_FAIL;
APPL_TRACE_ERROR0 ("bta_av_suspend_cfm: suspend failed, closing connection");
@@ -2285,7 +2367,7 @@ void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
p_scb->started = FALSE;
}
- if(p_scb->role & BTA_AV_ROLE_SUSPEND)
+ if (p_scb->role & BTA_AV_ROLE_SUSPEND)
{
p_scb->role &= ~BTA_AV_ROLE_SUSPEND;
p_scb->cong = FALSE;
@@ -2460,9 +2542,9 @@ void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
p_scb->started = FALSE;
p_scb->cong = FALSE;
- if(err_code)
+ if (err_code)
{
- if(AVDT_ERR_CONNECT == err_code)
+ if (AVDT_ERR_CONNECT == err_code)
{
/* report failure */
evt.status = BTA_AV_FAIL;
@@ -2472,8 +2554,11 @@ void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
else
{
APPL_TRACE_ERROR0("suspend rejected, try close");
- p_scb->suspend_sup = FALSE;
-
+ /* Disable suspend feature only with explicit rejection(not with timeout) */
+ if (err_code != AVDT_ERR_TIMEOUT)
+ {
+ p_scb->suspend_sup = FALSE;
+ }
/* drop the buffers queued in L2CAP */
L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
@@ -2507,10 +2592,14 @@ void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
/*
APPL_TRACE_DEBUG0("bta_av_rcfg_cfm");
*/
- if(err_code)
+ if (err_code)
{
APPL_TRACE_ERROR0("reconfig rejected, try close");
- p_scb->recfg_sup = FALSE;
+ /* Disable reconfiguration feature only with explicit rejection(not with timeout) */
+ if (err_code != AVDT_ERR_TIMEOUT)
+ {
+ p_scb->recfg_sup = FALSE;
+ }
/* started flag is FALSE when reconfigure command is sent */
/* drop the buffers queued in L2CAP */
L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
@@ -2518,6 +2607,8 @@ void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
}
else
{
+ /* update the codec info after rcfg cfm */
+ memcpy(p_scb->cfg.codec_info,p_data->str_msg.msg.reconfig_cfm.p_cfg->codec_info,AVDT_CODEC_SIZE);
/* take the SSM back to OPEN state */
bta_av_ssm_execute(p_scb, BTA_AV_STR_OPEN_OK_EVT, NULL);
}
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
index a47921af3..edf8b7fd3 100644
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -363,7 +363,7 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx)
** Returns BTA_AV_RSP_ACCEPT or BTA_AV_RSP_NOT_IMPL.
**
*******************************************************************************/
-static tBTA_AV_CODE bta_av_group_navi_supported(UINT8 len, UINT8 *p_data)
+static tBTA_AV_CODE bta_av_group_navi_supported(UINT8 len, UINT8 *p_data, BOOLEAN is_inquiry)
{
tBTA_AV_CODE ret=BTA_AV_RSP_NOT_IMPL;
UINT8 *p_ptr = p_data;
@@ -377,10 +377,18 @@ static tBTA_AV_CODE bta_av_group_navi_supported(UINT8 len, UINT8 *p_data)
if (u32 == AVRC_CO_METADATA)
{
- if (u16 <= AVRC_PDU_PREV_GROUP)
- ret = BTA_AV_RSP_ACCEPT;
+ if (is_inquiry)
+ {
+ if (u16 <= AVRC_PDU_PREV_GROUP)
+ ret = BTA_AV_RSP_IMPL_STBL;
+ }
else
- ret = BTA_AV_RSP_REJ;
+ {
+ if (u16 <= AVRC_PDU_PREV_GROUP)
+ ret = BTA_AV_RSP_ACCEPT;
+ else
+ ret = BTA_AV_RSP_REJ;
+ }
}
}
@@ -396,23 +404,34 @@ static tBTA_AV_CODE bta_av_group_navi_supported(UINT8 len, UINT8 *p_data)
** Returns BTA_AV_RSP_ACCEPT of supported, BTA_AV_RSP_NOT_IMPL if not.
**
*******************************************************************************/
-static tBTA_AV_CODE bta_av_op_supported(tBTA_AV_RC rc_id)
+static tBTA_AV_CODE bta_av_op_supported(tBTA_AV_RC rc_id, BOOLEAN is_inquiry)
{
tBTA_AV_CODE ret_code = BTA_AV_RSP_NOT_IMPL;
if (p_bta_av_rc_id)
{
- if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+ if (is_inquiry)
{
- ret_code = BTA_AV_RSP_ACCEPT;
+ if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+ {
+ ret_code = BTA_AV_RSP_IMPL_STBL;
+ }
}
- else if ((p_bta_av_cfg->rc_pass_rsp == BTA_AV_RSP_INTERIM) && p_bta_av_rc_id_ac)
+ else
{
- if (p_bta_av_rc_id_ac[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+ if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+ {
+ ret_code = BTA_AV_RSP_ACCEPT;
+ }
+ else if ((p_bta_av_cfg->rc_pass_rsp == BTA_AV_RSP_INTERIM) && p_bta_av_rc_id_ac)
{
- ret_code = BTA_AV_RSP_INTERIM;
+ if (p_bta_av_rc_id_ac[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+ {
+ ret_code = BTA_AV_RSP_INTERIM;
+ }
}
}
+
}
return ret_code;
}
@@ -824,11 +843,15 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
tBTA_AV av;
BT_HDR *p_pkt = NULL;
tAVRC_MSG_VENDOR *p_vendor = &p_data->rc_msg.msg.vendor;
+ BOOLEAN is_inquiry = ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) || p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ);
if (p_data->rc_msg.opcode == AVRC_OP_PASS_THRU)
{
/* if this is a pass thru command */
- if (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_CTRL)
+ if ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_CTRL) ||
+ (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) ||
+ (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ)
+ )
{
/* check if operation is supported */
if (p_data->rc_msg.msg.pass.op_id == AVRC_ID_VENDOR)
@@ -837,9 +860,11 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
}
else
{
- p_data->rc_msg.msg.hdr.ctype = bta_av_op_supported(p_data->rc_msg.msg.pass.op_id);
+ p_data->rc_msg.msg.hdr.ctype = bta_av_op_supported(p_data->rc_msg.msg.pass.op_id, is_inquiry);
}
+ APPL_TRACE_DEBUG1("ctype %d",p_data->rc_msg.msg.hdr.ctype)
+
/* send response */
if (p_data->rc_msg.msg.hdr.ctype != BTA_AV_RSP_INTERIM)
AVRC_PassRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.pass);
@@ -1335,17 +1360,10 @@ void bta_av_sig_chg(tBTA_AV_DATA *p_data)
{
mask = 1 << xx;
APPL_TRACE_DEBUG1("conn_lcb: 0x%x", p_cb->conn_lcb);
- if(!(mask & p_cb->conn_lcb))
- {
- if (!p_cb->p_scb[xx])
- {
- /* We do not have scb for this avdt connection. */
- /* Silently close the connection. */
- APPL_TRACE_ERROR0("av scb not available for avdt connection");
- AVDT_DisconnectReq (p_data->str_msg.bd_addr, NULL);
- return;
- }
+ /* look for a p_lcb with its p_scb registered */
+ if((!(mask & p_cb->conn_lcb)) && (p_cb->p_scb[xx] != NULL))
+ {
p_lcb = &p_cb->lcb[xx];
p_lcb->lidx = xx + 1;
bdcpy(p_lcb->addr, p_data->str_msg.bd_addr);
@@ -1382,6 +1400,16 @@ void bta_av_sig_chg(tBTA_AV_DATA *p_data)
break;
}
}
+
+ /* check if we found something */
+ if (xx == BTA_AV_NUM_LINKS)
+ {
+ /* We do not have scb for this avdt connection. */
+ /* Silently close the connection. */
+ APPL_TRACE_ERROR0("av scb not available for avdt connection");
+ AVDT_DisconnectReq (p_data->str_msg.bd_addr, NULL);
+ return;
+ }
}
}
#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
@@ -1516,9 +1544,10 @@ static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle)
**
** Function bta_av_check_peer_features
**
-** Description checks
+** Description check supported features on the peer device from the SDP record
+** and return the feature mask
**
-** Returns void
+** Returns tBTA_AV_FEAT peer device feature mask
**
*******************************************************************************/
tBTA_AV_FEAT bta_av_check_peer_features (UINT16 service_uuid)
@@ -1624,13 +1653,9 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
}
APPL_TRACE_DEBUG1("rc_handle %d", rc_handle);
+ /* check peer version and whether support CT and TG role */
peer_features = bta_av_check_peer_features (UUID_SERVCLASS_AV_REMOTE_CONTROL);
- if ((p_cb->features & BTA_AV_FEAT_ADV_CTRL) && ((peer_features&BTA_AV_FEAT_ADV_CTRL) == 0))
- {
- /* if we support advance control and peer does not, check their support on TG role
- * some implementation uses 1.3 on CT ans 1.4 on TG */
- peer_features |= bta_av_check_peer_features (UUID_SERVCLASS_AV_REM_CTRL_TARGET);
- }
+ peer_features |= bta_av_check_peer_features (UUID_SERVCLASS_AV_REM_CTRL_TARGET);
p_cb->disc = 0;
utl_freebuf((void **) &p_cb->p_disc_db);
diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c
index 793c77259..f589a8870 100644
--- a/bta/av/bta_av_cfg.c
+++ b/bta/av/bta_av_cfg.c
@@ -78,39 +78,6 @@ const UINT8 bta_av_meta_caps_evt_ids[] = {
#define BTA_AV_NUM_RC_EVT_IDS (sizeof(bta_av_meta_caps_evt_ids) / sizeof(bta_av_meta_caps_evt_ids[0]))
#endif /* BTA_AV_NUM_RC_EVT_IDS */
-
-#else /* !ANDROID_APP_INCLUDED */
-
-/* Note: if AVRC_SUPF_TG_GROUP_NAVI is set, bta_av_cfg.avrc_group should be TRUE */
-#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1)
-
-const UINT16 bta_av_audio_flush_to[] = {
- 120, /* 1 stream */
- 100, /* 2 streams */
- 80, /* 3 streams */
- 60, /* 4 streams */
- 40 /* 5 streams */
-}; /* AVDTP audio transport channel flush timeout */
-
-
-/*
- * If the number of event IDs is changed in this array, BTA_AV_ NUM_RC_EVT_IDS also needs to be changed.
- */
-const UINT8 bta_av_meta_caps_evt_ids[] = {
- AVRC_EVT_PLAY_STATUS_CHANGE,
- AVRC_EVT_TRACK_CHANGE,
- AVRC_EVT_TRACK_REACHED_END,
- AVRC_EVT_TRACK_REACHED_START,
- AVRC_EVT_PLAY_POS_CHANGED,
- AVRC_EVT_BATTERY_STATUS_CHANGE,
- AVRC_EVT_SYSTEM_STATUS_CHANGE,
- AVRC_EVT_APP_SETTING_CHANGE,
-};
-
-#ifndef BTA_AV_NUM_RC_EVT_IDS
-#define BTA_AV_NUM_RC_EVT_IDS 8
-#endif
-
#endif /* ANDROID_APP_INCLUDED */
/* the MTU for the AVRCP browsing channel */
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
index 9ce7b2a89..cd22bcb2d 100644
--- a/bta/av/bta_av_int.h
+++ b/bta/av/bta_av_int.h
@@ -170,7 +170,7 @@ typedef void (*tBTA_AV_CO_OPEN) (tBTA_AV_HNDL hndl,
tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
UINT16 mtu);
typedef void (*tBTA_AV_CO_CLOSE) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu);
-typedef void (*tBTA_AV_CO_START) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+typedef void (*tBTA_AV_CO_START) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr);
typedef void (*tBTA_AV_CO_STOP) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
typedef void * (*tBTA_AV_CO_DATAPATH) (tBTA_AV_CODEC codec_type,
UINT32 *p_len, UINT32 *p_timestamp);
@@ -504,6 +504,7 @@ typedef struct
tBTA_AV_API_OPEN open_api; /* Saved OPEN api message */
UINT8 wait; /* set 0x1, when getting Caps as ACP, set 0x2, when started */
UINT8 q_tag; /* identify the associated q_info union member */
+ BOOLEAN no_rtp_hdr; /* TRUE if add no RTP header*/
} tBTA_AV_SCB;
#define BTA_AV_RC_ROLE_MASK 0x10
diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c
index 085362dd4..749756d61 100644
--- a/bta/av/bta_av_main.c
+++ b/bta/av/bta_av_main.c
@@ -1191,9 +1191,9 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
if(event >= first_event)
{
#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
- APPL_TRACE_EVENT2("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event));
+ APPL_TRACE_VERBOSE2("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event));
#else
- APPL_TRACE_EVENT1("AV nsm event=0x%x", event);
+ APPL_TRACE_VERBOSE1("AV nsm event=0x%x", event);
#endif
/* non state machine events */
(*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);
@@ -1201,16 +1201,16 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT)
{
#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
- APPL_TRACE_EVENT2("AV sm event=0x%x(%s)", event, bta_av_evt_code(event));
+ APPL_TRACE_VERBOSE2("AV sm event=0x%x(%s)", event, bta_av_evt_code(event));
#else
- APPL_TRACE_EVENT1("AV sm event=0x%x", event);
+ APPL_TRACE_VERBOSE1("AV sm event=0x%x", event);
#endif
/* state machine events */
bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA *) p_msg);
}
else
{
- APPL_TRACE_EVENT1("handle=0x%x", p_msg->layer_specific);
+ APPL_TRACE_VERBOSE1("handle=0x%x", p_msg->layer_specific);
/* stream state machine events */
bta_av_ssm_execute( bta_av_hndl_to_scb(p_msg->layer_specific),
p_msg->event, (tBTA_AV_DATA *) p_msg);
diff --git a/bta/av/bta_av_ssm.c b/bta/av/bta_av_ssm.c
index a35a4b02a..407146efd 100644
--- a/bta/av/bta_av_ssm.c
+++ b/bta/av/bta_av_ssm.c
@@ -436,10 +436,10 @@ void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data)
}
#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
- APPL_TRACE_EVENT5("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
+ APPL_TRACE_VERBOSE5("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state));
#else
- APPL_TRACE_EVENT2("AV Sevent=0x%x state=%d", event, p_scb->state);
+ APPL_TRACE_VERBOSE2("AV Sevent=0x%x state=%d", event, p_scb->state);
#endif
/* look up the state table for the current state */
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 29b4ec279..0ade1cca6 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -92,7 +92,10 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status );
static BOOLEAN bta_dm_dev_blacklisted_for_switch (BD_ADDR remote_bd_addr);
static void bta_dm_delay_role_switch_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr);
+
+static void bta_dm_disable_search_and_disc(void);
#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
#if ((defined SMP_INCLUDED) && (SMP_INCLUDED == TRUE))
static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_DATA *p_data);
@@ -103,8 +106,13 @@ static void btm_dm_start_gatt_discovery ( BD_ADDR bd_addr);
static void bta_dm_cancel_gatt_discovery(BD_ADDR bd_addr);
static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
#endif
-#endif
+static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
+static void bta_dm_observe_cmpl_cb (void * p_result);
+#ifndef BTA_DM_BLE_ADV_CHNL_MAP
+#define BTA_DM_BLE_ADV_CHNL_MAP (BTM_BLE_ADV_CHNL_37|BTM_BLE_ADV_CHNL_38|BTM_BLE_ADV_CHNL_39)
+#endif
+#endif
extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8* p_uuid128);
const UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID] =
@@ -454,10 +462,9 @@ void bta_dm_disable (tBTA_DM_MSG *p_data)
BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);
bta_dm_disable_pm();
-
+ bta_dm_disable_search_and_disc();
bta_dm_cb.disabling = TRUE;
- bta_dm_search_cancel(NULL);
if(BTM_GetNumAclLinks()==0)
{
@@ -750,6 +757,58 @@ void bta_dm_add_device (tBTA_DM_MSG *p_data)
/*******************************************************************************
**
+** Function bta_dm_close_acl
+**
+** Description This function forces to close the connection to a remote device
+** and optionaly remove the device from security database if
+** required.
+****
+*******************************************************************************/
+void bta_dm_close_acl(tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_API_REMOVE_ACL *p_remove_acl = &p_data->remove_acl;
+ UINT8 index;
+
+ APPL_TRACE_DEBUG0("bta_dm_close_acl");
+
+ if (BTM_IsAclConnectionUp(p_remove_acl->bd_addr))
+ {
+ for (index = 0; index < bta_dm_cb.device_list.count; index ++)
+ {
+ if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, p_remove_acl->bd_addr))
+ break;
+ }
+ if (index != bta_dm_cb.device_list.count)
+ {
+ if (p_remove_acl->remove_dev)
+ bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("unknown device, remove ACL failed");
+ }
+ /* Disconnect the ACL link */
+ btm_remove_acl(p_remove_acl->bd_addr);
+ }
+ /* if to remove the device from security database ? do it now */
+ else if (p_remove_acl->remove_dev)
+ {
+ if (!BTM_SecDeleteDevice(p_remove_acl->bd_addr))
+ {
+ APPL_TRACE_ERROR0("delete device from security database failed.");
+ }
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+ /* need to remove all pending background connection if any */
+ BTA_GATTC_CancelOpen(0, p_remove_acl->bd_addr, FALSE);
+ /* remove all cached GATT information */
+ BTA_GATTC_Refresh(p_remove_acl->bd_addr);
+#endif
+ }
+ /* otherwise, no action needed */
+
+}
+/*******************************************************************************
+**
** Function bta_dm_bond
**
** Description Bonds with peer device
@@ -784,8 +843,14 @@ void bta_dm_bond (tBTA_DM_MSG *p_data)
*/
sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
if (status == BTM_SUCCESS)
+ {
sec_event.auth_cmpl.success = TRUE;
-
+ }
+ else
+ {
+ /* delete this device entry from Sec Dev DB */
+ bta_dm_remove_sec_dev_entry(p_data->bond.bd_addr);
+ }
bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
}
@@ -1148,11 +1213,6 @@ void bta_dm_search_start (tBTA_DM_MSG *p_data)
// bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len);
memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
}
-
- if (p_data->search.inq_params.mode & BTM_LIMITED_INQUIRY)
- p_data->search.inq_params.mode |= BTM_BLE_LIMITED_INQUIRY;
- else
- p_data->search.inq_params.mode |= BTM_BLE_GENERAL_INQUIRY;
#endif
result.status = BTM_StartInquiry( (tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb,
@@ -1200,7 +1260,7 @@ void bta_dm_search_cancel (tBTA_DM_MSG *p_data)
{
BTM_CancelRemoteDeviceName();
}
-#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
if (bta_dm_search_cb.gatt_disc_active)
{
bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
@@ -1311,6 +1371,65 @@ static void bta_dm_di_disc_callback(UINT16 result)
/*******************************************************************************
**
+** Function bta_dm_disable_search_and_disc
+**
+** Description Cancels an ongoing search or discovery for devices in case of
+** a Bluetooth disable
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_disable_search_and_disc (void)
+{
+ tBTA_DM_DI_DISC_CMPL di_disc;
+ tBTA_DM_MSG * p_msg;
+
+ if(BTM_IsInquiryActive()||(bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE))
+ {
+ BTM_CancelInquiry();
+ bta_dm_search_cancel_notify(NULL);
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+ bta_sys_sendmsg(p_msg);
+
+ }
+ }
+ /* If no Service Search going on then issue cancel remote name in case it is active */
+ else if (!bta_dm_search_cb.name_discover_done)
+ {
+ BTM_CancelRemoteDeviceName();
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+ else if(bta_dm_di_cb.p_di_db != NULL)
+ {
+ memset(&di_disc, 0, sizeof(tBTA_DM_DI_DISC_CMPL));
+ bdcpy(di_disc.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ di_disc.result = BTA_FAILURE;
+
+ bta_dm_di_cb.p_di_db = NULL;
+ bta_dm_search_cb.p_search_cback(BTA_DM_DI_DISC_CMPL_EVT, NULL);
+ }
+
+#if (BLE_INCLUDED == TRUE) && (BTA_GATT_INCLUDED == TRUE)
+ if (bta_dm_search_cb.gatt_disc_active)
+ {
+ bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
** Function bta_dm_di_disc
**
** Description This function queries a remote device for DI information.
@@ -1561,7 +1680,8 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
{
/* send result back to app now, one by one */
bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
- BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+ result.disc_ble_res.bd_name[BD_NAME_LEN] = 0;
result.disc_ble_res.service.len = service_uuid.len;
result.disc_ble_res.service.uu.uuid16 = service_uuid.uu.uuid16;
@@ -2022,7 +2142,7 @@ void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data)
{
BTM_CancelRemoteDeviceName();
}
-#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+#if (BLE_INCLUDED == TRUE) && (BTA_GATT_INCLUDED == TRUE)
if (bta_dm_search_cb.gatt_disc_active)
{
bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
@@ -2535,22 +2655,25 @@ static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name)
{
tBTA_DM_REM_NAME * p_msg;
- APPL_TRACE_DEBUG1("bta_dm_remname_cback name=<%s>", p_remote_name->remote_bd_name);
+ APPL_TRACE_DEBUG2("bta_dm_remname_cback len = %d name=<%s>", p_remote_name->length,
+ p_remote_name->remote_bd_name);
/* remote name discovery is done but it could be failed */
bta_dm_search_cb.name_discover_done = TRUE;
- BCM_STRNCPY_S((char*)bta_dm_search_cb.peer_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN-1));
- bta_dm_search_cb.peer_name[BD_NAME_LEN-1]=0;
+ BCM_STRNCPY_S((char*)bta_dm_search_cb.peer_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN));
+ bta_dm_search_cb.peer_name[BD_NAME_LEN]=0;
BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
-
+#if BLE_INCLUDED == TRUE
+ GAP_BleReadPeerPrefConnParams (bta_dm_search_cb.peer_bdaddr);
+#endif
if ((p_msg = (tBTA_DM_REM_NAME *) GKI_getbuf(sizeof(tBTA_DM_REM_NAME))) != NULL)
{
bdcpy (p_msg->result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
- BCM_STRNCPY_S((char*)p_msg->result.disc_res.bd_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN-1));
+ BCM_STRNCPY_S((char*)p_msg->result.disc_res.bd_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN));
/* make sure the string is null terminated */
- p_msg->result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+ p_msg->result.disc_res.bd_name[BD_NAME_LEN] = 0;
p_msg->hdr.event = BTA_DM_REMT_NAME_EVT;
bta_sys_sendmsg(p_msg);
@@ -2825,6 +2948,8 @@ static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev
{
bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
}
+ /* delete this device entry from Sec Dev DB */
+ bta_dm_remove_sec_dev_entry(bd_addr);
}
return BTM_SUCCESS;
@@ -3074,6 +3199,7 @@ static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data)
break;
case BTM_BL_UPDATE_EVT:
p_msg->busy_level = p_data->update.busy_level;
+ p_msg->busy_level_flags = p_data->update.busy_level_flags;
break;
case BTM_BL_ROLE_CHG_EVT:
p_msg->new_role = p_data->role_chg.new_role;
@@ -3219,6 +3345,7 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data)
if( bta_dm_cb.p_sec_cback )
{
conn.busy_level.level = p_data->acl_change.busy_level;
+ conn.busy_level.level_flags = p_data->acl_change.busy_level_flags;
bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);
}
return;
@@ -3319,6 +3446,8 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data)
issue_unpair_cb = TRUE;
}
+ conn.link_down.is_removed = bta_dm_cb.device_list.peer_device[i].remove_dev_pending;
+
for(; i<bta_dm_cb.device_list.count ; i++)
{
memcpy(&bta_dm_cb.device_list.peer_device[i], &bta_dm_cb.device_list.peer_device[i+1], sizeof(bta_dm_cb.device_list.peer_device[i]));
@@ -3351,6 +3480,16 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data)
bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1000);
}
}
+ if (conn.link_down.is_removed)
+ {
+ BTM_SecDeleteDevice(p_bda);
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+ /* need to remove all pending background connection */
+ BTA_GATTC_CancelOpen(0, p_bda, FALSE);
+ /* remove all cached GATT information */
+ BTA_GATTC_Refresh(p_bda);
+#endif
+ }
bdcpy(conn.link_down.bd_addr, p_bda);
conn.link_down.status = (UINT8) btm_get_acl_disc_reason_code();
@@ -3379,6 +3518,9 @@ static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle)
{
tBTA_SYS_HW_MSG *sys_enable_event;
+ /* disable the power managment module */
+ bta_dm_disable_pm();
+
/* register our callback to SYS HW manager */
bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
@@ -3573,6 +3715,44 @@ static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle)
/*******************************************************************************
**
+** Function bta_dm_remove_sec_dev_entry
+**
+** Description Removes device entry from Security device DB if ACL connection with
+** remtoe device does not exist, else schedule for dev entry removal upon
+ ACL close
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
+{
+ UINT16 index = 0;
+ if (BTM_IsAclConnectionUp(remote_bd_addr))
+ {
+ APPL_TRACE_DEBUG1("%s ACL is not down. Schedule for Dev Removal when ACL closes",
+ __FUNCTION__);
+ for (index = 0; index < bta_dm_cb.device_list.count; index ++)
+ {
+ if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, remote_bd_addr))
+ break;
+ }
+ if (index != bta_dm_cb.device_list.count)
+ {
+ bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1(" %s Device does not exist in DB", __FUNCTION__);
+ }
+ }
+ else
+ {
+ BTM_SecDeleteDevice (remote_bd_addr);
+ }
+}
+
+/*******************************************************************************
+**
** Function bta_dm_adjust_roles
**
** Description Adjust roles
@@ -3668,7 +3848,7 @@ static void bta_dm_adjust_roles(BOOLEAN delay_role_switch)
*******************************************************************************/
static char *bta_dm_get_remname(void)
{
- char *p_name = bta_dm_search_cb.peer_name;
+ char *p_name = (char *)bta_dm_search_cb.peer_name;
char *p_temp;
/* If the name isn't already stored, try retrieving from BTM */
@@ -4048,16 +4228,6 @@ static void bta_dm_set_eir (char *local_name)
free_eir_length -= p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 2;
}
- /* if Inquiry Tx Resp Power compiled */
- if((p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power) &&
- (free_eir_length >= 3))
- {
- UINT8_TO_STREAM(p, 2); /* Length field */
- UINT8_TO_STREAM(p, BTM_EIR_TX_POWER_LEVEL_TYPE);
- UINT8_TO_STREAM(p, *(p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power));
- free_eir_length -= 3;
- }
-
/* if Manufacturer Specific are provided in configuration */
if(( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len > 0 )
&&( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec )
@@ -4078,6 +4248,16 @@ static void bta_dm_set_eir (char *local_name)
p_length = NULL;
}
+ /* if Inquiry Tx Resp Power compiled */
+ if ((p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power) &&
+ (free_eir_length >= 3))
+ {
+ UINT8_TO_STREAM(p, 2); /* Length field */
+ UINT8_TO_STREAM(p, BTM_EIR_TX_POWER_LEVEL_TYPE);
+ UINT8_TO_STREAM(p, *(p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power));
+ free_eir_length -= 3;
+ }
+
if( free_eir_length )
UINT8_TO_STREAM(p, 0); /* terminator of significant part */
@@ -4352,6 +4532,74 @@ void bta_dm_set_afh_channel_assesment (tBTA_DM_MSG * p_data)
}
#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function bta_dm_observe_results_cb
+**
+** Description Callback for BLE Observe result
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir)
+{
+;
+ tBTA_DM_SEARCH result;
+ tBTM_INQ_INFO *p_inq_info;
+ UINT16 service_class;
+ APPL_TRACE_DEBUG0("bta_dm_observe_results_cb")
+
+ bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);
+ result.inq_res.rssi = p_inq->rssi;
+ result.inq_res.ble_addr_type = p_inq->ble_addr_type;
+ result.inq_res.inq_result_type = p_inq->inq_result_type;
+ result.inq_res.device_type = p_inq->device_type;
+
+ /* application will parse EIR to find out remote device name */
+ result.inq_res.p_eir = p_eir;
+
+ if((p_inq_info = BTM_InqDbRead(p_inq->remote_bd_addr)) != NULL)
+ {
+ /* initialize remt_name_not_required to FALSE so that we get the name by default */
+ result.inq_res.remt_name_not_required = FALSE;
+ }
+
+ if(bta_dm_search_cb.p_scan_cback)
+ bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_RES_EVT, &result);
+
+ if(p_inq_info)
+ {
+ /* application indicates if it knows the remote name, inside the callback
+ copy that to the inquiry data base*/
+ if(result.inq_res.remt_name_not_required)
+ p_inq_info->appl_knows_rem_name = TRUE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_observe_cmpl_cb
+**
+** Description Callback for BLE Observe complete
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_observe_cmpl_cb (void * p_result)
+{
+ tBTA_DM_SEARCH data;
+
+ APPL_TRACE_DEBUG0("bta_dm_observe_cmpl_cb");
+
+ data.inq_cmpl.num_resps = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;
+ if (bta_dm_search_cb.p_scan_cback)
+ {
+ bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
+ }
+}
+
#if (SMP_INCLUDED == TRUE)
/*******************************************************************************
**
@@ -4367,6 +4615,9 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
{
tBTM_STATUS status = BTM_SUCCESS;
tBTA_DM_SEC sec_event;
+ UINT8 i;
+
+ APPL_TRACE_DEBUG0("bta_dm_ble_smp_cback");
if (!bta_dm_cb.p_sec_cback)
return BTM_NOT_AUTHORIZED;
@@ -4394,13 +4645,15 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
case BTM_LE_SEC_REQUEST_EVT:
bdcpy(sec_event.ble_req.bd_addr, bda);
- BCM_STRNCPY_S((char*)sec_event.ble_req.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ BCM_STRNCPY_S((char*)sec_event.ble_req.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+ sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
bta_dm_cb.p_sec_cback(BTA_DM_BLE_SEC_REQ_EVT, &sec_event);
break;
case BTM_LE_KEY_NOTIF_EVT:
bdcpy(sec_event.key_notif.bd_addr, bda);
- BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+ sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
sec_event.key_notif.passkey = p_data->key_notif;
bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_NOTIF_EVT, &sec_event);
break;
@@ -4418,17 +4671,41 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
case BTM_LE_KEY_EVT:
bdcpy(sec_event.ble_key.bd_addr, bda);
sec_event.ble_key.key_type = p_data->key.key_type;
- memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
+
+ if (p_data->key.key_type == BTM_LE_KEY_PID)
+ {
+ for (i=0; i<BT_OCTET16_LEN; i++ )
+ {
+ sec_event.ble_key.key_value.pid_key.irk[i] = p_data->key.p_key_value->pid_key.irk[i];
+ }
+ sec_event.ble_key.key_value.pid_key.addr_type = p_data->key.p_key_value->pid_key.addr_type;
+ memcpy( &(sec_event.ble_key.key_value.pid_key.static_addr),
+ &(p_data->key.p_key_value->pid_key.static_addr),
+ sizeof (BD_ADDR));
+ }
+ else
+ {
+ memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
+ }
+ // memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE)); todo will crash
bta_dm_cb.p_sec_cback(BTA_DM_BLE_KEY_EVT, &sec_event);
break;
case BTM_LE_COMPLT_EVT:
bdcpy(sec_event.auth_cmpl.bd_addr, bda);
+ BCM_STRNCPY_S((char*)sec_event.auth_cmpl.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+
if (p_data->complt.reason != 0)
+ {
sec_event.auth_cmpl.fail_reason = BTA_DM_AUTH_CONVERT_SMP_CODE(((UINT8)p_data->complt.reason));
+ /* delete this device entry from Sec Dev DB */
+ bta_dm_remove_sec_dev_entry (bda);
+ }
else
+ {
sec_event.auth_cmpl.success = TRUE;
-
+ }
+ sec_event.auth_cmpl.privacy_enabled = p_data->complt.privacy_supported;
if (bta_dm_cb.p_sec_cback)
{
//bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
@@ -4618,6 +4895,43 @@ void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data)
p_data->ble_set_scan_params.scan_window);
}
+
+/*******************************************************************************
+**
+** Function bta_dm_ble_observe
+**
+** Description This function set the preferred connection scan parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_observe (tBTA_DM_MSG *p_data)
+{
+
+ tBTM_STATUS status;
+ if (p_data->ble_observe.start)
+ {
+ /*Save the callback to be called when a scan results are available */
+ bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback;
+ if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration,
+ bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb))!= BTM_SUCCESS)
+ {
+ tBTA_DM_SEARCH data;
+ APPL_TRACE_WARNING2(" %s BTM_BleObserve failed. status %d",__FUNCTION__,status);
+ data.inq_cmpl.num_resps = 0;
+ if (bta_dm_search_cb.p_scan_cback)
+ {
+ bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
+ }
+ }
+ }
+ else
+ {
+ bta_dm_search_cb.p_scan_cback = NULL;
+ BTM_BleObserve(FALSE, 0, NULL,NULL );
+ }
+}
+
#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
/*******************************************************************************
@@ -4682,6 +4996,7 @@ static void bta_dm_gatt_disc_result(tBTA_GATT_ID service_id)
/* send result back to app now, one by one */
bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ result.disc_ble_res.bd_name[BD_NAME_LEN] = 0;
memcpy(&result.disc_ble_res.service, &service_id.uuid, sizeof(tBT_UUID));
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
@@ -4719,6 +5034,8 @@ static void bta_dm_gatt_disc_complete(UINT16 conn_id, tBTA_GATT_STATUS status)
p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
p_msg->disc_result.result.disc_res.result = (status == BTA_GATT_OK) ? BTA_SUCCESS :BTA_FAILURE;
p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+ p_msg->disc_result.result.disc_res.num_uuids = 0;
+ p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
bta_dm_get_remname(), (BD_NAME_LEN-1));
@@ -4882,5 +5199,4 @@ static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
}
#endif /* BTA_GATT_INCLUDED */
-
#endif /* BLE_INCLUDED */
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 06e3b936c..aedbe8106 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -1572,6 +1572,42 @@ void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services, t
#endif
}
+/*******************************************************************************
+**
+** Function BTA_DmBleEnableRemotePrivacy
+**
+** Description Enable/disable privacy on a remote device
+**
+** Parameters: bd_addr - BD address of the peer
+** privacy_enable - enable/disabe privacy on remote device.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleEnableRemotePrivacy(BD_ADDR bd_addr, BOOLEAN privacy_enable)
+{
+#if BLE_INCLUDED == TRUE
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_DmBleConfigLocalPrivacy
+**
+** Description Enable/disable privacy on the local device
+**
+** Parameters: privacy_enable - enable/disabe privacy on remote device.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable)
+{
+#if BLE_INCLUDED == TRUE
+#endif
+}
+
/*******************************************************************************
**
@@ -1614,3 +1650,74 @@ void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
}
}
+/*******************************************************************************
+**
+** Function BTA_DmCloseACL
+**
+** Description This function force to close an ACL connection and remove the
+** device from the security database list of known devices.
+**
+** Parameters: bd_addr - Address of the peer device
+** remove_dev - remove device or not after link down
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev)
+{
+ tBTA_DM_API_REMOVE_ACL *p_msg;
+
+ APPL_TRACE_API0("BTA_DmCloseACL");
+
+ if ((p_msg = (tBTA_DM_API_REMOVE_ACL *) GKI_getbuf(sizeof(tBTA_DM_API_REMOVE_ACL))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_REMOVE_ACL));
+
+ p_msg->hdr.event = BTA_DM_API_REMOVE_ACL_EVT;
+
+ memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
+ p_msg->remove_dev = remove_dev;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmBleObserve
+**
+** Description This procedure keep the device listening for advertising
+** events from a broadcast device.
+**
+** Parameters start: start or stop observe.
+**
+** Returns void
+
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+ tBTA_DM_SEARCH_CBACK *p_results_cb)
+{
+#if BLE_INCLUDED == TRUE
+
+ tBTA_DM_API_BLE_OBSERVE *p_msg;
+
+ APPL_TRACE_API1("BTA_DmBleObserve:start = %d ", start);
+
+ if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_OBSERVE_EVT;
+ p_msg->start = start;
+ p_msg->duration = duration;
+ p_msg->p_cback = p_results_cb;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
index 5e2690955..a7c3cc4ec 100644
--- a/bta/dm/bta_dm_cfg.c
+++ b/bta/dm/bta_dm_cfg.c
@@ -240,14 +240,14 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] =
(BTA_DM_PM_SSR1), /* the SSR entry */
#endif
{
- {{BTA_DM_PM_SNIFF2, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_SNIFF2, 30000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close, used for HH suspend */
- {{BTA_DM_PM_SNIFF2, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
- {{BTA_DM_PM_SNIFF2, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_SNIFF2, 30000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF2, 30000}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
@@ -358,7 +358,9 @@ tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] =
{
/*max_lat, min_rmt_to, min_loc_to*/
{0, 0, 0}, /* BTA_DM_PM_SSR0 - do not use SSR */
- {1600, 2, 2}, /* BTA_DM_PM_SSR1 - HH */
+ {0, 0, 2}, /* BTA_DM_PM_SSR1 - HH, can NOT share entry with any other profile,
+ seting default max latency and min remote timeout as 0,
+ and always read individual device preference from HH module */
{1200, 2, 2}, /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
{360, 160, 2} /* BTA_DM_PM_SSR3 - HD */
};
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index 35b369d23..245c8712d 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -60,6 +60,7 @@ enum
BTA_DM_API_TX_INQPWR_EVT,
BTA_DM_ACL_CHANGE_EVT,
BTA_DM_API_ADD_DEVICE_EVT,
+ BTA_DM_API_REMOVE_ACL_EVT,
/* security API events */
BTA_DM_API_BOND_EVT,
@@ -77,6 +78,7 @@ enum
BTA_DM_API_SET_ENCRYPTION_EVT,
+
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
BTA_DM_API_PASKY_CANCEL_EVT,
#endif
@@ -96,6 +98,7 @@ enum
BTA_DM_API_BLE_SET_BG_CONN_TYPE,
BTA_DM_API_BLE_CONN_PARAM_EVT,
BTA_DM_API_BLE_SCAN_PARAM_EVT,
+ BTA_DM_API_BLE_OBSERVE_EVT,
#endif
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -140,7 +143,7 @@ typedef struct
typedef struct
{
BT_HDR hdr;
- char name[BD_NAME_LEN];
+ BD_NAME name; /* max 248 bytes name, plus must be Null terminated */
} tBTA_DM_API_SET_NAME;
/* data type for BTA_DM_API_SET_VISIBILITY_EVT */
@@ -353,6 +356,7 @@ typedef struct
BT_HDR hdr;
tBTM_BL_EVENT event;
UINT8 busy_level;
+ UINT8 busy_level_flags;
BOOLEAN is_new;
UINT8 new_role;
BD_ADDR bd_addr;
@@ -475,6 +479,20 @@ typedef struct
}tBTA_DM_API_BLE_CONN_PARAMS;
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR peer_bda;
+ BOOLEAN privacy_enable;
+
+}tBTA_DM_API_ENABLE_PRIVACY;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN privacy_enable;
+}tBTA_DM_API_LOCAL_PRIVACY;
+
/* set scan parameter for BLE connections */
typedef struct
{
@@ -483,7 +501,14 @@ typedef struct
UINT16 scan_window;
}tBTA_DM_API_BLE_SCAN_PARAMS;
-#endif
+/* Data type for start/stop observe */
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN start;
+ UINT16 duration;
+ tBTA_DM_SEARCH_CBACK * p_cback;
+}tBTA_DM_API_BLE_OBSERVE;
typedef struct
{
@@ -491,6 +516,25 @@ typedef struct
BOOLEAN enable_or_disable;
}tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT;
+
+/* set adv parameter for BLE advertising */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 adv_int_min;
+ UINT16 adv_int_max;
+ tBLE_BD_ADDR *p_dir_bda;
+}tBTA_DM_API_BLE_ADV_PARAMS;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 data_mask;
+ tBTA_BLE_ADV_DATA *p_adv_cfg;
+}tBTA_DM_API_SET_ADV_CONFIG;
+
+#endif
+
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
/* data type for BTA_DM_API_UPDATE_EIR_UUID_EVT */
typedef struct
@@ -510,6 +554,14 @@ typedef struct
}tBTA_DM_API_SET_EIR_CONFIG;
#endif
+/* data type for BTA_DM_API_REMOVE_ACL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ BOOLEAN remove_dev;
+}tBTA_DM_API_REMOVE_ACL;
+
/* union of all data types */
typedef union
{
@@ -580,6 +632,11 @@ typedef union
tBTA_DM_API_BLE_SET_BG_CONN_TYPE ble_set_bd_conn_type;
tBTA_DM_API_BLE_CONN_PARAMS ble_set_conn_params;
tBTA_DM_API_BLE_SCAN_PARAMS ble_set_scan_params;
+ tBTA_DM_API_BLE_OBSERVE ble_observe;
+ tBTA_DM_API_ENABLE_PRIVACY ble_remote_privacy;
+ tBTA_DM_API_LOCAL_PRIVACY ble_local_privacy;
+ tBTA_DM_API_BLE_ADV_PARAMS ble_set_adv_params;
+ tBTA_DM_API_SET_ADV_CONFIG ble_set_adv_data;
#endif
tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT set_afh_channel_assessment;
@@ -590,6 +647,7 @@ typedef union
#if (BTM_EIR_SERVER_INCLUDED == TRUE)
tBTA_DM_API_SET_EIR_CONFIG set_eir_cfg;
#endif
+ tBTA_DM_API_REMOVE_ACL remove_acl;
} tBTA_DM_MSG;
@@ -623,6 +681,7 @@ typedef struct
#endif
tBTA_DM_PM_ACTTION pm_mode_attempted;
tBTA_DM_PM_ACTTION pm_mode_failed;
+ BOOLEAN remove_dev_pending;
} tBTA_DM_PEER_DEVICE;
@@ -738,7 +797,7 @@ typedef struct
UINT16 state;
BD_ADDR peer_bdaddr;
BOOLEAN name_discover_done;
- char peer_name[BD_NAME_LEN];
+ BD_NAME peer_name;
TIMER_LIST_ENT search_timer;
UINT8 service_index;
tBTA_DM_MSG * p_search_queue; /* search or discover commands during search cancel stored here */
@@ -749,6 +808,7 @@ typedef struct
BOOLEAN sdp_search;
#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+ tBTA_DM_SEARCH_CBACK * p_scan_cback;
#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
tBTA_GATTC_IF client_if;
UINT8 num_uuid;
@@ -917,6 +977,7 @@ extern void bta_dm_tx_inqpower(tBTA_DM_MSG *p_data);
extern void bta_dm_acl_change(tBTA_DM_MSG *p_data);
extern void bta_dm_add_device (tBTA_DM_MSG *p_data);
extern void bta_dm_remove_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_close_acl(tBTA_DM_MSG *p_data);
extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data);
@@ -931,6 +992,7 @@ extern void bta_dm_security_grant (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_observe (tBTA_DM_MSG *p_data);
#endif
extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
extern void bta_dm_confirm(tBTA_DM_MSG *p_data);
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index a2fec0474..dc94c6c4c 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -58,6 +58,7 @@ const tBTA_DM_ACTION bta_dm_action[] =
bta_dm_tx_inqpower, /* 7 BTA_DM_API_SIG_STRENGTH_EVT */
bta_dm_acl_change, /* 8 BTA_DM_ACL_CHANGE_EVT */
bta_dm_add_device, /* 9 BTA_DM_API_ADD_DEVICE_EVT */
+ bta_dm_close_acl, /* 10 BTA_DM_API_ADD_DEVICE_EVT */
/* security API events */
bta_dm_bond, /* 10 BTA_DM_API_BOND_EVT */
@@ -94,6 +95,7 @@ const tBTA_DM_ACTION bta_dm_action[] =
bta_dm_ble_set_bg_conn_type,
bta_dm_ble_set_conn_params, /* BTA_DM_API_BLE_CONN_PARAM_EVT */
bta_dm_ble_set_scan_params, /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
+ bta_dm_ble_observe,
#endif
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -211,8 +213,8 @@ const UINT8 bta_dm_search_search_cancelling_st_table[][BTA_DM_SEARCH_NUM_COLS] =
/* INQUIRY_CMPL */ {BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
/* REMT_NAME_EVT */ {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IDLE},
/* SDP_RESULT_EVT */ {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IDLE},
-/* SEARCH_CMPL_EVT */ {BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
-/* DISCV_RES_EVT */ {BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* SEARCH_CMPL_EVT */ {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */ {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IDLE},
/* API_DI_DISCOVER_EVT */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_CANCELLING}
diff --git a/bta/dm/bta_dm_pm.c b/bta/dm/bta_dm_pm.c
index 8a993de22..cb5da6faf 100644
--- a/bta/dm/bta_dm_pm.c
+++ b/bta/dm/bta_dm_pm.c
@@ -42,9 +42,14 @@ static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index);
static BOOLEAN bta_dm_pm_is_sco_active ();
static void bta_dm_pm_hid_check(BOOLEAN bScoActive);
static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable);
+
#if (BTM_SSR_INCLUDED == TRUE)
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+#include "../hh/bta_hh_int.h"
+/* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile can use it */
+#define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1
+#endif
static void bta_dm_pm_ssr(BD_ADDR peer_addr);
-static void bta_dm_ssr_cfg_cback(UINT8 id, UINT8 app_id, UINT16 max_lat, UINT16 min_rmt_to);
#endif
tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
@@ -70,9 +75,6 @@ void bta_dm_init_pm(void)
{
bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)bta_dm_pm_cback);
-#if (BTM_SSR_INCLUDED == TRUE)
- bta_sys_ssr_cfg_register((tBTA_SYS_SSR_CFG_CBACK*)bta_dm_ssr_cfg_cback);
-#endif
BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id,
bta_dm_pm_btm_cback);
}
@@ -165,13 +167,16 @@ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id,
btm_status = BTM_ReadLocalVersion (&vers);
p_dev = bta_dm_find_peer_device(peer_addr);
- /* Disable/Enable sniff policy on the SCO link if sco Up/Down. Will be removed in 2.2*/
- if ((btm_status == BTM_SUCCESS) &&
- (vers.manufacturer == LMP_COMPID_BROADCOM) &&
- (vers.hci_version < HCI_PROTO_VERSION_2_0) &&
+ /* Disable/Enable sniff policy on the SCO link if sco Up/Down. Will be removed in 2.2*/
+ if ((p_dev) &&
((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) )
+ {
+ if ((btm_status == BTM_SUCCESS) &&
+ (vers.manufacturer == LMP_COMPID_BROADCOM) &&
+ (vers.hci_version < HCI_PROTO_VERSION_2_0))
{
- bta_dm_pm_set_sniff_policy(p_dev, (status == BTA_SYS_SCO_OPEN));
+ bta_dm_pm_set_sniff_policy(p_dev, (status == BTA_SYS_SCO_OPEN));
+ }
}
/* find if there is an power mode entry for the service */
@@ -272,7 +277,11 @@ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id,
}
#if (BTM_SSR_INCLUDED == TRUE)
- if(p_bta_dm_ssr_spec[index].max_lat)
+ if(p_bta_dm_ssr_spec[index].max_lat
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+ || index == BTA_DM_PM_SSR_HH
+#endif
+ )
{
bta_dm_pm_ssr(peer_addr);
}
@@ -559,7 +568,6 @@ static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index)
return TRUE;
}
-
/*******************************************************************************
**
** Function bta_dm_pm_ssr
@@ -599,6 +607,14 @@ static void bta_dm_pm_ssr(BD_ADDR peer_addr)
p_spec_cur = &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr];
p_spec = &p_bta_dm_ssr_spec[ssr];
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+ /* HH has the per connection SSR preference, already read the SSR params from BTA HH */
+ if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr == BTA_DM_PM_SSR_HH)
+ {
+ if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat, &p_spec_cur->min_rmt_to) == BTA_HH_ERR)
+ continue;
+ }
+#endif
if (p_spec_cur->max_lat < p_spec->max_lat ||
(ssr == BTA_DM_PM_SSR0 && p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr != BTA_DM_PM_SSR0))
{
@@ -617,44 +633,6 @@ static void bta_dm_pm_ssr(BD_ADDR peer_addr)
p_spec->min_rmt_to, p_spec->min_loc_to);
}
}
-/*******************************************************************************
-**
-** Function bta_dm_ssr_cfg_cback
-**
-** Description Conn change callback from sys for low power management
-**
-**
-** Returns void
-**
-*******************************************************************************/
-static void bta_dm_ssr_cfg_cback(UINT8 id, UINT8 app_id,
- UINT16 max_lat, UINT16 min_rmt_to)
-{
- tBTA_DM_SSR_SPEC *p_spec;
- UINT8 i, index;
- /* find if there is an power mode entry for the service */
- for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++)
- {
-
- if((p_bta_dm_pm_cfg[i].id == id)
- && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id )))
- break;
-
- }
- /* if no entries are there for the app_id and subystem in p_bta_dm_pm_spec*/
- if(i> p_bta_dm_pm_cfg[0].app_id)
- return;
-
- index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
-
- APPL_TRACE_DEBUG2("SSR parameter changed to: max_latency: %d min_tout: %d", max_lat, min_rmt_to);
-
- p_spec = &p_bta_dm_ssr_spec[index];
- p_spec->max_lat = max_lat;
- p_spec->min_rmt_to = min_rmt_to;
-}
-
-
#endif
/*******************************************************************************
**
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 5cacf03ef..25260f998 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -146,7 +146,6 @@ void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
(*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT, (tBTA_GATTC *)&cb_data);
}
}
-
/*******************************************************************************
**
** Function bta_gattc_start_if
@@ -167,8 +166,6 @@ void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.client_if );
}
}
-
-
/*******************************************************************************
**
** Function bta_gattc_deregister_cmpl
@@ -225,7 +222,6 @@ void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_IF client_if)
}
}
-
/*******************************************************************************
**
** Function bta_gattc_deregister
@@ -263,8 +259,6 @@ void bta_gattc_int_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
APPL_TRACE_ERROR1("bta_gattc_int_deregister Deregister Failed, unknown client_if: %d", p_data->int_dereg.client_if);
}
}
-
-
/*******************************************************************************
**
** Function bta_gattc_deregister
@@ -364,7 +358,7 @@ void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p
UINT16 event = ((BT_HDR *)p_msg)->event;
tBTA_GATTC_CLCB *p_clcb = NULL;
tBTA_GATTC_RCB *p_clreg;
- tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tBTA_GATTC cb_data;
if (p_msg->api_cancel_conn.is_direct)
{
@@ -381,7 +375,8 @@ void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p
if (p_clreg && p_clreg->p_cback)
{
- (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ cb_data.status = BTA_GATT_ERROR;
+ (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
}
}
@@ -391,7 +386,6 @@ void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p
}
}
-
/*******************************************************************************
**
** Function bta_gattc_cancel_open_error
@@ -403,10 +397,11 @@ void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p
*******************************************************************************/
void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
- tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+ tBTA_GATTC cb_data;
+ cb_data.status=BTA_GATT_ERROR;
- if ( p_clcb->p_rcb->p_cback )
- (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ if ( p_clcb && p_clcb->p_rcb && p_clcb->p_rcb->p_cback )
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
/*******************************************************************************
@@ -493,7 +488,7 @@ void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg
tBTA_GATTC_CLCB *p_clcb;
tBTA_GATTC_DATA gattc_data;
- if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE))
+ if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE))
{
/* alwaya call open to hold a connection */
if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE))
@@ -540,14 +535,15 @@ void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg
void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
{
tBTA_GATTC_RCB *p_clreg;
- tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tBTA_GATTC cb_data;
+ cb_data.status = BTA_GATT_ERROR;
/* remove the device from the bg connection mask */
- if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, FALSE))
+ if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, FALSE, FALSE))
{
if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, FALSE))
{
- status = BTA_GATT_OK;
+ cb_data.status = BTA_GATT_OK;
}
else
{
@@ -558,7 +554,7 @@ void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
if (p_clreg && p_clreg->p_cback)
{
- (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
}
@@ -573,16 +569,16 @@ void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
*******************************************************************************/
void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
- tBTA_GATT_STATUS status = BTA_GATT_OK;
+ tBTA_GATTC cb_data;
if ( p_clcb->p_rcb->p_cback )
{
- (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ cb_data.status = BTA_GATT_OK;
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
bta_gattc_clcb_dealloc(p_clcb);
}
-
/*******************************************************************************
**
** Function bta_gattc_cancel_open
@@ -594,7 +590,7 @@ void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
*******************************************************************************/
void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
- tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+ tBTA_GATTC cb_data;
if (GATT_CancelConnect(p_clcb->p_rcb->client_if, p_data->api_cancel_conn.remote_bda, TRUE))
{
@@ -604,7 +600,8 @@ void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
if ( p_clcb->p_rcb->p_cback )
{
- (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ cb_data.status = BTA_GATT_ERROR;
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
}
}
}
@@ -631,7 +628,8 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda);
/* start database cache if needed */
- if (p_clcb->p_srcb->p_srvc_cache == NULL)
+ if (p_clcb->p_srcb->p_srvc_cache == NULL ||
+ p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE)
{
if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
{
@@ -662,7 +660,6 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
}
}
}
-
/*******************************************************************************
**
** Function bta_gattc_close_fail
@@ -717,26 +714,16 @@ void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
if (p_clcb->status == BTA_GATT_OK)
{
- /* if the srcb is no longer needed, reset the state */
- if ( -- p_clcb->p_srcb->num_clcb == 0)
- {
- APPL_TRACE_DEBUG0("Update srcb connection status");
- p_clcb->p_srcb->connected = FALSE;
- p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
- }
-
bta_gattc_clcb_dealloc(p_clcb);
}
( * p_cback)(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC *)&cb_data);
- if (-- p_clreg->num_clcb == 0 && p_clreg->dereg_pending)
+ if (p_clreg->num_clcb == 0 && p_clreg->dereg_pending)
{
bta_gattc_deregister_cmpl(p_clreg, p_clreg->client_if);
}
-
}
-
/*******************************************************************************
**
** Function bta_gattc_reset_discover_st
@@ -746,7 +733,7 @@ void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
** Returns None.
**
*******************************************************************************/
-void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb)
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status)
{
tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
UINT8 i;
@@ -755,12 +742,29 @@ void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb)
{
if (p_cb->clcb[i].p_srcb == p_srcb)
{
+ p_cb->clcb[i].status = status;
bta_gattc_sm_execute(&p_cb->clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
}
}
}
/*******************************************************************************
**
+** Function bta_gattc_disc_close
+**
+** Description close a GATTC connection while in discovery state.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_disc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("Discovery cancel conn_id=%d",p_clcb->bta_conn_id);
+
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_ERROR);
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_API_CLOSE_EVT, p_data);
+}
+/*******************************************************************************
+**
** Function bta_gattc_set_discover_st
**
** Description when a SRCB start discovery, tell all related clcb and set
@@ -781,12 +785,29 @@ void bta_gattc_set_discover_st(tBTA_GATTC_SERV *p_srcb)
{
if (p_cb->clcb[i].p_srcb == p_srcb)
{
+ p_cb->clcb[i].status = BTA_GATT_OK;
p_cb->clcb[i].state = BTA_GATTC_DISCOVER_ST;
}
}
}
/*******************************************************************************
**
+** Function bta_gattc_restart_discover
+**
+** Description process service change in discovery state, mark up the auto
+** update flag and set status to be discovery cancel for current
+** discovery.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ p_clcb->status = BTA_GATT_CANCEL;
+ p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+}
+/*******************************************************************************
+**
** Function bta_gattc_start_discover
**
** Description Start a discovery on server.
@@ -796,16 +817,14 @@ void bta_gattc_set_discover_st(tBTA_GATTC_SERV *p_srcb)
*******************************************************************************/
void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
- /* pending operation, wait until it finishes */
- APPL_TRACE_DEBUG1("bta_gattc_start_discover conn_id=%d",p_clcb->bta_conn_id);
- if (p_clcb->p_q_cmd != NULL && p_clcb->auto_update == BTA_GATTC_NO_SCHEDULE &&
- p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
- {
- p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
- p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
- }
- else /* no pending operation, start discovery right away */
+ APPL_TRACE_DEBUG2("bta_gattc_start_discover conn_id=%d p_clcb->p_srcb->state = %d ",
+ p_clcb->bta_conn_id, p_clcb->p_srcb->state);
+
+ if (((p_clcb->p_q_cmd == NULL || p_clcb->auto_update == BTA_GATTC_REQ_WAITING) &&
+ p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) ||
+ p_clcb->p_srcb->state == BTA_GATTC_SERV_DISC)
+ /* no pending operation, start discovery right away */
{
p_clcb->auto_update = BTA_GATTC_NO_SCHEDULE;
@@ -814,15 +833,19 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
/* clear the service change mask */
p_clcb->p_srcb->srvc_hdl_chg = FALSE;
p_clcb->p_srcb->update_count = 0;
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC_ACT;
/* set all srcb related clcb into discovery ST */
bta_gattc_set_discover_st(p_clcb->p_srcb);
- if ( bta_gattc_init_cache(p_clcb->p_srcb) ||
- bta_gattc_discover_pri_service(p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL) != BTA_GATT_OK)
+ if ((p_clcb->status = bta_gattc_init_cache(p_clcb->p_srcb)) == BTA_GATT_OK)
+ {
+ p_clcb->status = bta_gattc_discover_pri_service(p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL);
+ }
+ if (p_clcb->status != BTA_GATT_OK)
{
APPL_TRACE_ERROR0("discovery on server failed");
- bta_gattc_reset_discover_st(p_clcb->p_srcb);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
}
}
else
@@ -830,6 +853,15 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
APPL_TRACE_ERROR0("unknown device, can not start discovery");
}
}
+ /* pending operation, wait until it finishes */
+ else
+ {
+ p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+
+ if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+ p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
+ }
+
}
/*******************************************************************************
**
@@ -850,11 +882,31 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
#endif
p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
+ if (p_clcb->status != GATT_SUCCESS)
+ {
+ /* clean up cache */
+ if(p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache)
+ {
+ while (p_clcb->p_srcb->cache_buffer.p_first)
+ {
+ GKI_freebuf (GKI_dequeue (&p_clcb->p_srcb->cache_buffer));
+ }
+ p_clcb->p_srcb->p_srvc_cache = NULL;
+ }
+
+ /* used to reset cache in application */
+ bta_gattc_co_cache_reset(p_clcb->p_srcb->server_bda);
+ }
/* release pending attribute list buffer */
utl_freebuf((void **)&p_clcb->p_srcb->p_srvc_list);
+ if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING)
+ {
+ /* start discovery again */
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+ }
/* get any queued command to proceed */
- if (p_q_cmd != NULL)
+ else if (p_q_cmd != NULL)
{
p_clcb->p_q_cmd = NULL;
@@ -1063,7 +1115,6 @@ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
}
}
}
-
/*******************************************************************************
**
** Function bta_gattc_confirm
@@ -1220,8 +1271,6 @@ void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
( *p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT, &cb_data);
}
-
-
/*******************************************************************************
**
** Function bta_gattc_op_cmpl
@@ -1384,6 +1433,7 @@ void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
}
else
{
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
/* cache open failure, start discovery */
bta_gattc_start_discover(p_clcb, NULL);
}
@@ -1401,7 +1451,7 @@ void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
p_clcb->p_srcb->attr_index = 0;
bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, p_clcb->bta_conn_id);
- bta_gattc_reset_discover_st(p_clcb->p_srcb);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
}
}
@@ -1431,7 +1481,7 @@ void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
if (p_data->ci_load.status == BTA_GATT_OK)
{
p_clcb->p_srcb->attr_index = 0;
- bta_gattc_reset_discover_st(p_clcb->p_srcb);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
}
else /* load more */
@@ -1446,6 +1496,7 @@ void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
}
else
{
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
p_clcb->p_srcb->attr_index = 0;
/* cache open failure, start discovery */
bta_gattc_start_discover(p_clcb, NULL);
@@ -1469,10 +1520,9 @@ void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
p_clcb->p_srcb->attr_index = 0;
bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
- bta_gattc_reset_discover_st(p_clcb->p_srcb);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
}
}
-
/*******************************************************************************
**
** Function bta_gattc_fail
@@ -1504,20 +1554,28 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
{
BT_HDR *p_buf;
tBTA_GATTC_CLCB *p_clcb = NULL;
-
+#if BLE_INCLUDED == TRUE
+ UINT8 role ;
+#endif
APPL_TRACE_DEBUG4("bta_gattc_conn_cback: cif = %d connected = %d conn_id = %d reaosn = 0x%04x",
gattc_if, connected, conn_id, reason);
if (connected)
{
+#if BLE_INCLUDED == TRUE
+ role = L2CA_GetBleConnRole(bda);
+
+ if (role == HCI_ROLE_SLAVE)
+ bta_gattc_conn_find_alloc(bda);
+#endif
+
/* outgoing connection : locate a logic channel */
if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL)
{
-
#if BLE_INCLUDED == TRUE
- /* for a background connection */
- if (L2CA_GetBleConnRole(bda)== HCI_ROLE_MASTER &&
- bta_gattc_check_bg_conn(gattc_if, bda))
+ /* for a background connection or listening connection */
+ if (/* L2CA_GetBleConnRole(bda)== HCI_ROLE_MASTER && */
+ bta_gattc_check_bg_conn(gattc_if, bda, role))
{
/* allocate a new channel */
p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
@@ -1539,10 +1597,13 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
}
else
{
+#if BLE_INCLUDED == TRUE
+ bta_gattc_conn_dealloc(bda);
+#endif
/* connection attempt timeout, send connection callback event */
if (reason == GATT_CONN_CANCEL )
{
- p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
+ p_clcb = bta_gattc_find_alloc_clcb(gattc_if, bda);
p_clcb->bta_conn_id = conn_id;
}
if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL)
@@ -1564,6 +1625,55 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
}
/*******************************************************************************
**
+** Function bta_gattc_process_api_refresh
+**
+** Description process refresh API to delete cache and start a new discovery
+** if currently connected.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+ tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_conn.remote_bda);
+ tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
+ BOOLEAN found = FALSE;
+ UINT8 i;
+
+ if (p_srvc_cb != NULL)
+ {
+ /* try to find a CLCB */
+ if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0)
+ {
+ for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+ {
+ if (p_clcb->in_use && p_clcb->p_srcb == p_srvc_cb)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ {
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+ return;
+ }
+ }
+ /* in all other cases, mark it and delete the cache */
+ if (p_srvc_cb->p_srvc_cache != NULL)
+ {
+ while (p_srvc_cb->cache_buffer.p_first)
+ GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+ p_srvc_cb->p_srvc_cache = NULL;
+ }
+ }
+ /* used to reset cache in application */
+ bta_gattc_co_cache_reset(p_msg->api_conn.remote_bda);
+
+}
+/*******************************************************************************
+**
** Function bta_gattc_process_srvc_chg_ind
**
** Description process service change indication.
@@ -1624,7 +1734,6 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
/* notify applicationf or service change */
if (p_clrcb->p_cback != NULL)
{
- APPL_TRACE_ERROR0("bta_gattc_process_srvc_chg_ind 2");
(* p_clrcb->p_cback)(BTA_GATTC_SRVC_CHG_EVT, (tBTA_GATTC *)p_srcb->server_bda);
}
@@ -1746,7 +1855,6 @@ void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPL
APPL_TRACE_ERROR1("Indi/Notif for Unknown handle[0x%04x], can not find in local cache.", handle);
}
}
-
/*******************************************************************************
**
** Function bta_gattc_cmpl_cback
@@ -1799,4 +1907,45 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS
return;
}
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function bta_gattc_init_clcb_conn
+**
+** Description Initaite a BTA CLCB connection
+**
+** Returns void
+**
+********************************************************************************/
+void bta_gattc_init_clcb_conn(UINT8 cif, BD_ADDR remote_bda)
+{
+ tBTA_GATTC_CLCB *p_clcb = NULL;
+ tBTA_GATTC_DATA gattc_data;
+ UINT16 conn_id;
+
+ /* should always get the connection ID */
+ if (GATT_GetConnIdIfConnected(cif, remote_bda,&conn_id) == FALSE)
+ {
+ APPL_TRACE_ERROR0("bta_gattc_init_clcb_conn ERROR: not a connected device");
+ return;
+ }
+
+ /* initaite a new connection here */
+ if ((p_clcb = bta_gattc_clcb_alloc(cif, remote_bda)) != NULL)
+ {
+ gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
+
+ gattc_data.api_conn.client_if = cif;
+ memcpy(gattc_data.api_conn.remote_bda, remote_bda, BD_ADDR_LEN);
+ gattc_data.api_conn.is_direct = TRUE;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_API_OPEN_EVT, &gattc_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("No resources");
+ }
+}
+
+#endif /* #if BLE_INCLUDED == TRUE */
#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
index 1cace7d6a..59a9544d4 100644
--- a/bta/gatt/bta_gattc_api.c
+++ b/bta/gatt/bta_gattc_api.c
@@ -32,6 +32,14 @@
#include "bta_gatt_api.h"
#include "bta_gattc_int.h"
+
+/*****************************************************************************
+** Externs
+*****************************************************************************/
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTC_CB bta_gattc_cb;
+#endif
+
/*****************************************************************************
** Constants
*****************************************************************************/
@@ -44,6 +52,22 @@ static const tBTA_SYS_REG bta_gatt_reg =
/*******************************************************************************
**
+** Function BTA_GATTC_Init
+**
+** Description This function is called to initalize GATTC module
+**
+** Parameters None
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_Init()
+{
+ memset(&bta_gattc_cb, 0, sizeof(tBTA_GATTC_CB));
+}
+
+/*******************************************************************************
+**
** Function BTA_GATTC_AppRegister
**
** Description This function is called to register application callbacks
@@ -232,7 +256,7 @@ void BTA_GATTC_ServiceSearchRequest (UINT16 conn_id, tBT_UUID *p_srvc_uuid)
**
** Function BTA_GATTC_GetFirstChar
**
-** Description This function is called to find the first charatceristic of the
+** Description This function is called to find the first characteristic of the
** service on the given server.
**
** Parameters conn_id: connection ID which identify the server.
@@ -270,7 +294,7 @@ tBTA_GATT_STATUS BTA_GATTC_GetFirstChar (UINT16 conn_id, tBTA_GATT_SRVC_ID *p_s
**
** Function BTA_GATTC_GetNextChar
**
-** Description This function is called to find the next charatceristic of the
+** Description This function is called to find the next characteristic of the
** service on the given server.
**
** Parameters conn_id: connection ID which identify the server.
@@ -314,8 +338,8 @@ tBTA_GATT_STATUS BTA_GATTC_GetNextChar (UINT16 conn_id,
**
** Function BTA_GATTC_GetFirstCharDescr
**
-** Description This function is called to find the first charatceristic descriptor of the
-** charatceristic on the given server.
+** Description This function is called to find the first characteristic descriptor of the
+** characteristic on the given server.
**
** Parameters conn_id: connection ID which identify the server.
** p_char_id: the characteristic ID of which the descriptor is belonged to.
@@ -358,8 +382,8 @@ tBTA_GATT_STATUS BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_I
**
** Function BTA_GATTC_GetNextCharDescr
**
-** Description This function is called to find the next charatceristic of the
-** service on the given server.
+** Description This function is called to find the next characteristic descriptor
+** of the characterisctic.
**
** Parameters conn_id: connection ID which identify the server.
** p_start_descr_id: start the characteristic search from the next record
@@ -667,7 +691,10 @@ void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
tBTA_GATT_AUTH_REQ auth_req)
{
tBTA_GATTC_API_WRITE *p_buf;
- UINT16 len = sizeof(tBTA_GATTC_API_WRITE) + p_data->len;
+ UINT16 len = sizeof(tBTA_GATTC_API_WRITE);
+
+ if (p_data != NULL)
+ len += p_data->len;
if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf(len)) != NULL)
{
@@ -789,7 +816,7 @@ void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id)
tBTA_GATTC_API_CONFIRM *p_buf;
APPL_TRACE_API3("BTA_GATTC_SendIndConfirm conn_id=%d service uuid1=0x%x char uuid=0x%x",
- conn_id, p_char_id->srvc_id.id.uuid.uu.uuid16, p_char_id->char_id.uuid.uu.uuid16); //toto
+ conn_id, p_char_id->srvc_id.id.uuid.uu.uuid16, p_char_id->char_id.uuid.uu.uuid16);
if ((p_buf = (tBTA_GATTC_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_GATTC_API_CONFIRM))) != NULL)
{
@@ -841,22 +868,39 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
{
for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
{
- if (!p_clreg->notif_reg[i].in_use)
+ if ( p_clreg->notif_reg[i].in_use &&
+ !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
+ bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
{
- memset(&p_clreg->notif_reg, 0, sizeof(tBTA_GATTC_NOTIF_REG));
-
- p_clreg->notif_reg[i].in_use = TRUE;
- memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);
- memcpy(&p_clreg->notif_reg[i].char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
-
+ APPL_TRACE_WARNING0("notification already registered");
status = BTA_GATT_OK;
break;
}
}
- if (i == BTA_GATTC_NOTIF_REG_MAX)
+ if (status != BTA_GATT_OK)
{
- status = BTA_GATT_NO_RESOURCES;
- APPL_TRACE_ERROR0("Max Notification Reached, registration failed.");
+ for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+ {
+ if (!p_clreg->notif_reg[i].in_use)
+ {
+ memset((void *)&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+
+ p_clreg->notif_reg[i].in_use = TRUE;
+ memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);
+
+ p_clreg->notif_reg[i].char_id.srvc_id.is_primary = p_char_id->srvc_id.is_primary;
+ bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.srvc_id.id, &p_char_id->srvc_id.id);
+ bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.char_id, &p_char_id->char_id);
+
+ status = BTA_GATT_OK;
+ break;
+ }
+ }
+ if (i == BTA_GATTC_NOTIF_REG_MAX)
+ {
+ status = BTA_GATT_NO_RESOURCES;
+ APPL_TRACE_ERROR0("Max Notification Reached, registration failed.");
+ }
}
}
else
@@ -905,10 +949,9 @@ tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
{
if (p_clreg->notif_reg[i].in_use &&
!memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
- !memcmp(&p_clreg->notif_reg[i].char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID)))
+ bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
{
APPL_TRACE_DEBUG0("Deregistered.");
-
memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
status = BTA_GATT_OK;
break;
@@ -931,4 +974,31 @@ tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
return status;
}
+/*******************************************************************************
+**
+** Function BTA_GATTC_Refresh
+**
+** Description Refresh the server cache of the remote device
+**
+** Parameters remote_bda: remote device BD address.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTC_Refresh(BD_ADDR remote_bda)
+{
+ tBTA_GATTC_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTC_API_REFRESH_EVT;
+
+ memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
#endif /* BTA_GATT_INCLUDED */
+
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
index 3774df4a6..7b87afe99 100644
--- a/bta/gatt/bta_gattc_cache.c
+++ b/bta/gatt/bta_gattc_cache.c
@@ -303,10 +303,6 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE);
-#if 0
-//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
- bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
-#endif
return status;
}
/*******************************************************************************
@@ -335,6 +331,12 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
APPL_TRACE_DEBUG2("free byte = %d, req %d bytes.", p_srvc_cb->free_byte, len);
#endif
+ if (p_srvc_cb->p_cur_srvc == NULL)
+ {
+ APPL_TRACE_ERROR0("Illegal action to add char/descr/incl srvc before adding a service!");
+ return GATT_WRONG_STATE;
+ }
+
if (p_srvc_cb->free_byte < len)
{
if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
@@ -381,10 +383,6 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
p_srvc_cb->p_cur_srvc->p_last_attr = p_attr;
-#if 0
-//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
- bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
-#endif
return status;
}
@@ -578,7 +576,6 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
conn_id, TRUE);
- //bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
}
/*******************************************************************************
**
@@ -935,8 +932,8 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
case GATT_DISC_SRVC_BY_UUID:
bta_gattc_add_srvc_to_list(p_srvc_cb,
p_data->handle,
- p_data->value.handle,
- p_data->type,
+ p_data->value.group_value.e_handle,
+ p_data->value.group_value.service_type,
TRUE);
break;
@@ -980,7 +977,14 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
{
tBTA_GATTC_SERV * p_srvc_cb;
+ tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
+ {
+ p_clcb->status = status;
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+ return;
+ }
p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
if (p_srvc_cb != NULL)
@@ -988,6 +992,7 @@ void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT
switch (disc_type)
{
case GATT_DISC_SRVC_ALL:
+ case GATT_DISC_SRVC_BY_UUID:
#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
#endif
@@ -1031,7 +1036,7 @@ UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service
tBT_UUID attr_uuid;
BOOLEAN char_map = FALSE, done = FALSE;
- while (p_cache && !done)
+ while (p_service_id && p_cache && !done)
{
#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]",
@@ -1040,9 +1045,7 @@ UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service
#endif
p_attr = p_cache->p_attr;
- if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, TRUE) &&
- p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id &&
- p_cache->service_uuid.is_primary == p_service_id->is_primary)
+ if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
{
for (j = 0; p_attr; j ++)
{
@@ -1210,12 +1213,12 @@ void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid)
{
if (bta_gattc_uuid_compare(uuid, p_cache->service_uuid.id.uuid, FALSE))
{
-//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
APPL_TRACE_DEBUG3("found service [0x%04x], inst[%d] handle [%d]",
p_cache->service_uuid.id.uuid.uu.uuid16,
p_cache->service_uuid.id.inst_id,
p_cache->s_handle);
-//#endif
+#endif
if (p_clcb->p_rcb->p_cback)
{
memset(&cb_data, 0, sizeof(tBTA_GATTC));
@@ -1224,7 +1227,6 @@ void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid)
memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid ,sizeof(tBTA_GATT_SRVC_ID));
(* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
- //todo (tBTA_GATTC *)&p_cache->service_uuid);
}
}
p_cache = p_cache->p_next;
@@ -1260,11 +1262,9 @@ static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
if (p_uuid_cond)
memcpy(&uuid_cond, p_uuid_cond, sizeof(tBT_UUID));
- for (i = 0; p_cache <= p_srcb->p_cur_srvc && p_cache && status != BTA_GATT_OK; i ++)
+ for (i = 0; p_cache && status != BTA_GATT_OK; i ++)
{
- if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, FALSE) &&
- p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id &&
- p_service_id->is_primary == p_cache->service_uuid.is_primary)
+ if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
{
#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
APPL_TRACE_DEBUG2("found matching service [0x%04x], inst[%d]",
@@ -1399,8 +1399,6 @@ tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
/* lock other GKI task */
GKI_sched_lock();
- APPL_TRACE_DEBUG0("bta_gattc_query_cache");
-
if (p_clcb != NULL )
{
if (p_clcb->state == BTA_GATTC_CONN_ST)
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 407e5d878..118b906a9 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -51,6 +51,7 @@ enum
BTA_GATTC_API_SEARCH_EVT,
BTA_GATTC_API_CONFIRM_EVT,
BTA_GATTC_API_READ_MULTI_EVT,
+ BTA_GATTC_API_REFRESH_EVT,
BTA_GATTC_INT_CONN_EVT,
BTA_GATTC_INT_DISCOVER_EVT,
@@ -74,14 +75,16 @@ typedef UINT16 tBTA_GATTC_INT_EVT;
/* max client application GATTC can support */
#ifndef BTA_GATTC_CL_MAX
-#define BTA_GATTC_CL_MAX 4
+#define BTA_GATTC_CL_MAX 10
#endif
/* max known devices GATTC can support */
#ifndef BTA_GATTC_KNOWN_SR_MAX
-#define BTA_GATTC_KNOWN_SR_MAX 4
+#define BTA_GATTC_KNOWN_SR_MAX 10
#endif
+#define BTA_GATTC_CONN_MAX GATT_MAX_PHY_CHANNEL
+
#ifndef BTA_GATTC_CLCB_MAX
#define BTA_GATTC_CLCB_MAX GATT_CL_MAX_LCB
#endif
@@ -268,6 +271,8 @@ typedef struct
#define BTA_GATTC_SERV_IDLE 0
#define BTA_GATTC_SERV_LOAD 1
#define BTA_GATTC_SERV_SAVE 2
+#define BTA_GATTC_SERV_DISC 3
+#define BTA_GATTC_SERV_DISC_ACT 4
UINT8 state;
@@ -348,11 +353,19 @@ typedef struct
BOOLEAN in_use;
BD_ADDR remote_bda;
tBTA_GATTC_CIF_MASK cif_mask;
+ tBTA_GATTC_CIF_MASK cif_adv_mask;
}tBTA_GATTC_BG_TCK;
typedef struct
{
+ BOOLEAN in_use;
+ BD_ADDR remote_bda;
+}tBTA_GATTC_CONN;
+
+typedef struct
+{
+ tBTA_GATTC_CONN conn_track[BTA_GATTC_CONN_MAX];
tBTA_GATTC_BG_TCK bg_track[BTA_GATTC_KNOWN_SR_MAX];
tBTA_GATTC_RCB cl_rcb[BTA_GATTC_CL_MAX];
@@ -402,6 +415,7 @@ extern void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_disc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
@@ -420,13 +434,15 @@ extern void bta_gattc_ci_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
extern void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA * p_msg);
extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg);
extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data);
extern void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
BD_ADDR remote_bda, UINT16 conn_id);
+extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
/* utility functions */
-extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda); //todo
+extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda);
extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id);
extern tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
extern void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb);
@@ -443,10 +459,14 @@ extern BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_pr
extern void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR *p_attr, tBT_UUID *p_uuid);
extern BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY *p_notify);
extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid, tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value);
-extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN add);
-extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
+extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR_PTR remote_bda, BOOLEAN add, BOOLEAN is_listen);
+extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, UINT8 role);
extern UINT8 bta_gattc_num_reg_app(void);
extern void bta_gattc_clear_notif_registration(UINT16 conn_id);
+extern tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda);
+extern BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar);
+extern BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar);
+extern void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src);
/* discovery functions */
extern void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
@@ -461,4 +481,10 @@ extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index);
extern BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
+
+extern tBTA_GATTC_CONN * bta_gattc_conn_alloc(BD_ADDR remote_bda);
+extern tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda);
+extern tBTA_GATTC_CONN * bta_gattc_conn_find_alloc(BD_ADDR remote_bda);
+extern BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda);
+
#endif /* BTA_GATTC_INT_H */
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
index a1fb536d6..01a0224ce 100644
--- a/bta/gatt/bta_gattc_main.c
+++ b/bta/gatt/bta_gattc_main.c
@@ -42,7 +42,6 @@ enum
{
BTA_GATTC_OPEN,
BTA_GATTC_OPEN_FAIL,
- //BTA_GATTC_OPEN_FAIL_IN_CONN, //<--- need to remove this?
BTA_GATTC_OPEN_ERROR,
BTA_GATTC_CANCEL_OPEN,
BTA_GATTC_CANCEL_OPEN_OK,
@@ -68,6 +67,8 @@ enum
BTA_GATTC_CI_SAVE,
BTA_GATTC_CACHE_OPEN,
BTA_GATTC_IGNORE_OP_CMPL,
+ BTA_GATTC_DISC_CLOSE,
+ BTA_GATTC_RESTART_DISCOVER,
BTA_GATTC_IGNORE
};
@@ -79,7 +80,6 @@ const tBTA_GATTC_ACTION bta_gattc_action[] =
{
bta_gattc_open,
bta_gattc_open_fail,
- //bta_gattc_open_fail_in_conn, //<--- need to remove this?
bta_gattc_open_error,
bta_gattc_cancel_open,
bta_gattc_cancel_open_ok,
@@ -104,7 +104,9 @@ const tBTA_GATTC_ACTION bta_gattc_action[] =
bta_gattc_ci_load,
bta_gattc_ci_save,
bta_gattc_cache_open,
- bta_gattc_ignore_op_cmpl
+ bta_gattc_ignore_op_cmpl,
+ bta_gattc_disc_close,
+ bta_gattc_restart_discover
};
@@ -131,6 +133,8 @@ static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] =
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
@@ -163,6 +167,7 @@ static const UINT8 bta_gattc_st_w4_conn[][BTA_GATTC_NUM_COLS] =
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
@@ -190,11 +195,13 @@ static const UINT8 bta_gattc_st_connected[][BTA_GATTC_NUM_COLS] =
/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_WRITE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_EXEC, BTA_GATTC_CONN_ST},
-/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST}, //BTA_GATTC_CLOSING_ST
+/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_SEARCH, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_CONFIRM, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_READ_MULTI, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
+
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_START_DISCOVER, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
@@ -222,13 +229,15 @@ static const UINT8 bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] =
/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
-/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST }, //BTA_GATTC_CLOSING_ST
+/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_DISC_CLOSE, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_CONFIRM, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
+
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
-/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_START_DISCOVER, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_RESTART_DISCOVER, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_DISC_CMPL, BTA_GATTC_CONN_ST},
/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE_OP_CMPL, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
@@ -367,6 +376,10 @@ BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
bta_gattc_process_api_open_cancel(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
+ case BTA_GATTC_API_REFRESH_EVT:
+ bta_gattc_process_api_refresh(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
default:
if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific))
!= NULL)
@@ -450,7 +463,8 @@ static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code)
return "BTA_GATTC_API_REG_EVT";
case BTA_GATTC_API_DEREG_EVT:
return "BTA_GATTC_API_DEREG_EVT";
-
+ case BTA_GATTC_API_REFRESH_EVT:
+ return "BTA_GATTC_API_REFRESH_EVT";
default:
return "unknown GATTC event code";
}
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
index a36e26cd2..4749f21e5 100644
--- a/bta/gatt/bta_gattc_utils.c
+++ b/bta/gatt/bta_gattc_utils.c
@@ -221,6 +221,7 @@ tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_b
#endif
p_clcb = &bta_gattc_cb.clcb[i_clcb];
p_clcb->in_use = TRUE;
+ p_clcb->status = BTA_GATT_OK;
bdcpy(p_clcb->bda, remote_bda);
p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
@@ -275,18 +276,23 @@ tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remo
*******************************************************************************/
void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
{
+ tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
if (p_clcb)
{
- if (p_clcb->p_srcb->num_clcb)
- p_clcb->p_srcb->num_clcb --;
+ if (p_srcb->num_clcb)
+ p_srcb->num_clcb --;
if (p_clcb->p_rcb->num_clcb)
p_clcb->p_rcb->num_clcb --;
+ if ( p_srcb->num_clcb == 0)
+ {
+ p_srcb->connected = FALSE;
+ p_srcb->state = BTA_GATTC_SERV_IDLE;
+ }
utl_freebuf((void **)&p_clcb->p_q_cmd);
- APPL_TRACE_ERROR2("bta_gattc_clcb_dealloc in_use=%d conn_id=%d",p_clcb->in_use, p_clcb->bta_conn_id);
memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
}
else
@@ -299,7 +305,7 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
**
** Function bta_gattc_find_srcb
**
-** Description find server cache by remote bd address
+** Description find server cache by remote bd address currently in use
**
** Returns pointer to the server cache.
**
@@ -316,6 +322,28 @@ tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda)
}
return NULL;
}
+
+/*******************************************************************************
+**
+** Function bta_gattc_find_srvr_cache
+**
+** Description find server cache by remote bd address
+**
+** Returns pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda)
+{
+ tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
+ {
+ if (bdcmp(p_srcb->server_bda, bda) == 0)
+ return p_srcb;
+ }
+ return NULL;
+}
/*******************************************************************************
**
** Function bta_gattc_find_scb_by_cid
@@ -441,6 +469,85 @@ void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR *p_attr, tBT_UUID *p_uuid)
}
/*******************************************************************************
**
+** Function bta_gattc_cpygattid
+**
+** Description copy two tBTA_GATT_ID value
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src)
+{
+ memset ((void *)p_des, 0, sizeof(tBTA_GATT_ID));
+
+ p_des->inst_id = p_src->inst_id;
+
+ p_des->uuid.len = p_src->uuid.len;
+
+ if (p_des->uuid.len == LEN_UUID_16)
+ {
+ p_des->uuid.uu.uuid16 = p_src->uuid.uu.uuid16;
+ }
+ else if (p_des->uuid.len == LEN_UUID_128)
+ {
+ memcpy(p_des->uuid.uu.uuid128, p_src->uuid.uu.uuid128, LEN_UUID_128);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_gattid_compare
+**
+** Description compare two tBTA_GATT_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_gattid_compare(tBTA_GATT_ID *p_src, tBTA_GATT_ID *p_tar)
+{
+ if (p_src->inst_id == p_tar->inst_id &&
+ bta_gattc_uuid_compare (p_src->uuid, p_tar->uuid, TRUE ))
+ return TRUE;
+ else
+ return FALSE;
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_srvcid_compare
+**
+** Description compare two tBTA_GATT_SRVC_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar)
+{
+ if (p_src->is_primary == p_tar->is_primary &&
+ bta_gattc_gattid_compare (&p_src->id, &p_tar->id))
+ return TRUE;
+ else
+ return FALSE;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_charid_compare
+**
+** Description compare two tBTA_GATTC_CHAR_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar)
+{
+ if (bta_gattc_gattid_compare (&p_src->char_id, &p_tar->char_id) &&
+ bta_gattc_srvcid_compare (&p_src->srvc_id, &p_tar->srvc_id))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*******************************************************************************
+**
** Function bta_gattc_check_notif_registry
**
** Description check if the service notificaition has been registered.
@@ -457,12 +564,7 @@ BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_SERV
{
if (p_clreg->notif_reg[i].in_use &&
bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
- (bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.srvc_id.id.uuid, p_notify->char_id.srvc_id.id.uuid, FALSE) &&
- p_clreg->notif_reg[i].char_id.srvc_id.id.inst_id == p_notify->char_id.srvc_id.id.inst_id &&
- p_clreg->notif_reg[i].char_id.srvc_id.is_primary == p_notify->char_id.srvc_id.is_primary &&
- bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.char_id.uuid, p_notify->char_id.char_id.uuid, FALSE) &&
- p_clreg->notif_reg[i].char_id.char_id.inst_id == p_notify->char_id.char_id.inst_id)
- )
+ bta_gattc_charid_compare (&p_clreg->notif_reg[i].char_id, &p_notify->char_id))
{
APPL_TRACE_DEBUG0("Notification registered!");
return TRUE;
@@ -562,22 +664,36 @@ tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID d
** Returns TRUE if success; FALSE otherwise.
**
*******************************************************************************/
-BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN add)
+BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR_PTR remote_bda_ptr,
+ BOOLEAN add, BOOLEAN is_listen)
{
tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0];
UINT8 i = 0;
+ tBTA_GATTC_CIF_MASK *p_cif_mask;
for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
{
if (p_bg_tck->in_use &&
- bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
+ ((remote_bda_ptr != NULL && bdcmp(p_bg_tck->remote_bda, remote_bda_ptr) == 0) ||
+ (remote_bda_ptr == NULL && bdcmp(p_bg_tck->remote_bda, bd_addr_null) == 0)))
{
+ p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
+
if (add)
/* mask on the cif bit */
- p_bg_tck->cif_mask |= (1 <<(client_if - 1));
+ *p_cif_mask |= (1 <<(client_if - 1));
else
- p_bg_tck->cif_mask &= (~(1 <<(client_if - 1)));
-
+ {
+ if (client_if != 0)
+ *p_cif_mask &= (~(1 <<(client_if - 1)));
+ else
+ *p_cif_mask = 0;
+ }
+ /* no BG connection for this device, make it available */
+ if (p_bg_tck->cif_mask == 0 && p_bg_tck->cif_adv_mask == 0)
+ {
+ memset(p_bg_tck, 0, sizeof(tBTA_GATTC_BG_TCK));
+ }
return TRUE;
}
}
@@ -594,8 +710,14 @@ BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BO
if (!p_bg_tck->in_use)
{
p_bg_tck->in_use = TRUE;
- bdcpy(p_bg_tck->remote_bda, remote_bda);
- p_bg_tck->cif_mask = (1 <<(client_if - 1));
+ if (remote_bda_ptr)
+ bdcpy(p_bg_tck->remote_bda, remote_bda_ptr);
+ else
+ bdcpy(p_bg_tck->remote_bda, bd_addr_null);
+
+ p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
+
+ *p_cif_mask = (1 <<(client_if - 1));
return TRUE;
}
}
@@ -612,20 +734,25 @@ BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BO
** Returns TRUE if success; FALSE otherwise.
**
*******************************************************************************/
-BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, UINT8 role)
{
tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0];
UINT8 i = 0;
BOOLEAN is_bg_conn = FALSE;
- for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+ for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX && !is_bg_conn; i ++, p_bg_tck ++)
{
if (p_bg_tck->in_use &&
- bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
+ (bdcmp(p_bg_tck->remote_bda, remote_bda) == 0 ||
+ bdcmp(p_bg_tck->remote_bda, bd_addr_null) == 0))
{
- if ((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0)
+ if (((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0) &&
+ role == HCI_ROLE_MASTER)
+ is_bg_conn = TRUE;
+
+ if (((p_bg_tck->cif_adv_mask &(1 <<(client_if - 1))) != 0) &&
+ role == HCI_ROLE_SLAVE)
is_bg_conn = TRUE;
- break;
}
}
return is_bg_conn;
@@ -656,9 +783,103 @@ void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status
(*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
}
}
+/*******************************************************************************
+**
+** Function bta_gattc_conn_alloc
+**
+** Description allocate connection tracking spot
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_alloc(BD_ADDR remote_bda)
+{
+ UINT8 i_conn = 0;
+ tBTA_GATTC_CONN *p_conn = &bta_gattc_cb.conn_track[0];
+
+ for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
+ {
+ if (!p_conn->in_use)
+ {
+#if BTA_GATT_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_gattc_conn_alloc: found conn_track[%d] available",i_conn);
+#endif
+ p_conn->in_use = TRUE;
+ bdcpy(p_conn->remote_bda, remote_bda);
+ return p_conn;
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_conn_find
+**
+** Description allocate connection tracking spot
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda)
+{
+ UINT8 i_conn = 0;
+ tBTA_GATTC_CONN *p_conn = &bta_gattc_cb.conn_track[0];
+
+ for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
+ {
+ if (p_conn->in_use && bdcmp(remote_bda, p_conn->remote_bda) == 0)
+ {
+#if BTA_GATT_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_gattc_conn_find: found conn_track[%d] matched",i_conn);
+#endif
+ return p_conn;
+ }
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_conn_find_alloc
+**
+** Description find or allocate connection tracking spot
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_find_alloc(BD_ADDR remote_bda)
+{
+ tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find (remote_bda);
+
+ if (p_conn == NULL)
+ {
+ p_conn = bta_gattc_conn_alloc(remote_bda);
+ }
+ return p_conn;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_conn_dealloc
+**
+** Description de-allocate connection tracking spot
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda)
+{
+ tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find (remote_bda);
+ if (p_conn != NULL)
+ {
+ p_conn->in_use = FALSE;
+ memset(p_conn->remote_bda, 0, BD_ADDR_LEN);
+ return TRUE;
+ }
+ return FALSE;
+}
#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
index 1b475985c..5504df0b6 100644
--- a/bta/gatt/bta_gatts_act.c
+++ b/bta/gatt/bta_gatts_act.c
@@ -292,7 +292,6 @@ void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
tBTA_GATTS cb_data;
UINT8 srvc_idx;
UINT16 service_id = 0;
- //tBTA_GATTS_HNDL_RANGE handle_range;
cb_data.create.status = BTA_GATT_ERROR;
@@ -714,7 +713,6 @@ void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
}
-
/*******************************************************************************
**
** Function bta_gatts_request_cback
diff --git a/bta/gatt/bta_gatts_api.c b/bta/gatt/bta_gatts_api.c
index 65df0a6b9..d30878e61 100644
--- a/bta/gatt/bta_gatts_api.c
+++ b/bta/gatt/bta_gatts_api.c
@@ -33,6 +33,13 @@
#include "bta_gatts_int.h"
/*****************************************************************************
+** Externs
+*****************************************************************************/
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTS_CB bta_gatts_cb;
+#endif
+
+/*****************************************************************************
** Constants
*****************************************************************************/
@@ -44,6 +51,22 @@ static const tBTA_SYS_REG bta_gatts_reg =
/*******************************************************************************
**
+** Function BTA_GATTS_Init
+**
+** Description This function is called to initalize GATTS module
+**
+** Parameters None
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTS_Init()
+{
+ memset(&bta_gatts_cb, 0, sizeof(tBTA_GATTS_CB));
+}
+
+/*******************************************************************************
+**
** Function BTA_GATTS_AppRegister
**
** Description This function is called to register application callbacks
diff --git a/bta/gatt/bta_gatts_int.h b/bta/gatt/bta_gatts_int.h
index 4810c058e..9f0ec7e2f 100644
--- a/bta/gatt/bta_gatts_int.h
+++ b/bta/gatt/bta_gatts_int.h
@@ -28,7 +28,6 @@
#include "bta_sys.h"
#include "bta_gatt_api.h"
#include "gatt_api.h"
-//#include "bta_gatts_co.h"
#include "gki.h"
@@ -52,7 +51,8 @@ enum
BTA_GATTS_API_RSP_EVT,
BTA_GATTS_API_OPEN_EVT,
BTA_GATTS_API_CANCEL_OPEN_EVT,
- BTA_GATTS_API_CLOSE_EVT
+ BTA_GATTS_API_CLOSE_EVT,
+ BTA_GATTS_API_LISTEN_EVT
};
typedef UINT16 tBTA_GATTS_INT_EVT;
@@ -116,7 +116,6 @@ typedef struct
typedef struct
{
BT_HDR hdr;
- //todo BD_ADDR bd_addr;
UINT16 attr_id;
UINT16 len;
BOOLEAN need_confirm;
@@ -148,6 +147,14 @@ typedef struct
typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN;
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR_PTR remote_bda;
+ tBTA_GATTS_IF server_if;
+ BOOLEAN start;
+} tBTA_GATTS_API_LISTEN;
+
typedef union
{
BT_HDR hdr;
@@ -164,6 +171,8 @@ typedef union
tBTA_GATTS_API_CANCEL_OPEN api_cancel_open;
tBTA_GATTS_INT_START_IF int_start_if;
+ /* if peripheral role is supported */
+ tBTA_GATTS_API_LISTEN api_listen;
} tBTA_GATTS_DATA;
/* application registration control block */
@@ -172,7 +181,7 @@ typedef struct
BOOLEAN in_use;
tBT_UUID app_uuid;
tBTA_GATTS_CBACK *p_cback;
- tBTA_GATTS_IF gatt_if; //todo cahneg to server_if
+ tBTA_GATTS_IF gatt_if;
}tBTA_GATTS_RCB;
/* service registration control block */
@@ -233,6 +242,7 @@ extern void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_
extern void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
extern void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
extern void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_listen(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
extern BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src);
extern tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if);
diff --git a/bta/hh/bta_hh_act.c b/bta/hh/bta_hh_act.c
index de080965b..f2b91e005 100644
--- a/bta/hh/bta_hh_act.c
+++ b/bta/hh/bta_hh_act.c
@@ -84,18 +84,20 @@ void bta_hh_api_enable(tBTA_HH_DATA *p_data)
status = BTA_HH_OK;
/* initialize device CB */
- for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+ for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
{
bta_hh_cb.kdev[xx].state = BTA_HH_IDLE_ST;
bta_hh_cb.kdev[xx].hid_handle = BTA_HH_INVALID_HANDLE;
bta_hh_cb.kdev[xx].index = xx;
- /* initialize control block map */
- bta_hh_cb.cb_index[xx] = BTA_HH_MAX_KNOWN;
}
+
+ /* initialize control block map */
+ for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+ bta_hh_cb.cb_index[xx] = BTA_HH_IDX_INVALID;
}
- /* signal BTA call back event */
- (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
+ /* signal BTA call back event */
+ (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
}
/*******************************************************************************
**
@@ -124,7 +126,7 @@ void bta_hh_api_disable(void)
{
bta_hh_cb.w4_disable = TRUE;
- for(xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+ for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
{
/* send API_CLOSE event to every connected device */
if ( bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST )
@@ -152,24 +154,15 @@ void bta_hh_api_disable(void)
*******************************************************************************/
void bta_hh_disc_cmpl(void)
{
- UINT8 xx;
tBTA_HH_STATUS status = BTA_HH_OK;
/* Deregister with lower layer */
if (HID_HostDeregister()!= HID_SUCCESS)
status = BTA_HH_ERR;
- /* free buffer in CB holding report descriptors */
- for(xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
- {
- utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
- }
- utl_freebuf((void **)&bta_hh_cb.p_disc_db);
-
- (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status);
- /* all connections are down, no waiting for diconnect */
- memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+ bta_hh_cleanup_disable(status);
}
+
/*******************************************************************************
**
** Function bta_hh_sdp_cback
@@ -186,7 +179,8 @@ static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask,
UINT8 hdl;
tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
- if (result == SDP_SUCCESS)
+ /* make sure sdp succeeded and hh has not been disabled */
+ if ((result == SDP_SUCCESS) && (p_cb != NULL))
{
/* security is required for the connection, add attr_mask bit*/
if (p_cb->sec_mask)
@@ -269,20 +263,20 @@ static void bta_hh_di_sdp_cback(UINT16 result)
* set to 0xffff and we will allow the connection to go through. Spec mandates that DI
* record be set, but many HID devices do not set this. So for IOP purposes, we allow the
* connection to go through and update the DI record to invalid DI entry.*/
- if ((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH))
+ if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) && (p_cb != NULL))
{
if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0)
{
/* always update information with primary DI record */
if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS)
{
- bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version);
+ bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0);
}
}
else /* no DI recrod available */
{
- bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0);
+ bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0);
}
if ((ret = HID_HostGetSDPRecord(p_cb->addr,
@@ -332,6 +326,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
p_cb->sec_mask = p_data->api_conn.sec_mask;
p_cb->mode = p_data->api_conn.mode;
+ bta_hh_cb.p_cur = p_cb;
/* if previously virtually cabled device, skip SDP */
if (p_cb->app_id)
@@ -355,9 +350,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
bta_hh_cb.cb_index[hdl] = p_cb->index;
}
else
- {
- status = BTA_HH_ERR_SDP;
- }
+ status = BTA_HH_ERR_NO_RES;
}
bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
@@ -531,12 +524,7 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
/* initialize device driver */
bta_hh_co_open(p_cb->hid_handle, p_cb->sub_class,
- p_cb->attr_mask, p_cb->app_id);
-
- /* update SSR settings */
- bta_sys_chg_ssr_config(BTA_ID_HH ,p_cb->app_id, p_cb->dscp_info.ssr_max_latency, p_cb->dscp_info.ssr_min_tout);
- /* inform role manager */
- bta_sys_conn_open( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
+ p_cb->attr_mask, p_cb->app_id);
/* set protocol mode when not default report mode */
if (p_cb->mode != BTA_HH_PROTO_RPT_MODE)
@@ -895,7 +883,8 @@ void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
bta_hh_update_di_info(p_cb,
p_dev_info->dscp_info.vendor_id,
p_dev_info->dscp_info.product_id,
- p_dev_info->dscp_info.version);
+ p_dev_info->dscp_info.version,
+ 0);
/* add to BTA device list */
bta_hh_add_device_to_list(p_cb, dev_handle,
@@ -917,13 +906,12 @@ void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
#if BTA_HH_DEBUG
bta_hh_trace_dev_db();
#endif
- break;
+ break;
case BTA_HH_RMV_DEV_EVT: /* remove device */
dev_info.handle = (UINT8)p_dev_info->hdr.layer_specific;
-
bdcpy(dev_info.bda, p_cb->addr);
- if (p_cb->state != BTA_HH_CONN_ST )
+
{
if(HID_HostRemoveDev( dev_info.handle ) == HID_SUCCESS)
{
@@ -1087,7 +1075,7 @@ static void bta_hh_cback (UINT8 dev_handle, UINT8 event, UINT32 data,
utl_freebuf((void **)&pdata);
break;
case HID_HDEV_EVT_VC_UNPLUG:
- for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
{
if (bta_hh_cb.kdev[xx].hid_handle == dev_handle)
{
diff --git a/bta/hh/bta_hh_api.c b/bta/hh/bta_hh_api.c
index 300fc6fc2..2a7965e92 100644
--- a/bta/hh/bta_hh_api.c
+++ b/bta/hh/bta_hh_api.c
@@ -57,7 +57,7 @@ static const tBTA_SYS_REG bta_hh_reg =
** Returns void
**
*******************************************************************************/
-void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback)
+void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
{
tBTA_HH_API_ENABLE *p_buf;
@@ -291,12 +291,21 @@ void BTA_HhSendCtrl(UINT8 dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type)
**
** Description This function send DATA transaction to HID device.
**
+** Parameter dev_handle: device handle
+** dev_bda: remote device address
+** p_data: data to be sent in the DATA transaction; or
+** the data to be write into the Output Report of a LE HID
+** device. The report is identified the report ID which is
+** the value of the byte (UINT8 *)(p_buf + 1) + p_buf->offset.
+** p_data->layer_specific needs to be set to the report type,
+** it can be OUTPUT report, or FEATURE report.
+**
** Returns void
**
*******************************************************************************/
void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR *p_data)
{
- bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, BTA_HH_RPTT_OUTPUT, 0, 0, p_data);
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, (UINT8)p_data->layer_specific, 0, 0, p_data);
}
/*******************************************************************************
diff --git a/bta/hh/bta_hh_cfg.c b/bta/hh/bta_hh_cfg.c
index 5b7335abf..e3ffefe9b 100644
--- a/bta/hh/bta_hh_cfg.c
+++ b/bta/hh/bta_hh_cfg.c
@@ -34,13 +34,6 @@
#define BTA_HH_DISC_BUF_SIZE GKI_MAX_BUF_SIZE
#endif
-/* application ID(none-zero) for each type of device */
-#define BTA_HH_APP_ID_MI 1
-#define BTA_HH_APP_ID_KB 2
-#define BTA_HH_APP_ID_RMC 3
-#define BTA_HH_APP_ID_3DSG 4
-#define BTA_HH_APP_ID_JOY 5
-#define BTA_HH_APP_ID_GPAD 6
/* The type of devices supported by BTA HH and corresponding application ID */
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index f3a8e54d3..7630a3ad3 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -174,7 +174,7 @@ typedef struct
suppose BTA will connect
to only one keyboard at
the same time */
- tBTA_HH_DEV_CB kdev[BTA_HH_MAX_KNOWN]; /* device control block */
+ tBTA_HH_DEV_CB kdev[BTA_HH_MAX_DEVICE]; /* device control block */
tBTA_HH_DEV_CB* p_cur; /* current device control
block idx, used in sdp */
UINT8 cb_index[BTA_HH_MAX_KNOWN]; /* maintain a CB index
@@ -232,13 +232,17 @@ extern void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
tHID_DEV_DSCP_INFO *p_dscp_info,
UINT8 sub_class, UINT16 max_latency, UINT16 min_tout, UINT8 app_id);
extern void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
- UINT16 version);
+ UINT16 version, UINT8 flag);
+extern void bta_hh_cleanup_disable(tBTA_HH_STATUS status);
+
+extern UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle);
/* action functions used outside state machine */
extern void bta_hh_api_enable(tBTA_HH_DATA *p_data);
extern void bta_hh_api_disable(void);
extern void bta_hh_disc_cmpl(void);
+extern tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout);
#if BTA_HH_DEBUG
extern void bta_hh_trace_dev_db(void);
diff --git a/bta/hh/bta_hh_main.c b/bta/hh/bta_hh_main.c
index a1d0ad27a..1c034698d 100644
--- a/bta/hh/bta_hh_main.c
+++ b/bta/hh/bta_hh_main.c
@@ -96,8 +96,7 @@ const UINT8 bta_hh_st_idle[][BTA_HH_NUM_COLS] =
/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST },
-/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
-
+/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST }
};
@@ -115,7 +114,7 @@ const UINT8 bta_hh_st_w4_conn[][BTA_HH_NUM_COLS] =
/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_IGNORE , BTA_HH_W4_CONN_ST },
/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST },
-/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST }
+/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST }
};
@@ -233,6 +232,14 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data
cback_data.hs_data.status = BTA_HH_ERR_HDL;
/* hs_data.rsp_data will be all zero, which is not valid value */
}
+ else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL &&
+ p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+ {
+ cback_data.status = BTA_HH_ERR_HDL;
+ cback_event = BTA_HH_VC_UNPLUG_EVT;
+ }
+ else
+ cback_event = 0;
break;
case BTA_HH_API_CLOSE_EVT:
@@ -297,7 +304,7 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data
*******************************************************************************/
BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
{
- UINT8 index = BTA_HH_MAX_KNOWN;
+ UINT8 index = BTA_HH_IDX_INVALID;
tBTA_HH_DEV_CB *p_cb = NULL;
switch (p_msg->event)
@@ -330,24 +337,24 @@ BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
}
else /* else remove device by handle */
{
- index = bta_hh_cb.cb_index[p_msg->layer_specific];
+ index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
// btla-specific ++
/* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
* then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
* cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
* So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
- * force the index to be MAX_KNOWN
+ * force the index to be IDX_INVALID
*/
if (bta_hh_cb.kdev[index].in_use == FALSE) {
- index = BTA_HH_MAX_KNOWN;
+ index = BTA_HH_IDX_INVALID;
}
// btla-specific --
}
}
- else if (p_msg->layer_specific < BTA_HH_MAX_KNOWN )
- index = bta_hh_cb.cb_index[p_msg->layer_specific];
+ else
+ index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
- if (index != BTA_HH_MAX_KNOWN)
+ if (index != BTA_HH_IDX_INVALID)
p_cb = &bta_hh_cb.kdev[index];
#if BTA_HH_DEBUG
diff --git a/bta/hh/bta_hh_utils.c b/bta/hh/bta_hh_utils.c
index 43492824d..bea0f2b81 100644
--- a/bta/hh/bta_hh_utils.c
+++ b/bta/hh/bta_hh_utils.c
@@ -23,6 +23,10 @@
#include "bta_hh_int.h"
+/* if SSR max latency is not defined by remote device, set the default value
+ as half of the link supervision timeout */
+#define BTA_HH_GET_DEF_SSR_MAX_LAT(x) ((x)>> 1)
+
/*****************************************************************************
** Constants
*****************************************************************************/
@@ -61,7 +65,7 @@ UINT8 bta_hh_find_cb(BD_ADDR bda)
UINT8 xx;
/* See how many active devices there are. */
- for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
{
/* check if any active/known devices is a match */
if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) &&
@@ -83,7 +87,7 @@ UINT8 bta_hh_find_cb(BD_ADDR bda)
}
/* if no active device match, find a spot for it */
- for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
{
if (!bta_hh_cb.kdev[xx].in_use)
{
@@ -91,12 +95,15 @@ UINT8 bta_hh_find_cb(BD_ADDR bda)
break;
}
}
- /* If device list full, report BTA_HH_MAX_KNOWN */
+ /* If device list full, report BTA_HH_IDX_INVALID */
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG2("bta_hh_find_cb:: index = %d while max = %d",
- xx, BTA_HH_MAX_KNOWN);
+ xx, BTA_HH_MAX_DEVICE);
#endif
+ if (xx == BTA_HH_MAX_DEVICE)
+ xx = BTA_HH_IDX_INVALID;
+
return xx;
}
@@ -115,7 +122,9 @@ void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb)
UINT8 index;
if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE )
- bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_MAX_KNOWN;
+ {
+ bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_IDX_INVALID;
+ }
/* reset device control block */
index = p_cb->index; /* Preserve index for this control block */
@@ -140,7 +149,7 @@ void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb)
**
*******************************************************************************/
void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
- UINT16 version)
+ UINT16 version, UINT8 flag)
{
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG3("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
@@ -178,15 +187,8 @@ void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
p_cb->sub_class = sub_class;
p_cb->app_id = app_id;
- if (ssr_max_latency == HID_SSR_PARAM_INVALID)
- p_cb->dscp_info.ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
- else
- p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
-
- if (ssr_min_tout == HID_SSR_PARAM_INVALID)
- p_cb->dscp_info.ssr_min_tout = BTA_HH_SSR_MIN_TOUT_DEF;
- else
- p_cb->dscp_info.ssr_min_tout = ssr_min_tout;
+ p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
+ p_cb->dscp_info.ssr_min_tout = ssr_min_tout;
/* store report descriptor info */
if ( p_dscp_info)
@@ -386,6 +388,108 @@ void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_mice_data, UINT8 *p_report,
}
+/*******************************************************************************
+**
+** Function bta_hh_read_ssr_param
+**
+** Description Read the SSR Parameter for the remote device
+**
+** Returns tBTA_HH_STATUS operation status
+**
+*******************************************************************************/
+tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout)
+{
+ tBTA_HH_STATUS status = BTA_HH_ERR;
+ tBTA_HH_CB *p_cb = &bta_hh_cb;
+ UINT8 i;
+ UINT16 ssr_max_latency;
+ /* lock other GKI task */
+ GKI_sched_lock();
+ for (i = 0; i < BTA_HH_MAX_KNOWN; i ++)
+ {
+ if (memcmp(p_cb->kdev[i].addr, bd_addr, BD_ADDR_LEN) == 0)
+ {
+
+ /* if remote device does not have HIDSSRHostMaxLatency attribute in SDP,
+ set SSR max latency default value here. */
+ if (p_cb->kdev[i].dscp_info.ssr_max_latency == HID_SSR_PARAM_INVALID)
+ {
+ /* The default is calculated as half of link supervision timeout.*/
+
+ BTM_GetLinkSuperTout(p_cb->kdev[i].addr, &ssr_max_latency) ;
+ ssr_max_latency = BTA_HH_GET_DEF_SSR_MAX_LAT(ssr_max_latency);
+
+ /* per 1.1 spec, if the newly calculated max latency is greater than
+ BTA_HH_SSR_MAX_LATENCY_DEF which is 500ms, use BTA_HH_SSR_MAX_LATENCY_DEF */
+ if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF)
+ ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
+
+ * p_max_ssr_lat = ssr_max_latency;
+ }
+ else
+ * p_max_ssr_lat = p_cb->kdev[i].dscp_info.ssr_max_latency;
+
+ if (p_cb->kdev[i].dscp_info.ssr_min_tout == HID_SSR_PARAM_INVALID)
+ * p_min_ssr_tout = BTA_HH_SSR_MIN_TOUT_DEF;
+ else
+ * p_min_ssr_tout = p_cb->kdev[i].dscp_info.ssr_min_tout;
+
+ status = BTA_HH_OK;
+
+ break;
+ }
+ }
+ GKI_sched_unlock();
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_cleanup_disable
+**
+** Description when disable finished, cleanup control block and send callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
+{
+ UINT8 xx;
+ /* free buffer in CB holding report descriptors */
+ for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
+ {
+ utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
+ }
+ utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+
+ (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status);
+ /* all connections are down, no waiting for diconnect */
+ memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_dev_handle_to_cb_idx
+**
+** Description convert a HID device handle to the device control block index.
+**
+**
+** Returns UINT8: index of the device control block.
+**
+*******************************************************************************/
+UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle)
+{
+ UINT8 index = BTA_HH_IDX_INVALID;
+
+ /* regular HID device checking */
+ if (dev_handle < BTA_HH_MAX_KNOWN )
+ index = bta_hh_cb.cb_index[dev_handle];
+
+ return index;
+
+}
#if BTA_HH_DEBUG
/*******************************************************************************
**
@@ -402,7 +506,7 @@ void bta_hh_trace_dev_db(void)
APPL_TRACE_DEBUG0("bta_hh_trace_dev_db:: Device DB list********************");
- for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
{
APPL_TRACE_DEBUG3("kdev[%d] in_use[%d] handle[%d] ",xx,
bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle);
diff --git a/bta/hl/bta_hl_act.c b/bta/hl/bta_hl_act.c
index 0f46e5ebd..ab1222229 100644
--- a/bta/hl/bta_hl_act.c
+++ b/bta/hl/bta_hl_act.c
@@ -59,7 +59,8 @@ static void bta_hl_sdp_cback5(UINT16 status);
static void bta_hl_sdp_cback6(UINT16 status);
-static tSDP_DISC_CMPL_CB * const bta_hl_sdp_cback_arr[] = {
+static tSDP_DISC_CMPL_CB * const bta_hl_sdp_cback_arr[] =
+{
bta_hl_sdp_cback0,
bta_hl_sdp_cback1,
bta_hl_sdp_cback2,
@@ -544,7 +545,7 @@ void bta_hl_dch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
tBTA_HL evt_data;
- tBTA_HL_EVT event;
+ tBTA_HL_EVT event = 0;
BOOLEAN send_evt=TRUE;
tBTA_HL_STATUS status;
@@ -880,7 +881,7 @@ void bta_hl_dch_mca_open_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
tMCA_DL_OPEN *p_open_ind = &p_data->mca_evt.mca_data.open_ind;
tBTA_HL evt_data;
tBTA_HL_EVT event;
- UINT8 old_dch_oper;
+ UINT8 old_dch_oper = BTA_HL_DCH_OP_NONE;
BOOLEAN send_event = FALSE;
@@ -987,8 +988,8 @@ void bta_hl_dch_mca_open_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
tMCA_DL_OPEN *p_open_cfm = &p_data->mca_evt.mca_data.open_cfm;
tBTA_HL evt_data;
tBTA_HL_EVT event;
- UINT8 old_dch_oper;
- tBTA_HL_DCH_MODE dch_mode;
+ UINT8 old_dch_oper = BTA_HL_DCH_OP_NONE;
+ tBTA_HL_DCH_MODE dch_mode = BTA_HL_DCH_MODE_STREAMING;
BOOLEAN send_event = FALSE;
@@ -1006,10 +1007,6 @@ void bta_hl_dch_mca_open_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
{
dch_mode = BTA_HL_DCH_MODE_RELIABLE;
}
- else
- {
- dch_mode = BTA_HL_DCH_MODE_STREAMING;
- }
if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
{
@@ -1034,6 +1031,11 @@ void bta_hl_dch_mca_open_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
old_dch_oper = p_dcb->dch_oper;
p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
}
+ else
+ {
+ APPL_TRACE_ERROR1("Error dch oper =%d", p_dcb->dch_oper);
+ return;
+ }
switch (old_dch_oper)
{
@@ -2209,7 +2211,6 @@ tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 m
uuid_list.len = LEN_UUID_16;
uuid_list.uu.uuid16 = UUID_SERVCLASS_HDP_PROFILE;
-
SDP_InitDiscoveryDb(p_cb->p_db, BTA_HL_DISC_SIZE, 1, &uuid_list, num_attrs, attr_list);
if (!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, p_cb->sdp_cback))
@@ -2324,22 +2325,30 @@ void bta_hl_cch_mca_open(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
*******************************************************************************/
void bta_hl_cch_mca_close(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
{
- tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
#if BTA_HL_DEBUG == TRUE
- APPL_TRACE_DEBUG0("bta_hl_cch_mca_close");
+ APPL_TRACE_DEBUG1("bta_hl_cch_mca_close mcl_handle=%d", p_mcb->mcl_handle);
#endif
if (p_mcb->sdp_oper != BTA_HL_SDP_OP_CCH_INIT)
{
- if ( MCA_DisconnectReq((tMCA_HANDLE) p_acb->app_handle) != MCA_SUCCESS)
+ if(p_mcb->mcl_handle)
{
- bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+ if ( MCA_DisconnectReq((tMCA_HANDLE) p_mcb->mcl_handle) != MCA_SUCCESS)
+ {
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ p_mcb->close_pending = TRUE;
+ APPL_TRACE_DEBUG0("No valid mcl_handle to stop the CCH setup now so wait until CCH is up then close it" );
}
}
else
{
p_mcb->close_pending = TRUE;
+ APPL_TRACE_DEBUG0("can not stop the CCH setup becasue SDP is in progress so wait until it is done" );
}
}
@@ -2365,6 +2374,12 @@ void bta_hl_cch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
#endif
bta_sys_conn_close(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
+ if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE && p_mcb->force_close_local_cch_opening)
+ {
+ p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_OPEN;
+ APPL_TRACE_DEBUG0("change cch_oper from BTA_HL_CCH_OP_LOCAL_CLOSE to BTA_HL_CCH_OP_LOCAL_OPEN");
+ }
+
switch (p_mcb->cch_oper)
{
case BTA_HL_CCH_OP_LOCAL_OPEN:
@@ -2445,6 +2460,28 @@ void bta_hl_cch_mca_disconnect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_da
/*******************************************************************************
**
+** Function bta_hl_cch_mca_disc_open
+**
+** Description Action routine for disconnect the just opened Control channel
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_disc_open(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG2("bta_hl_cch_mca_disc_open mcl_handle=0x%x close_pending=%d", p_data->mca_evt.mcl_handle, p_mcb->close_pending );
+#endif
+
+ p_mcb->close_pending = FALSE;
+ p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
+ bta_hl_cch_mca_close(app_idx, mcl_idx, p_data);
+}
+
+/*******************************************************************************
+**
** Function bta_hl_cch_mca_rsp_tout
**
** Description Action routine for processing the MCAP response timeout
@@ -2464,6 +2501,7 @@ void bta_hl_cch_mca_rsp_tout(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data
bta_hl_check_cch_close(app_idx,mcl_idx,p_data,TRUE);
}
+
/*******************************************************************************
**
** Function bta_hl_cch_mca_connect
@@ -2482,7 +2520,7 @@ void bta_hl_cch_mca_connect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
BOOLEAN send_event=TRUE;
#if BTA_HL_DEBUG == TRUE
- APPL_TRACE_DEBUG0("bta_hl_cch_mca_connect");
+ APPL_TRACE_DEBUG1("bta_hl_cch_mca_connect mcl_handle=%d ", p_data->mca_evt.mcl_handle);
#endif
p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
@@ -2596,7 +2634,7 @@ void bta_hl_mcap_ctrl_cback (tMCA_HANDLE handle, tMCA_CL mcl, UINT8 event,
break;
}
- if ((p_msg = (tBTA_HL_MCA_EVT *)GKI_getbuf(sizeof(tBTA_HL_MCA_EVT))) != NULL)
+ if (send_event && ((p_msg = (tBTA_HL_MCA_EVT *)GKI_getbuf(sizeof(tBTA_HL_MCA_EVT))) != NULL))
{
p_msg->hdr.event = mca_event;
p_msg->app_handle = (tBTA_HL_APP_HANDLE) handle;
@@ -2606,7 +2644,6 @@ void bta_hl_mcap_ctrl_cback (tMCA_HANDLE handle, tMCA_CL mcl, UINT8 event,
}
}
-
/*******************************************************************************
**
** Function bta_hl_mcap_data_cback
diff --git a/bta/hl/bta_hl_int.h b/bta/hl/bta_hl_int.h
index 648eb2cff..30a3f94ae 100644
--- a/bta/hl/bta_hl_int.h
+++ b/bta/hl/bta_hl_int.h
@@ -485,6 +485,7 @@ typedef struct
UINT8 sdp_mdl_idx;
tBTA_HL_SDP sdp;
UINT8 cch_oper;
+ UINT8 force_close_local_cch_opening;
BOOLEAN intentional_close;
BOOLEAN rsp_tout;
UINT8 timer_oper;
@@ -667,6 +668,7 @@ extern "C"
extern void bta_hl_cch_mca_close(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
extern void bta_hl_cch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
extern void bta_hl_cch_mca_disconnect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+ extern void bta_hl_cch_mca_disc_open(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
extern void bta_hl_cch_mca_rsp_tout(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
extern void bta_hl_cch_mca_connect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
diff --git a/bta/hl/bta_hl_main.c b/bta/hl/bta_hl_main.c
index afac4c371..cbc83ef21 100644
--- a/bta/hl/bta_hl_main.c
+++ b/bta/hl/bta_hl_main.c
@@ -300,6 +300,7 @@ enum
BTA_HL_CCH_MCA_CONNECT,
BTA_HL_CCH_MCA_DISCONNECT,
BTA_HL_CCH_MCA_RSP_TOUT,
+ BTA_HL_CCH_MCA_DISC_OPEN,
BTA_HL_CCH_IGNORE
};
@@ -315,7 +316,8 @@ const tBTA_HL_CCH_ACTION bta_hl_cch_action[] =
bta_hl_cch_close_cmpl,
bta_hl_cch_mca_connect,
bta_hl_cch_mca_disconnect,
- bta_hl_cch_mca_rsp_tout
+ bta_hl_cch_mca_rsp_tout,
+ bta_hl_cch_mca_disc_open
};
@@ -374,7 +376,7 @@ static const UINT8 bta_hl_cch_st_closing[][BTA_HL_CCH_NUM_COLS] =
/* BTA_HL_CCH_OPEN_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_CLOSING_ST},
/* BTA_HL_CCH_SDP_OK_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
/* BTA_HL_CCH_SDP_FAIL_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
-/* BTA_HL_MCA_CONNECT_IND_EVT */ {BTA_HL_CCH_MCA_CONNECT, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISC_OPEN, BTA_HL_CCH_CLOSING_ST},
/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISCONNECT, BTA_HL_CCH_CLOSING_ST},
/* BTA_HL_CCH_CLOSE_EVT */ {BTA_HL_CCH_MCA_CLOSE, BTA_HL_CCH_CLOSING_ST},
/* BTA_HL_CCH_CLOSE_CMPL_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
@@ -601,9 +603,10 @@ static void bta_hl_api_register(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
{
tBTA_HL evt_data;
UINT8 app_idx;
- tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_APP_CB *p_acb = NULL;
tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
+
if (p_cb->enable)
{
if (!bta_hl_is_a_duplicate_id(p_data->api_reg.app_id))
@@ -641,7 +644,8 @@ static void bta_hl_api_register(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
if ((status != BTA_HL_STATUS_DUPLICATE_APP_ID) &&
(status != BTA_HL_STATUS_NO_RESOURCE))
{
- memset(p_acb, 0, sizeof(tBTA_HL_APP_CB));
+ if (p_acb)
+ memset(p_acb, 0, sizeof(tBTA_HL_APP_CB));
}
}
#if BTA_HL_DEBUG == TRUE
@@ -651,9 +655,11 @@ static void bta_hl_api_register(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
}
#endif
+ memset(&evt_data, 0, sizeof(tBTA_HL));
evt_data.reg_cfm.status = status;
evt_data.reg_cfm.app_id = p_data->api_reg.app_id;
- evt_data.reg_cfm.app_handle = p_acb->app_handle;
+ if (status == BTA_HL_STATUS_OK)
+ evt_data.reg_cfm.app_handle = p_acb->app_handle;
if (p_data->api_reg.p_cback)
{
p_data->api_reg.p_cback(BTA_HL_REGISTER_CFM_EVT, (tBTA_HL *) &evt_data);
@@ -697,7 +703,7 @@ static void bta_hl_api_deregister(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
}
else
{
- APPL_TRACE_ERROR1("Inavlide app_handle=%d", p_data->api_dereg.app_handle);
+ APPL_TRACE_ERROR1("Invalid app_handle=%d", p_data->api_dereg.app_handle);
}
}
@@ -760,12 +766,20 @@ static void bta_hl_api_cch_open(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
break;
case BTA_HL_STATUS_NO_RESOURCE:
case BTA_HL_STATUS_FAIL:
- bta_hl_build_cch_open_cfm(&evt_data, p_data->api_cch_open.app_handle,
- 0,
- p_data->api_cch_open.bd_addr,
- status);
+
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- p_acb->p_cback(BTA_HL_CCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_cch_open_cfm(&evt_data, p_data->api_cch_open.app_handle,
+ 0,
+ p_data->api_cch_open.bd_addr,
+ status);
+ p_acb->p_cback(BTA_HL_CCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_cch_open Null Callback");
+ }
break;
default:
APPL_TRACE_ERROR1("status code=%d", status);
@@ -811,13 +825,20 @@ static void bta_hl_api_cch_close(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
bta_hl_check_cch_close(app_idx, mcl_idx, p_data, TRUE);
break;
- case BTA_HL_STATUS_FAIL:
+ case BTA_HL_STATUS_INVALID_MCL_HANDLE:
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- bta_hl_build_cch_close_cfm(&evt_data,
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_cch_close_cfm(&evt_data,
p_acb->app_handle,
p_data->api_cch_close.mcl_handle,
status);
- p_acb->p_cback(BTA_HL_CCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+ p_acb->p_cback(BTA_HL_CCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_cch_close Null Callback");
+ }
break;
default:
@@ -958,12 +979,20 @@ static void bta_hl_api_dch_open(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
case BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID:
case BTA_HL_STATUS_INVALID_CTRL_PSM:
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- bta_hl_build_dch_open_cfm(&evt_data,
- p_acb->app_handle,
- p_data->api_dch_open.mcl_handle,
- BTA_HL_INVALID_MDL_HANDLE,
- 0,0,0,0,0, status);
- p_acb->p_cback(BTA_HL_DCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_dch_open_cfm(&evt_data,
+ p_acb->app_handle,
+ p_data->api_dch_open.mcl_handle,
+ BTA_HL_INVALID_MDL_HANDLE,
+ 0,0,0,0,0, status);
+ p_acb->p_cback(BTA_HL_DCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_dch_open Null Callback");
+ }
+
break;
default:
APPL_TRACE_ERROR1("Status code=%d", status);
@@ -1018,14 +1047,21 @@ static void bta_hl_api_dch_close(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
break;
case BTA_HL_STATUS_FAIL:
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
- bta_hl_build_dch_close_cfm(&evt_data,
- p_acb->app_handle,
- p_mcb->mcl_handle,
- p_data->api_dch_close.mdl_handle,
- status);
+ if (p_acb->p_cback)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ bta_hl_build_dch_close_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_data->api_dch_close.mdl_handle,
+ status);
- p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+ p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_dch_close Null Callback");
+ }
break;
default:
APPL_TRACE_ERROR1("Status code=%d", status);
@@ -1053,8 +1089,9 @@ static void bta_hl_api_dch_reconnect(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
tBTA_HL_MDL_CB *p_dcb;
UINT8 mdep_cfg_idx;
UINT8 mdl_cfg_idx;
+ tBTA_HL_MDEP_CFG *p_mdep_cfg;
- if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_open.mcl_handle, &app_idx, &mcl_idx))
+ if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_reconnect.mcl_handle, &app_idx, &mcl_idx))
{
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
@@ -1085,6 +1122,20 @@ static void bta_hl_api_dch_reconnect(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
p_dcb->mdl_cfg_idx_included = TRUE;
p_dcb->mdl_cfg_idx = mdl_cfg_idx;
p_dcb->dch_mode = p_acb->mdl_cfg[mdl_cfg_idx].dch_mode;
+
+ p_mdep_cfg = BTA_HL_GET_MDEP_CFG_PTR(app_idx, mdep_cfg_idx);
+
+ if (p_mdep_cfg->mdep_role == BTA_HL_MDEP_ROLE_SINK)
+ {
+ p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SOURCE;
+ APPL_TRACE_DEBUG0("peer mdep role = SOURCE ");
+ }
+ else
+ {
+ p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SINK;
+ APPL_TRACE_DEBUG0("peer mdep role = SINK ");
+ }
+
bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
&p_dcb->max_rx_apdu_size,
&p_dcb->max_tx_apdu_size);
@@ -1139,12 +1190,19 @@ static void bta_hl_api_dch_reconnect(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
case BTA_HL_STATUS_NO_CCH:
case BTA_HL_STATUS_NO_RESOURCE:
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- bta_hl_build_dch_open_cfm(&evt_data,
- p_acb->app_handle,
- p_data->api_dch_reconnect.mcl_handle,
- BTA_HL_INVALID_MDL_HANDLE,
- 0,p_data->api_dch_reconnect.mdl_id,0,0,0, status);
- p_acb->p_cback(BTA_HL_DCH_RECONNECT_CFM_EVT,(tBTA_HL *) &evt_data );
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_dch_open_cfm(&evt_data,
+ p_acb->app_handle,
+ p_data->api_dch_reconnect.mcl_handle,
+ BTA_HL_INVALID_MDL_HANDLE,
+ 0,p_data->api_dch_reconnect.mdl_id,0,0,0, status);
+ p_acb->p_cback(BTA_HL_DCH_RECONNECT_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_dch_reconnect Null Callback");
+ }
break;
default:
APPL_TRACE_ERROR1("Status code=%d", status);
@@ -1260,15 +1318,22 @@ static void bta_hl_api_dch_echo_test(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_INIT_EVT, p_data);
}
break;
- case BTA_HL_STATUS_NO_CCH:
case BTA_HL_STATUS_ECHO_TEST_BUSY:
case BTA_HL_STATUS_NO_RESOURCE:
case BTA_HL_STATUS_INVALID_DCH_CFG:
- bta_hl_build_echo_test_cfm(&evt_data,
- p_acb->app_handle,
- p_mcb->mcl_handle,
- status);
- p_acb->p_cback(BTA_HL_DCH_ECHO_TEST_CFM_EVT,(tBTA_HL *) &evt_data );
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_echo_test_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ status);
+ p_acb->p_cback(BTA_HL_DCH_ECHO_TEST_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_dch_echo_test Null Callback");
+ }
break;
default:
@@ -1350,13 +1415,20 @@ static void bta_hl_api_sdp_query(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
case BTA_HL_STATUS_NO_RESOURCE:
case BTA_HL_STATUS_FAIL:
case BTA_HL_STATUS_SDP_NO_RESOURCE:
- bta_hl_build_sdp_query_cfm(&evt_data,
- p_data->api_sdp_query.app_handle,
- p_data->api_sdp_query.bd_addr,
- NULL,
- status);
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- p_acb->p_cback(BTA_HL_SDP_QUERY_CFM_EVT,(tBTA_HL *) &evt_data );
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_sdp_query_cfm(&evt_data,
+ p_data->api_sdp_query.app_handle,
+ p_data->api_sdp_query.bd_addr,
+ NULL,
+ status);
+ p_acb->p_cback(BTA_HL_SDP_QUERY_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_sdp_query Null Callback");
+ }
break;
case BTA_HL_STATUS_OK:
break;
@@ -1515,15 +1587,20 @@ static void bta_hl_api_delete_mdl(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
case BTA_HL_STATUS_NO_MDL_ID_FOUND:
case BTA_HL_STATUS_INVALID_MDL_ID:
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- bta_hl_build_delete_mdl_cfm(&evt_data,
- p_acb->app_handle,
- p_data->api_delete_mdl.mcl_handle,
- p_data->api_delete_mdl.mdl_id,
- status);
-
- p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_delete_mdl_cfm(&evt_data,
+ p_acb->app_handle,
+ p_data->api_delete_mdl.mcl_handle,
+ p_data->api_delete_mdl.mdl_id,
+ status);
+ p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_delete_mdl Null Callback");
+ }
break;
- case BTA_HL_STATUS_INVALID_APP_HANDLE:
default:
APPL_TRACE_ERROR1("status code =%d", status);
break;
@@ -1591,13 +1668,21 @@ static void bta_hl_mca_delete_mdl_cfm(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
if (send_cfm_evt)
{
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- bta_hl_build_delete_mdl_cfm(&evt_data,
- p_acb->app_handle,
- p_mcb->mcl_handle,
- p_delete_cfm->mdl_id,
- status);
+ if (p_acb->p_cback)
+ {
+ bta_hl_build_delete_mdl_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_delete_cfm->mdl_id,
+ status);
+
+ p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_mca_delete_mdl_cfm Null Callback");
- p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
}
}
@@ -1647,10 +1732,17 @@ static void bta_hl_mca_delete_mdl_ind(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
if (send_ind_evt)
{
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- evt_data.delete_mdl_ind.mcl_handle = p_mcb->mcl_handle;
- evt_data.delete_mdl_ind.app_handle = p_acb->app_handle;
- evt_data.delete_mdl_ind.mdl_id = p_delete_ind->mdl_id;
- p_acb->p_cback(BTA_HL_DELETE_MDL_IND_EVT,(tBTA_HL *) &evt_data );
+ if (p_acb->p_cback)
+ {
+ evt_data.delete_mdl_ind.mcl_handle = p_mcb->mcl_handle;
+ evt_data.delete_mdl_ind.app_handle = p_acb->app_handle;
+ evt_data.delete_mdl_ind.mdl_id = p_delete_ind->mdl_id;
+ p_acb->p_cback(BTA_HL_DELETE_MDL_IND_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_mca_delete_mdl_ind Null Callback");
+ }
}
}
@@ -1718,16 +1810,24 @@ static void bta_hl_api_dch_abort(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
case BTA_HL_STATUS_NO_MDL_ID_FOUND:
case BTA_HL_STATUS_FAIL:
- p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
- bta_hl_build_abort_cfm(&evt_data,
- p_acb->app_handle,
- p_mcb->mcl_handle,
- BTA_HL_STATUS_FAIL);
- p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT,(tBTA_HL *) &evt_data );
+ if (p_acb->p_cback)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ bta_hl_build_abort_cfm(&evt_data,
+
+
+
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_STATUS_FAIL);
+ p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT,(tBTA_HL *) &evt_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_hl_api_dch_abort Null Callback");
+ }
break;
- case BTA_HL_STATUS_INVALID_BD_ADDR:
- case BTA_HL_STATUS_INVALID_APP_HANDLE:
default:
APPL_TRACE_ERROR1("Status code=%d", status);
break;
diff --git a/bta/hl/bta_hl_sdp.c b/bta/hl/bta_hl_sdp.c
index 15620e8d4..45af7be48 100644
--- a/bta/hl/bta_hl_sdp.c
+++ b/bta/hl/bta_hl_sdp.c
@@ -310,7 +310,7 @@ tBTA_HL_STATUS bta_hl_sdp_register (UINT8 app_idx)
}
cnt++;
- if (cnt>BTA_HL_NUM_SUP_FEATURE_ELEMS)
+ if (cnt==BTA_HL_NUM_SUP_FEATURE_ELEMS)
{
result = FALSE;
break;
diff --git a/bta/hl/bta_hl_utils.c b/bta/hl/bta_hl_utils.c
index 7f94a9cf9..5fab7fd03 100644
--- a/bta/hl/bta_hl_utils.c
+++ b/bta/hl/bta_hl_utils.c
@@ -520,7 +520,7 @@ BOOLEAN bta_hl_find_cch_cb_indexes(tBTA_HL_DATA *p_msg,
{
BOOLEAN found = FALSE;
tBTA_HL_MCL_CB *p_mcb;
- UINT8 app_idx, mcl_idx;
+ UINT8 app_idx = 0, mcl_idx = 0;
switch (p_msg->hdr.event)
{
@@ -567,7 +567,7 @@ BOOLEAN bta_hl_find_cch_cb_indexes(tBTA_HL_DATA *p_msg,
if (found)
{
p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
- if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE)
+ if ((p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE) && (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_OPEN) )
{
p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_CLOSE;
}
@@ -584,7 +584,7 @@ BOOLEAN bta_hl_find_cch_cb_indexes(tBTA_HL_DATA *p_msg,
if (found)
{
p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
- if (p_mcb->cch_oper != BTA_HL_CCH_OP_REMOTE_CLOSE)
+ if ((p_mcb->cch_oper != BTA_HL_CCH_OP_REMOTE_CLOSE) && (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_OPEN))
{
p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
}
@@ -629,7 +629,7 @@ BOOLEAN bta_hl_find_dch_cb_indexes(tBTA_HL_DATA *p_msg,
{
BOOLEAN found = FALSE;
tBTA_HL_MCL_CB *p_mcb;
- UINT8 app_idx, mcl_idx, mdl_idx;
+ UINT8 app_idx = 0, mcl_idx = 0, mdl_idx = 0;
switch (p_msg->hdr.event)
{
@@ -1124,7 +1124,7 @@ BOOLEAN bta_hl_find_mcl_idx_using_handle( tBTA_HL_MCL_HANDLE mcl_handle,
{
tBTA_HL_APP_CB *p_acb;
BOOLEAN found=FALSE;
- UINT8 i,j;
+ UINT8 i = 0,j = 0;
for (i=0; i<BTA_HL_NUM_APPS; i++)
{
@@ -1959,7 +1959,7 @@ BOOLEAN bta_hl_validate_reconnect_params(UINT8 app_idx, UINT8 mcl_idx,
BOOLEAN local_mdep_id_found =FALSE;
BOOLEAN mdl_cfg_found =FALSE;
BOOLEAN status=FALSE;
- UINT8 i, in_use_mdl_idx;
+ UINT8 i, in_use_mdl_idx = 0;
#if BTA_HL_DEBUG == TRUE
APPL_TRACE_DEBUG1("bta_hl_validate_reconnect_params mdl_id=%d", p_reconnect->mdl_id);
@@ -2358,7 +2358,7 @@ void bta_hl_save_mdl_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx )
tBTA_HL_MDL_CFG mdl_cfg;
tBTA_HL_MDEP *p_mdep_cfg;
tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
- UINT8 time_val;
+ UINT8 time_val = 0;
mdl_id = p_dcb->mdl_id;
if (!bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, mdl_id, &mdl_cfg_idx))
{
@@ -2581,12 +2581,14 @@ BOOLEAN bta_hl_validate_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx)
tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
BOOLEAN success = FALSE;
- UINT8 mdl_cfg_idx;
+ UINT8 mdl_cfg_idx = 0;
tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
+ BOOLEAN get_l2cap_result, get_mdl_result;
+ get_l2cap_result = bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg);
+ get_mdl_result = bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_dcb->mdl_id, &mdl_cfg_idx);
- if (bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg) &&
- bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_dcb->mdl_id, &mdl_cfg_idx))
+ if (get_l2cap_result && get_mdl_result)
{
if ((p_acb->mdl_cfg[mdl_cfg_idx].mtu <= l2cap_cfg.mtu) &&
(p_acb->mdl_cfg[mdl_cfg_idx].fcs == l2cap_cfg.fcs) &&
@@ -2632,7 +2634,7 @@ BOOLEAN bta_hl_is_cong_on(UINT8 app_id, BD_ADDR bd_addr, tBTA_HL_MDL_ID mdl_id)
{
tBTA_HL_MDL_CB *p_dcb;
- UINT8 app_idx, mcl_idx, mdl_idx;
+ UINT8 app_idx = 0, mcl_idx, mdl_idx;
BOOLEAN cong_status = TRUE;
if (bta_hl_find_app_idx(app_id, &app_idx))
@@ -2766,7 +2768,10 @@ void bta_hl_check_deregistration(UINT8 app_idx, tBTA_HL_DATA *p_data )
p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE)
{
+ if (p_mcb->cch_state == BTA_HL_CCH_OPENING_ST)
+ p_mcb->force_close_local_cch_opening = TRUE;
p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+ APPL_TRACE_DEBUG1("p_mcb->force_close_local_cch_opening=%d", p_mcb->force_close_local_cch_opening );
bta_hl_check_cch_close(app_idx,mcl_idx,p_data, TRUE);
}
}
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 81dff39cc..042e48755 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -182,14 +182,20 @@ typedef UINT8 tBTA_SEC;
#define BTA_DM_NON_DISC BTM_NON_DISCOVERABLE /* Device is not discoverable. */
#define BTA_DM_GENERAL_DISC BTM_GENERAL_DISCOVERABLE /* General discoverable. */
#define BTA_DM_LIMITED_DISC BTM_LIMITED_DISCOVERABLE /* Limited discoverable. */
-
-// btla-specific ++
-typedef UINT16 tBTA_DM_DISC;
-// btla-specific --
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_DM_BLE_NON_DISCOVERABLE BTM_BLE_NON_DISCOVERABLE /* Device is not LE discoverable */
+#define BTA_DM_BLE_GENERAL_DISCOVERABLE BTM_BLE_GENERAL_DISCOVERABLE /* Device is LE General discoverable */
+#define BTA_DM_BLE_LIMITED_DISCOVERABLE BTM_BLE_LIMITED_DISCOVERABLE /* Device is LE Limited discoverable */
+#endif
+typedef UINT16 tBTA_DM_DISC; /* this discoverability mode is a bit mask among BR mode and LE mode */
/* Connectable Modes */
#define BTA_DM_NON_CONN BTM_NON_CONNECTABLE /* Device is not connectable. */
#define BTA_DM_CONN BTM_CONNECTABLE /* Device is connectable. */
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_DM_BLE_NON_CONNECTABLE BTM_BLE_NON_CONNECTABLE /* Device is LE non-connectable. */
+#define BTA_DM_BLE_CONNECTABLE BTM_BLE_CONNECTABLE /* Device is LE connectable. */
+#endif
// btla-specific ++
typedef UINT16 tBTA_DM_CONN;
@@ -204,6 +210,7 @@ typedef UINT16 tBTA_DM_CONN;
#define BTA_DM_CONN_PAIRED 1
/* Inquiry Modes */
+#define BTA_DM_INQUIRY_NONE BTM_INQUIRY_NONE /*No BR inquiry. */
#define BTA_DM_GENERAL_INQUIRY BTM_GENERAL_INQUIRY /* Perform general inquiry. */
#define BTA_DM_LIMITED_INQUIRY BTM_LIMITED_INQUIRY /* Perform limited inquiry. */
@@ -291,6 +298,8 @@ typedef struct
UINT8 *bta_dm_eir_flags; /* flags for EIR */
UINT8 bta_dm_eir_manufac_spec_len; /* length of manufacturer specific in bytes */
UINT8 *bta_dm_eir_manufac_spec; /* manufacturer specific */
+ UINT8 bta_dm_eir_additional_len; /* length of additional data in bytes */
+ UINT8 *bta_dm_eir_additional; /* additional data */
} tBTA_DM_EIR_CONF;
#if BLE_INCLUDED == TRUE
@@ -302,16 +311,22 @@ typedef struct
#define BTA_BLE_ADV_FLAG_MASK BTM_BLE_ADV_FLAG_MASK
#define BTA_BLE_LIMIT_DISC_MASK BTM_BLE_LIMIT_DISC_MASK
-#define BTA_BLE_AD_BIT_DEV_NAME BTM_BLE_AD_BIT_DEV_NAME
-#define BTA_BLE_AD_BIT_FLAGS BTM_BLE_AD_BIT_FLAGS
-#define BTA_BLE_AD_BIT_MANU BTM_BLE_AD_BIT_MANU
-#define BTA_BLE_AD_BIT_TX_PWR BTM_BLE_AD_BIT_TX_PWR
-#define BTA_BLE_AD_BIT_ATTR BTM_BLE_AD_BIT_ATTR
-#define BTA_BLE_AD_BIT_INT_RANGE BTM_BLE_AD_BIT_INT_RANGE
-#define BTA_BLE_AD_BIT_SERVICE BTM_BLE_AD_BIT_SERVICE
-#define BTA_BLE_AD_BIT_SERVICE_SOL BTM_BLE_AD_BIT_SERVICE_SOL
-#define BTA_BLE_AD_BIT_SERVICE_DATA BTM_BLE_AD_BIT_SERVICE_DATA
-#define BTA_BLE_AD_BIT_SIGN_DATA BTM_BLE_AD_BIT_SIGN_DATA
+/* ADV data bit mask */
+#define BTA_BLE_AD_BIT_DEV_NAME BTM_BLE_AD_BIT_DEV_NAME
+#define BTA_BLE_AD_BIT_FLAGS BTM_BLE_AD_BIT_FLAGS
+#define BTA_BLE_AD_BIT_MANU BTM_BLE_AD_BIT_MANU
+#define BTA_BLE_AD_BIT_TX_PWR BTM_BLE_AD_BIT_TX_PWR
+#define BTA_BLE_AD_BIT_INT_RANGE BTM_BLE_AD_BIT_INT_RANGE
+#define BTA_BLE_AD_BIT_SERVICE BTM_BLE_AD_BIT_SERVICE
+#define BTA_BLE_AD_BIT_APPEARANCE BTM_BLE_AD_BIT_APPEARANCE
+#define BTA_BLE_AD_BIT_PROPRIETARY BTM_BLE_AD_BIT_PROPRIETARY
+#define BTA_DM_BLE_AD_BIT_SERVICE_SOL BTM_BLE_AD_BIT_SERVICE_SOL
+#define BTA_DM_BLE_AD_BIT_SERVICE_DATA BTM_BLE_AD_BIT_SERVICE_DATA
+#define BTA_DM_BLE_AD_BIT_SIGN_DATA BTM_BLE_AD_BIT_SIGN_DATA
+#define BTA_DM_BLE_AD_BIT_SERVICE_128SOL BTM_BLE_AD_BIT_SERVICE_128SOL
+#define BTA_DM_BLE_AD_BIT_PUBLIC_ADDR BTM_BLE_AD_BIT_PUBLIC_ADDR
+#define BTA_DM_BLE_AD_BIT_RANDOM_ADDR BTM_BLE_AD_BIT_RANDOM_ADDR
+
typedef UINT16 tBTA_BLE_AD_MASK;
/* slave preferred connection interval range */
@@ -330,36 +345,36 @@ typedef struct
UINT16 *p_uuid;
}tBTA_BLE_SERVICE;
-/* attribute data */
+
typedef struct
{
- UINT16 uuid;
- UINT16 data_len;
- UINT8 *p_data;
-}tBTA_BLE_ATTR;
-
-#define BTA_BLE_NUM_AD_ATTR_MAX BTM_BLE_NUM_AD_ATTR_MAX
+ UINT8 len;
+ UINT8 *p_val;
+}tBTA_BLE_MANU;
-/* attribute list contained in adv data */
typedef struct
{
- UINT8 num_attr;
- tBTA_BLE_ATTR attr_list[BTA_BLE_NUM_AD_ATTR_MAX];
-}tBTA_BLE_ATTR_DATA;
+ UINT8 adv_type;
+ UINT8 len;
+ UINT8 *p_val; /* number of len byte */
+}tBTA_BLE_PROP_ELEM;
+/* vendor proprietary adv type */
typedef struct
{
- UINT8 len;
- UINT8 *p_val;
-}tBTA_BLE_MANU;
+ UINT8 num_elem;
+ tBTA_BLE_PROP_ELEM *p_elem;
+}tBTA_BLE_PROPRIETARY;
typedef struct
{
- tBTA_BLE_MANU manu; /* manufactuer data */
- tBTA_BLE_INT_RANGE int_range; /* slave prefered conn interval range */
- tBTA_BLE_SERVICE services; /* services */
- tBTA_BLE_ATTR_DATA attr; /* attribute data */
- UINT8 flag;
+ tBTA_BLE_MANU manu; /* manufactuer data */
+ tBTA_BLE_INT_RANGE int_range; /* slave prefered conn interval range */
+ tBTA_BLE_SERVICE services; /* services */
+ UINT16 appearance; /* appearance data */
+ UINT8 flag;
+ tBTA_BLE_PROPRIETARY *p_proprietary;
+
}tBTA_BLE_ADV_DATA;
/* These are the fields returned in each device adv packet. It
@@ -373,11 +388,84 @@ typedef struct
UINT8 tx_power_level;
UINT8 remote_name_len;
UINT8 *p_remote_name;
- tBTA_BLE_ATTR_DATA attr_data;
tBTA_BLE_SERVICE service;
} tBTA_BLE_INQ_DATA;
#endif
+/* BLE customer specific feature function type definitions */
+/* data type used on customer specific feature for RSSI monitoring */
+#define BTA_BLE_RSSI_ALERT_HI 0
+#define BTA_BLE_RSSI_ALERT_RANGE 1
+#define BTA_BLE_RSSI_ALERT_LO 2
+typedef UINT8 tBTA_DM_BLE_RSSI_ALERT_TYPE;
+
+#define BTA_BLE_RSSI_ALERT_NONE BTM_BLE_RSSI_ALERT_NONE /* (0) */
+#define BTA_BLE_RSSI_ALERT_HI_BIT BTM_BLE_RSSI_ALERT_HI_BIT /* (1) */
+#define BTA_BLE_RSSI_ALERT_RANGE_BIT BTM_BLE_RSSI_ALERT_RANGE_BIT /* (1 << 1) */
+#define BTA_BLE_RSSI_ALERT_LO_BIT BTM_BLE_RSSI_ALERT_LO_BIT /* (1 << 2) */
+typedef UINT8 tBTA_DM_BLE_RSSI_ALERT_MASK;
+
+
+typedef void (tBTA_DM_BLE_RSSI_CBACK) (BD_ADDR bd_addr, tBTA_DM_BLE_RSSI_ALERT_TYPE alert_type, INT8 rssi);
+
+/* max number of filter spot for different filter type */
+#define BTA_DM_BLE_MAX_UUID_FILTER BTM_BLE_MAX_UUID_FILTER /* 8 */
+#define BTA_DM_BLE_MAX_ADDR_FILTER BTM_BLE_MAX_ADDR_FILTER /* 8 */
+#define BTA_DM_BLE_PF_STR_COND_MAX BTM_BLE_PF_STR_COND_MAX /* 4 apply to manu data , or local name */
+#define BTA_DM_BLE_PF_STR_LEN_MAX BTM_BLE_PF_STR_LEN_MAX /* match for first 20 bytes */
+
+#define BTA_DM_BLE_PF_LOGIC_OR 0
+#define BTA_DM_BLE_PF_LOGIC_AND 1
+typedef UINT8 tBTA_DM_BLE_PF_LOGIC_TYPE;
+
+enum
+{
+ BTA_DM_BLE_SCAN_COND_ADD,
+ BTA_DM_BLE_SCAN_COND_DELETE,
+ BTA_DM_BLE_SCAN_COND_CLEAR = 2
+};
+typedef UINT8 tBTA_DM_BLE_SCAN_COND_OP;
+
+/* filter selection bit index */
+#define BTA_DM_BLE_PF_ADDR_FILTER BTM_BLE_PF_ADDR_FILTER
+#define BTA_DM_BLE_PF_SRVC_UUID BTM_BLE_PF_SRVC_UUID
+#define BTA_DM_BLE_PF_SRVC_SOL_UUID BTM_BLE_PF_SRVC_SOL_UUID
+#define BTA_DM_BLE_PF_LOCAL_NAME BTM_BLE_PF_LOCAL_NAME
+#define BTA_DM_BLE_PF_MANU_DATA BTM_BLE_PF_MANU_DATA
+#define BTA_DM_BLE_PF_SRVC_DATA BTM_BLE_PF_SRVC_DATA
+#define BTA_DM_BLE_PF_TYPE_MAX BTM_BLE_PF_TYPE_MAX
+typedef UINT8 tBTA_DM_BLE_PF_COND_TYPE;
+
+typedef struct
+{
+ tBLE_BD_ADDR *p_target_addr; /* target address, if NULL, generic UUID filter */
+ tBT_UUID uuid; /* UUID condition */
+ tBTA_DM_BLE_PF_LOGIC_TYPE cond_logic; /* AND/OR */
+}tBTA_DM_BLE_PF_UUID_COND;
+
+typedef struct
+{
+ UINT8 data_len; /* <= 20 bytes */
+ UINT8 *p_data;
+}tBTA_DM_BLE_PF_LOCAL_NAME_COND;
+
+typedef struct
+{
+ UINT16 company_id; /* company ID */
+ UINT8 data_len; /* <= 20 bytes */
+ UINT8 *p_pattern;
+}tBTA_DM_BLE_PF_MANU_COND;
+
+typedef union
+{
+ tBLE_BD_ADDR target_addr;
+ tBTA_DM_BLE_PF_LOCAL_NAME_COND local_name; /* lcoal name filtering */
+ tBTA_DM_BLE_PF_MANU_COND manu_data; /* manufactuer data filtering */
+ tBTA_DM_BLE_PF_UUID_COND srvc_uuid; /* service UUID filtering */
+ tBTA_DM_BLE_PF_UUID_COND solicitate_uuid; /* solicitated service UUID filtering */
+}tBTA_DM_BLE_PF_COND_PARAM;
+
+
typedef INT8 tBTA_DM_RSSI_VALUE;
typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE;
@@ -430,8 +518,8 @@ typedef struct
typedef struct
{
BD_ADDR bd_addr; /* BD address peer device. */
- BD_NAME bd_name; /* Name of peer device. */
DEV_CLASS dev_class; /* Class of Device */
+ BD_NAME bd_name; /* Name of peer device. */
} tBTA_DM_PIN_REQ;
/* BLE related definition */
@@ -481,12 +569,13 @@ typedef tBTM_LE_PENC_KEYS tBTA_LE_PENC_KEYS ;
typedef tBTM_LE_PCSRK_KEYS tBTA_LE_PCSRK_KEYS;
typedef tBTM_LE_LENC_KEYS tBTA_LE_LENC_KEYS ;
typedef tBTM_LE_LCSRK_KEYS tBTA_LE_LCSRK_KEYS ;
+typedef tBTM_LE_PID_KEYS tBTA_LE_PID_KEYS ;
typedef union
{
tBTA_LE_PENC_KEYS penc_key; /* received peer encryption key */
tBTA_LE_PCSRK_KEYS psrk_key; /* received peer device SRK */
- BT_OCTET16 pid_key; /* peer device ID key */
+ tBTA_LE_PID_KEYS pid_key; /* peer device ID key */
tBTA_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
tBTA_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
}tBTA_LE_KEY_VALUE;
@@ -538,6 +627,9 @@ typedef struct
LINK_KEY key; /* Link key associated with peer device. */
UINT8 key_type; /* The type of Link Key */
BOOLEAN success; /* TRUE of authentication succeeded, FALSE if failed. */
+#if BLE_INCLUDED == TRUE
+ BOOLEAN privacy_enabled; /* used for BLE device only */
+#endif
UINT8 fail_reason; /* The HCI reason/error code for when success=FALSE */
} tBTA_DM_AUTH_CMPL;
@@ -565,6 +657,7 @@ typedef struct
{
BD_ADDR bd_addr; /* BD address peer device. */
UINT8 status; /* connection open/closed */
+ BOOLEAN is_removed; /* TRUE if device is removed when link is down */
} tBTA_DM_LINK_DOWN;
/* Structure associated with BTA_DM_ROLE_CHG_EVT */
@@ -589,6 +682,7 @@ typedef struct
{
UINT8 level; /* when paging or inquiring, level is 10.
Otherwise, the number of ACL links */
+ UINT8 level_flags; /* indicates individual flags */
} tBTA_DM_BUSY_LEVEL;
#define BTA_IO_CAP_OUT BTM_IO_CAP_OUT /* DisplayOnly */
@@ -630,6 +724,7 @@ typedef tBTM_OOB_DATA tBTA_OOB_DATA;
/* Structure associated with BTA_DM_SP_CFM_REQ_EVT */
typedef struct
{
+ /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
BD_ADDR bd_addr; /* peer address */
DEV_CLASS dev_class; /* peer CoD */
BD_NAME bd_name; /* peer device name */
@@ -661,6 +756,7 @@ typedef struct
/* Structure associated with BTA_DM_SP_KEY_NOTIF_EVT */
typedef struct
{
+ /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
BD_ADDR bd_addr; /* peer address */
DEV_CLASS dev_class; /* peer CoD */
BD_NAME bd_name; /* peer device name */
@@ -670,6 +766,7 @@ typedef struct
/* Structure associated with BTA_DM_SP_RMT_OOB_EVT */
typedef struct
{
+ /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
BD_ADDR bd_addr; /* peer address */
DEV_CLASS dev_class; /* peer CoD */
BD_NAME bd_name; /* peer device name */
@@ -845,7 +942,8 @@ typedef UINT8 tBTA_DM_PM_ACTTION;
/* index to bta_dm_ssr_spec */
#define BTA_DM_PM_SSR0 0
-#define BTA_DM_PM_SSR1 1
+#define BTA_DM_PM_SSR1 1 /* BTA_DM_PM_SSR1 will be dedicated for
+ HH SSR setting entry, no other profile can use it */
#define BTA_DM_PM_SSR2 2
#define BTA_DM_PM_SSR3 3
#define BTA_DM_PM_SSR4 4
@@ -1458,6 +1556,22 @@ BTA_API extern tBTA_STATUS BTA_DmGetDiRecord( UINT8 get_record_index, tBTA_DI_GE
/*******************************************************************************
**
+**
+** Function BTA_DmCloseACL
+**
+** Description This function force to close an ACL connection and remove the
+** device from the security database list of known devices.
+**
+** Parameters: bd_addr - Address of the peer device
+** remove_dev - remove device or not after link down
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev);
+
+/*******************************************************************************
+**
** Function BTA_SysFeatures
**
** Description This function is called to set system features.
@@ -1707,6 +1821,25 @@ BTA_API extern void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_
BTA_API extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
tBTA_DM_BLE_SEC_ACT sec_act);
+
+/*******************************************************************************
+**
+** Function BTA_DmBleObserve
+**
+** Description This procedure keep the device listening for advertising
+** events from a broadcast device.
+**
+** Parameters start: start or stop observe.
+** duration : Duration of the scan. Continuous scan if 0 is passed
+** p_results_cb: Callback to be called with scan results
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+ tBTA_DM_SEARCH_CBACK *p_results_cb);
+
+
#endif
// btla-specific ++
@@ -1721,6 +1854,47 @@ BTA_API extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *
*******************************************************************************/
BTA_API extern void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable);
// btla-specific --
+/*******************************************************************************
+**
+** Function BTA_DmBleConfigLocalPrivacy
+**
+** Description Enable/disable privacy on the local device
+**
+** Parameters: privacy_enable - enable/disabe privacy on remote device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable);
+
+/*******************************************************************************
+**
+** Function BTA_DmBleEnableRemotePrivacy
+**
+** Description Enable/disable privacy on a remote device
+**
+** Parameters: bd_addr - BD address of the peer
+** privacy_enable - enable/disabe privacy on remote device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleEnableRemotePrivacy(BD_ADDR bd_addr, BOOLEAN privacy_enable);
+
+
+/*******************************************************************************
+**
+** Function BTA_DmBleSetAdvConfig
+**
+** Description This function is called to override the BTA default ADV parameters.
+**
+** Parameters Pointer to User defined ADV data structure
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
+ tBTA_BLE_ADV_DATA *p_adv_cfg);
#ifdef __cplusplus
}
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
index eb7727945..1ea570c64 100644
--- a/bta/include/bta_av_api.h
+++ b/bta/include/bta_av_api.h
@@ -47,6 +47,7 @@
#define BTA_AV_FAIL_STREAM 3 /* stream connection failed */
#define BTA_AV_FAIL_RESOURCES 4 /* no resources */
#define BTA_AV_FAIL_ROLE 5 /* failed due to role management related issues */
+#define BTA_AV_FAIL_GET_CAP 6 /* get capability failed due to no SEP availale on the peer */
typedef UINT8 tBTA_AV_STATUS;
@@ -492,6 +493,8 @@ typedef struct
const UINT8 *p_meta_evt_ids;/* the the metadata Get Capabilities response for event id */
const tBTA_AV_ACT *p_act_tbl;/* the action function table for VDP stream */
tBTA_AV_REG *p_reg; /* action function to register VDP */
+ char avrc_controller_name[BTA_SERVICE_NAME_LEN]; /* Default AVRCP controller name */
+ char avrc_target_name[BTA_SERVICE_NAME_LEN]; /* Default AVRCP target name*/
} tBTA_AV_CFG;
#ifdef __cplusplus
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 0404847e6..78bdf134a 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2003-2012 Broadcom Corporation
+ * Copyright (C) 2003-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
* This is the public interface file for BTA GATT.
*
******************************************************************************/
+
#ifndef BTA_GATT_API_H
#define BTA_GATT_API_H
@@ -53,7 +54,7 @@ typedef struct
{
tBT_UUID uuid; /* uuid of the attribute */
UINT8 inst_id; /* instance ID */
-} tBTA_GATT_ID;
+} __attribute__((packed)) tBTA_GATT_ID;
/* Success code and error codes */
#define BTA_GATT_OK GATT_SUCCESS
@@ -90,6 +91,7 @@ typedef struct
#define BTA_GATT_INVALID_CFG GATT_INVALID_CFG /* 0x008b */
#define BTA_GATT_DUP_REG 0x008c
#define BTA_GATT_ALREADY_OPEN 0x008d /* 0x008d */
+#define BTA_GATT_CANCEL 0x008e /* 0x008e */
typedef UINT8 tBTA_GATT_STATUS;
#define BTA_GATT_INVALID_CONN_ID GATT_INVALID_CONN_ID
@@ -110,8 +112,9 @@ typedef UINT8 tBTA_GATT_STATUS;
#define BTA_GATTC_PREP_WRITE_EVT 11 /* GATT prepare write event */
#define BTA_GATTC_EXEC_EVT 12 /* execute write complete event */
#define BTA_GATTC_ACL_EVT 13 /* ACL up event */
-#define BTA_GATTC_CANCEL_OPEN_EVT 14 /* cancel open event */
+#define BTA_GATTC_CANCEL_OPEN_EVT 14 /* cancel open event */
#define BTA_GATTC_SRVC_CHG_EVT 15 /* service change event */
+
typedef UINT8 tBTA_GATTC_EVT;
typedef tGATT_IF tBTA_GATTC_IF;
@@ -562,6 +565,19 @@ extern "C"
/*******************************************************************************
**
+** Function BTA_GATTC_Init
+**
+** Description This function is called to initalize GATTC module
+**
+** Parameters None
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Init();
+
+/*******************************************************************************
+**
** Function BTA_GATTC_AppRegister
**
** Description This function is called to register application callbacks
@@ -968,11 +984,37 @@ BTA_API extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_r
tBTA_GATT_AUTH_REQ auth_req);
+/*******************************************************************************
+**
+** Function BTA_GATTC_Refresh
+**
+** Description Refresh the server cache of the remote device
+**
+** Parameters remote_bda: remote device BD address.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Refresh(BD_ADDR remote_bda);
/*******************************************************************************
** BTA GATT Server API
********************************************************************************/
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_Init
+**
+** Description This function is called to initalize GATTS module
+**
+** Parameters None
+**
+** Returns None
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_Init();
+
/*******************************************************************************
**
** Function BTA_GATTS_AppRegister
@@ -1208,6 +1250,24 @@ BTA_API extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_r
*******************************************************************************/
BTA_API extern void BTA_GATTS_Close(UINT16 conn_id);
+/*******************************************************************************
+**
+** Function BTA_GATTS_Listen
+**
+** Description Start advertisement to listen for connection request for a
+** GATT server
+**
+** Parameters server_if: server interface.
+** start: to start or stop listening for connection
+** remote_bda: remote device BD address, if listen to all device
+** use NULL.
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start,
+ BD_ADDR_PTR target_bda);
+
#ifdef __cplusplus
diff --git a/bta/include/bta_gattc_co.h b/bta/include/bta_gattc_co.h
index d2392b82a..fa882ecdb 100644
--- a/bta/include/bta_gattc_co.h
+++ b/bta/include/bta_gattc_co.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2010-2012 Broadcom Corporation
+ * Copyright (C) 2009-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -97,5 +97,19 @@ BTA_API extern void bta_gattc_co_cache_save(BD_ADDR server_bda, UINT16 evt,
BTA_API extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt,
UINT16 start_index, UINT16 conn_id);
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_reset
+**
+** Description This callout function is executed by GATTC to reset cache in
+** application
+**
+** Parameter server_bda: server bd address of this cache belongs to
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_reset(BD_ADDR server_bda);
+
#endif /* BTA_GATT_CO_H */
diff --git a/bta/include/bta_hh_api.h b/bta/include/bta_hh_api.h
index f613d30ae..2cd29f406 100644
--- a/bta/include/bta_hh_api.h
+++ b/bta/include/bta_hh_api.h
@@ -29,7 +29,7 @@
#endif
#ifndef BTA_HH_SSR_MAX_LATENCY_DEF
-#define BTA_HH_SSR_MAX_LATENCY_DEF 1600
+#define BTA_HH_SSR_MAX_LATENCY_DEF 800 /* 500 ms*/
#endif
#ifndef BTA_HH_SSR_MIN_TOUT_DEF
@@ -51,15 +51,28 @@
#define BTA_HH_ADD_DEV_EVT 11 /* Add Device callback */
#define BTA_HH_RMV_DEV_EVT 12 /* remove device finished */
#define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */
-#define BTA_HH_UPDATE_UCD_EVT 14
-#define BTA_HH_API_ERR_EVT 15 /* API error is caught */
+#define BTA_HH_DATA_EVT 15
+#define BTA_HH_API_ERR_EVT 16 /* API error is caught */
typedef UINT16 tBTA_HH_EVT;
+/* application ID(none-zero) for each type of device */
+#define BTA_HH_APP_ID_MI 1
+#define BTA_HH_APP_ID_KB 2
+#define BTA_HH_APP_ID_RMC 3
+#define BTA_HH_APP_ID_3DSG 4
+#define BTA_HH_APP_ID_JOY 5
+#define BTA_HH_APP_ID_GPAD 6
+#define BTA_HH_APP_ID_LE 0xff
+
/* defined the minimum offset */
#define BTA_HH_MIN_OFFSET L2CAP_MIN_OFFSET+1
+/* HID_HOST_MAX_DEVICES can not exceed 15 for th design of BTA HH */
+#define BTA_HH_IDX_INVALID 0xff
#define BTA_HH_MAX_KNOWN HID_HOST_MAX_DEVICES
+#define BTA_HH_MAX_DEVICE HID_HOST_MAX_DEVICES
+
/* invalid device handle */
#define BTA_HH_INVALID_HANDLE 0xff
@@ -107,7 +120,8 @@ enum
BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */
BTA_HH_ERR_NO_RES, /* out of system resources */
BTA_HH_ERR_AUTH_FAILED, /* authentication fail */
- BTA_HH_ERR_HDL
+ BTA_HH_ERR_HDL,
+ BTA_HH_ERR_SEC
};
typedef UINT8 tBTA_HH_STATUS;
@@ -162,6 +176,8 @@ typedef UINT8 tBTA_HH_TRANS_CTRL_TYPE;
typedef tHID_DEV_DSCP_INFO tBTA_HH_DEV_DESCR;
+#define BTA_HH_SSR_PARAM_INVALID HID_SSR_PARAM_INVALID
+
/* id DI is not existing in remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be set to 0xffff */
#define BTA_HH_VENDOR_ID_INVALID 0xffff
@@ -172,8 +188,8 @@ typedef struct
UINT16 vendor_id; /* vendor ID */
UINT16 product_id; /* product ID */
UINT16 version; /* version */
- UINT16 ssr_max_latency; /* SSR max latency */
- UINT16 ssr_min_tout; /* SSR min timeout */
+ UINT16 ssr_max_latency; /* SSR max latency, BTA_HH_SSR_PARAM_INVALID if unknown */
+ UINT16 ssr_min_tout; /* SSR min timeout, BTA_HH_SSR_PARAM_INVALID if unknown */
UINT8 ctry_code; /*Country Code.*/
tBTA_HH_DEV_DESCR descriptor;
}tBTA_HH_DEV_DSCP_INFO;
@@ -291,7 +307,7 @@ extern "C"
** Returns void
**
*******************************************************************************/
-BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback);
+BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback);
/*******************************************************************************
**
@@ -375,6 +391,28 @@ BTA_API extern void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type,
UINT8 rpt_id, UINT16 buf_size);
/*******************************************************************************
**
+** Function BTA_HhSetIdle
+**
+** Description send SET_IDLE to device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate);
+
+/*******************************************************************************
+**
+** Function BTA_HhGetIdle
+**
+** Description Send a GET_IDLE to HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetIdle(UINT8 dev_handle);
+
+/*******************************************************************************
+**
** Function BTA_HhSendCtrl
**
** Description Send HID_CONTROL request to a HID device.
@@ -455,6 +493,7 @@ BTA_API extern void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask,
**
*******************************************************************************/
BTA_API extern void BTA_HhRemoveDev(UINT8 dev_handle );
+
/*******************************************************************************
**
** Parsing Utility Functions
@@ -472,6 +511,11 @@ BTA_API extern void BTA_HhRemoveDev(UINT8 dev_handle );
BTA_API extern void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
UINT16 report_len);
+/* test commands */
+BTA_API extern void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id);
+
+
+
#ifdef __cplusplus
}
#endif
diff --git a/btif/co/bta_dm_co.c b/btif/co/bta_dm_co.c
index 611af2dbf..a310a008d 100644
--- a/btif/co/bta_dm_co.c
+++ b/btif/co/bta_dm_co.c
@@ -25,6 +25,12 @@
#if (BTM_OOB_INCLUDED == TRUE)
#include "btif_dm.h"
#endif
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+#include "bte_appl.h"
+#endif
+
+tBTE_APPL_CFG bte_appl_cfg = { 0x5, 0x4, 0x7, 0x7, 0x10 };
+
/*******************************************************************************
**
** Function bta_dm_co_get_compress_memory
@@ -352,9 +358,10 @@ void bta_dm_co_le_io_key_req(BD_ADDR bd_addr, UINT8 *p_max_key_size,
void bta_dm_co_ble_load_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
tBTA_BLE_LOCAL_ID_KEYS *p_id_keys)
{
- BTIF_TRACE_ERROR0("##################################");
- BTIF_TRACE_ERROR0("bta_dm_co_ble_load_local_keys: TBD Load local keys if any are persisted");
- BTIF_TRACE_ERROR0("##################################");
+ BTIF_TRACE_DEBUG0("##################################");
+ BTIF_TRACE_DEBUG0("bta_dm_co_ble_load_local_keys: Load local keys if any are persisted");
+ BTIF_TRACE_DEBUG0("##################################");
+ btif_dm_get_ble_local_keys( p_key_mask, er, p_id_keys);
}
/*******************************************************************************
@@ -387,14 +394,10 @@ void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
* If the answer can not be obtained right away,
* set *p_oob_data to BTA_OOB_UNKNOWN and call bta_dm_ci_io_req() when the answer is available */
+ *p_oob_data = FALSE;
+
/* *p_auth_req by default is FALSE for devices with NoInputNoOutput; TRUE for other devices. */
- BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_auth_req=%d ble_authereq=%d", *p_auth_req, bte_appl_cfg.ble_auth_req);
- BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_io_cap=%d ble_io_cap=%d", *p_io_cap, bte_appl_cfg.ble_io_cap);
- BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_init_key=%d ble_init_key=%d", *p_init_key, bte_appl_cfg.ble_init_key);
- BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_resp_key=%d ble_resp_key=%d", *p_resp_key, bte_appl_cfg.ble_resp_key );
- BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_max_key_size=%d ble_max_key_size=%d", *p_max_key_size, bte_appl_cfg.ble_max_key_size );
- *p_oob_data = FALSE;
if (bte_appl_cfg.ble_auth_req)
*p_auth_req = bte_appl_cfg.ble_auth_req | (bte_appl_cfg.ble_auth_req & 0x04) | ((*p_auth_req) & 0x04);
@@ -407,9 +410,8 @@ void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
if (bte_appl_cfg.ble_resp_key<=7)
*p_resp_key = bte_appl_cfg.ble_resp_key;
- if (bte_appl_cfg.ble_max_key_size<=16)
+ if (bte_appl_cfg.ble_max_key_size > 7 && bte_appl_cfg.ble_max_key_size <= 16)
*p_max_key_size = bte_appl_cfg.ble_max_key_size;
-
}
diff --git a/btif/co/bta_gattc_co.c b/btif/co/bta_gattc_co.c
new file mode 100644
index 000000000..1a71d69f5
--- /dev/null
+++ b/btif/co/bta_gattc_co.c
@@ -0,0 +1,139 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#include "gki.h"
+#include "bta_gattc_co.h"
+#include "bta_gattc_ci.h"
+
+#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
+#if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_open
+**
+** Description This callout function is executed by GATTC when a GATT server
+** cache is ready to be sent.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** evt: call in event to be passed in when cache open is done.
+** conn_id: connection ID of this cache operation attach to.
+** to_save: open cache to save or to load.
+**
+** Returns void.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt, UINT16 conn_id, BOOLEAN to_save)
+{
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ /* open NV cache and send call in */
+ bta_gattc_ci_cache_open(server_bda, evt, status, conn_id);
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_load
+**
+** Description This callout function is executed by GATT when server cache
+** is required to load.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** evt: call in event to be passed in when cache save is done.
+** num_attr: number of attribute to be save.
+** attr_index: starting attribute index of the save operation.
+** conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 start_index, UINT16 conn_id)
+{
+ UINT16 num_attr = 0;
+ tBTA_GATTC_NV_ATTR attr[BTA_GATTC_NV_LOAD_MAX];
+ tBTA_GATT_STATUS status = BTA_GATT_MORE;
+
+ bta_gattc_ci_cache_load(server_bda, evt, num_attr, attr, status, conn_id);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_save
+**
+** Description This callout function is executed by GATT when a server cache
+** is available to save.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** evt: call in event to be passed in when cache save is done.
+** num_attr: number of attribute to be save.
+** p_attr: pointer to the list of attributes to save.
+** attr_index: starting attribute index of the save operation.
+** conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
+ tBTA_GATTC_NV_ATTR *p_attr_list, UINT16 attr_index, UINT16 conn_id)
+{
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ bta_gattc_ci_cache_save(server_bda, evt, status, conn_id);
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_close
+**
+** Description This callout function is executed by GATTC when a GATT server
+** cache is written completely.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** conn_id: connection ID of this cache operation attach to.
+**
+** Returns void.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
+{
+ /* close NV when server cache is done saving or loading,
+ does not need to do anything for now on Insight */
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_reset
+**
+** Description This callout function is executed by GATTC to reset cache in
+** application
+**
+** Parameter server_bda: server bd address of this cache belongs to
+**
+** Returns void.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_reset(BD_ADDR server_bda)
+{
+}
+
+#endif
+#endif
+
diff --git a/btif/co/bta_gatts_co.c b/btif/co/bta_gatts_co.c
new file mode 100644
index 000000000..725d14595
--- /dev/null
+++ b/btif/co/bta_gatts_co.c
@@ -0,0 +1,243 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_co.c
+**
+** Description: This file contains the GATT client call-out
+** function implementation for Insight.
+**
+** Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_api.h"
+
+#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
+#if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <stdlib.h>
+#include "gki.h"
+#include "bd.h"
+#include "bta_gatts_co.h"
+
+/*****************************************************************************
+** Local type definitions
+*****************************************************************************/
+
+#define BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE 50
+
+typedef struct
+{
+ BOOLEAN enable;
+ UINT8 num_clients;
+ tBTA_GATTS_SRV_CHG srv_chg[BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE];
+} __attribute__((packed)) btif_gatts_srv_chg_cb_t;
+
+/*****************************************************************************
+** Static variables
+*****************************************************************************/
+
+static btif_gatts_srv_chg_cb_t btif_gatts_srv_chg_cb;
+
+/*****************************************************************************
+** Static functions
+*****************************************************************************/
+
+static void btif_gatts_check_init(void)
+{
+ btif_gatts_srv_chg_cb_t *p_cb= &btif_gatts_srv_chg_cb;
+
+ if (!p_cb->enable)
+ {
+ memset(p_cb, 0, sizeof(btif_gatts_srv_chg_cb_t));
+ p_cb->enable = TRUE;
+ }
+}
+
+static BOOLEAN btif_gatts_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
+ tBTA_GATTS_SRV_CHG_REQ *p_req,
+ tBTA_GATTS_SRV_CHG_RSP *p_rsp)
+{
+ BOOLEAN status = TRUE;
+ BOOLEAN found = FALSE;
+ UINT8 i, j, idx, last_idx;
+ btif_gatts_srv_chg_cb_t *p_cb = &btif_gatts_srv_chg_cb;
+
+ btif_gatts_check_init();
+
+ switch (cmd)
+ {
+ case BTA_GATTS_SRV_CHG_CMD_ADD_CLIENT:
+
+ if (p_cb->num_clients < BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE)
+ {
+ memcpy(&p_cb->srv_chg[p_cb->num_clients], &p_req->srv_chg, sizeof(tBTA_GATTS_SRV_CHG));
+ p_cb->num_clients++;
+ } else {
+ status = FALSE;
+ }
+ break;
+
+ case BTA_GATTS_SRV_CHG_CMD_UPDATE_CLIENT:
+
+ for (i=0; i != p_cb->num_clients; ++i)
+ {
+ if (!memcmp(p_cb->srv_chg[i].bda, p_req->srv_chg.bda, sizeof(BD_ADDR)))
+ {
+ found = TRUE;
+ memcpy(&p_cb->srv_chg[i], &p_req->srv_chg, sizeof(tBTA_GATTS_SRV_CHG));
+ break;
+ }
+ }
+
+ if (!found)
+ status = FALSE;
+ break;
+
+ case BTA_GATTS_SRV_CHG_CMD_REMOVE_CLIENT:
+
+ for (i=0; i != p_cb->num_clients; ++i)
+ {
+ if (!memcmp(p_cb->srv_chg[i].bda, p_req->srv_chg.bda, sizeof(BD_ADDR)))
+ {
+ found = TRUE;
+ last_idx = p_cb->num_clients - 1;
+
+ if (i != last_idx )
+ {
+ /* Update the array so there is no gap */
+ for (j=i; j != last_idx; ++j )
+ {
+ memcpy(&p_cb->srv_chg[j], &p_cb->srv_chg[j+1], sizeof(tBTA_GATTS_SRV_CHG));
+ }
+
+ }
+
+ /* Reset the last client and update num_clients */
+ memset(&p_cb->srv_chg[last_idx], 0, sizeof(tBTA_GATTS_SRV_CHG));
+ p_cb->num_clients--;
+ break;
+ }
+ }
+
+ if (!found)
+ status = FALSE;
+ break;
+
+ case BTA_GATTS_SRV_CHG_CMD_READ_NUM_CLENTS:
+ p_rsp->num_clients = p_cb->num_clients;
+ break;
+
+ case BTA_GATTS_SRV_CHG_CMD_READ_CLENT:
+ idx = p_req->client_read_index - 1;
+
+ if (idx < p_cb->num_clients )
+ memcpy(&p_rsp->srv_chg, &p_cb->srv_chg[idx], sizeof(tBTA_GATTS_SRV_CHG));
+ else
+ status = FALSE;
+ break;
+
+ default:
+ status = FALSE;
+ break;
+ }
+
+ return status;
+}
+
+/*****************************************************************************
+** Externally called functions
+*****************************************************************************/
+
+void btif_gatts_add_bonded_dev_from_nv(BD_ADDR bda)
+{
+ btif_gatts_srv_chg_cb_t *p_cb= &btif_gatts_srv_chg_cb;
+ BOOLEAN found = FALSE;
+ UINT8 i;
+
+ btif_gatts_check_init();
+
+ for (i=0; i != p_cb->num_clients; ++i)
+ {
+ if (!memcmp(p_cb->srv_chg[i].bda, bda, sizeof(BD_ADDR)))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ if (p_cb->num_clients < BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE)
+ {
+ bdcpy(p_cb->srv_chg[p_cb->num_clients].bda, bda);
+ p_cb->srv_chg[p_cb->num_clients].srv_changed = FALSE;
+ p_cb->num_clients++;
+ }
+ }
+}
+
+/*****************************************************************************
+** Call-out functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_gatts_co_update_handle_range
+**
+** Description This callout function is executed by GATTS when a GATT server
+** handle range ios to be added or removed.
+**
+** Parameter is_add: true is to add a handle range; otherwise is to delete.
+** p_hndl_range: handle range.
+**
+** Returns void.
+**
+*******************************************************************************/
+void bta_gatts_co_update_handle_range(BOOLEAN is_add, tBTA_GATTS_HNDL_RANGE *p_hndl_range)
+{
+}
+
+/*******************************************************************************
+**
+** Function bta_gatts_co_srv_chg
+**
+** Description This call-out is to read/write/remove service change related
+** informaiton. The request consists of the cmd and p_req and the
+** response is returned in p_rsp
+**
+** Parameter cmd - request command
+** p_req - request paramters
+** p_rsp - response data for the request
+**
+** Returns TRUE - if the request is processed successfully and
+** the response is returned in p_rsp.
+** FASLE - if the request can not be processed
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
+ tBTA_GATTS_SRV_CHG_REQ *p_req,
+ tBTA_GATTS_SRV_CHG_RSP *p_rsp)
+{
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_gatts_co_load_handle_range
+**
+** Description This callout function is executed by GATTS when a GATT server
+** handle range is requested to be loaded from NV.
+**
+** Parameter
+**
+** Returns void.
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
+ tBTA_GATTS_HNDL_RANGE *p_handle_range)
+{
+ return FALSE;
+}
+#endif
+#endif
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index b4ea4c223..e7f9be211 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -61,7 +61,10 @@ static int uhid_event(btif_hh_device_t *p_dev)
ssize_t ret;
memset(&ev, 0, sizeof(ev));
if(!p_dev)
+ {
APPL_TRACE_ERROR1("%s: Device not found",__FUNCTION__)
+ return -1;
+ }
ret = read(p_dev->fd, &ev, sizeof(ev));
if (ret == 0) {
APPL_TRACE_ERROR2("%s: Read HUP on uhid-cdev %s", __FUNCTION__,
@@ -91,7 +94,6 @@ static int uhid_event(btif_hh_device_t *p_dev)
APPL_TRACE_DEBUG0("UHID_CLOSE from uhid-dev\n");
break;
case UHID_OUTPUT:
- APPL_TRACE_DEBUG0("UHID_OUTPUT from uhid-dev\n");
APPL_TRACE_DEBUG2("UHID_OUTPUT: Report type = %d, report_size = %d"
,ev.u.output.rtype, ev.u.output.size);
//Send SET_REPORT with feature report if the report type in output event is FEATURE
@@ -331,8 +333,9 @@ void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id)
p_dev = &btif_hh_cb.devices[i];
if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
APPL_TRACE_WARNING3("%s: Found an existing device with the same handle "
- "dev_status = %d, dev_handle =%d",__FUNCTION__,
- p_dev->dev_status,p_dev->dev_handle);
+ "dev_status = %d, dev_handle =%d"
+ ,__FUNCTION__,p_dev->dev_status
+ ,p_dev->dev_handle);
btif_hh_close_poll_thread(p_dev);
break;
}
diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h
index c787becb7..19af505ac 100644
--- a/btif/include/btif_api.h
+++ b/btif/include/btif_api.h
@@ -325,4 +325,14 @@ bt_status_t btif_dut_mode_configure(uint8_t enable);
*******************************************************************************/
bt_status_t btif_dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len);
+/*******************************************************************************
+**
+** Function btif_le_test_mode
+**
+** Description Sends a HCI BLE Test command to the Controller
+**
+** Returns BT_STATUS_SUCCESS on success
+**
+*******************************************************************************/
+bt_status_t btif_le_test_mode(uint16_t opcode, uint8_t *buf, uint8_t len);
#endif /* BTIF_API_H */
diff --git a/btif/include/btif_common.h b/btif/include/btif_common.h
index 6bf885fde..f11b6294d 100644
--- a/btif/include/btif_common.h
+++ b/btif/include/btif_common.h
@@ -107,6 +107,9 @@ enum
BTIF_DM_CB_REMOVE_BOND, /*Remove bond */
BTIF_DM_CB_HID_REMOTE_NAME, /* Remote name callback for HID device */
BTIF_DM_CB_BOND_STATE_BONDING,
+ BTIF_DM_CB_LE_TX_TEST, /* BLE Tx Test command complete callback */
+ BTIF_DM_CB_LE_RX_TEST, /* BLE Rx Test command complete callback */
+ BTIF_DM_CB_LE_TEST_END, /* BLE Test mode end callback */
BTIF_HFP_CB_START = BTIF_SIG_CB_START(BTIF_HFP),
BTIF_HFP_CB_AUDIO_CONNECTING, /* HF AUDIO connect has been sent to BTA successfully */
diff --git a/btif/include/btif_dm.h b/btif/include/btif_dm.h
index 2d73c45fb..ed03e3419 100644
--- a/btif/include/btif_dm.h
+++ b/btif/include/btif_dm.h
@@ -19,7 +19,8 @@
#ifndef BTIF_DM_H
#define BTIF_DM_H
-/*******************************************************************************
+#include "bta_api.h"
+/************************************************************************************
** Functions
********************************************************************************/
@@ -45,5 +46,75 @@ void btif_dm_proc_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r);
BOOLEAN btif_dm_proc_rmt_oob(BD_ADDR bd_addr, BT_OCTET16 p_c, BT_OCTET16 p_r);
#endif /* BTIF_DM_OOB_TEST */
#endif /* BTM_OOB_INCLUDED */
+#if (BLE_INCLUDED == TRUE)
+
+typedef struct
+{
+ UINT8 ltk[BT_OCTET16_LEN];
+ UINT8 rand[BT_OCTET8_LEN];
+ UINT16 ediv;
+ UINT8 sec_level;
+ UINT8 key_size;
+}btif_dm_ble_penc_keys_t;
+
+typedef struct
+{
+ UINT32 counter;
+ UINT8 csrk[BT_OCTET16_LEN];
+ UINT8 sec_level;
+}btif_dm_ble_pcsrk_keys_t;
+
+typedef struct
+{
+ UINT16 div;
+ UINT8 key_size;
+ UINT8 sec_level;
+}btif_dm_ble_lenc_keys_t;
+
+typedef struct
+{
+ UINT32 counter;
+ UINT16 div;
+ UINT8 sec_level;
+
+}btif_dm_ble_lcsrk_keys_t;
+
+typedef struct
+{
+ BOOLEAN is_penc_key_rcvd;
+ btif_dm_ble_penc_keys_t penc_key; /* received peer encryption key */
+ BOOLEAN is_pcsrk_key_rcvd;
+ btif_dm_ble_pcsrk_keys_t pcsrk_key; /* received peer device SRK */
+ BOOLEAN is_pid_key_rcvd;
+ UINT8 pid_key[BT_OCTET16_LEN]; /* peer device ID key */
+ BOOLEAN is_lenc_key_rcvd;
+ btif_dm_ble_lenc_keys_t lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
+ BOOLEAN is_lcsrk_key_rcvd;
+ btif_dm_ble_lcsrk_keys_t lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
+} btif_dm_ble_cb_t;
+
+#define BTIF_DM_LE_KEY_PENC BTA_LE_KEY_PENC
+#define BTIF_DM_LE_KEY_PID BTA_LE_KEY_PID
+#define BTIF_DM_LE_KEY_PCSRK BTA_LE_KEY_PCSRK
+#define BTIF_DM_LE_KEY_LENC BTA_LE_KEY_LENC
+#define BTIF_DM_LE_KEY_LID BTA_LE_KEY_LID
+#define BTIF_DM_LE_KEY_LCSRK BTA_LE_KEY_LCSRK
+
+#define BTIF_DM_LE_LOCAL_KEY_IR (1<<0)
+#define BTIF_DM_LE_LOCAL_KEY_IRK (1<<1)
+#define BTIF_DM_LE_LOCAL_KEY_DHK (1<<2)
+#define BTIF_DM_LE_LOCAL_KEY_ER (1<<3)
+
+void btif_dm_load_ble_local_keys(void);
+void btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+ tBTA_BLE_LOCAL_ID_KEYS *p_id_keys);
+void btif_dm_save_ble_bonding_keys(void);
+void btif_dm_remove_ble_bonding_keys(void);
+void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ *p_ble_req);
+
+void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name,
+ tBT_DEVICE_TYPE dev_type);
+
+#endif /* BLE_INCLUDED */
#endif
diff --git a/btif/include/btif_gatt.h b/btif/include/btif_gatt.h
new file mode 100644
index 000000000..e71ba1ee3
--- /dev/null
+++ b/btif/include/btif_gatt.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/*****************************************************************************
+**
+** Name: btif_gatt.h
+**
+** Description:
+**
+******************************************************************************/
+
+#ifndef BTIF_GATT_H
+#define BTIF_GATT_H
+
+
+
+#endif
+
diff --git a/btif/include/btif_gatt_util.h b/btif/include/btif_gatt_util.h
new file mode 100644
index 000000000..37fe5011a
--- /dev/null
+++ b/btif/include/btif_gatt_util.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#ifndef BTIF_GATT_UTIL_H
+#define BTIF_GATT_UTIL_H
+
+void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src);
+void btif_to_bta_char_id(tBTA_GATT_ID *p_dest, btgatt_char_id_t *p_src);
+void btif_to_bta_srvc_id(tBTA_GATT_SRVC_ID *p_dest, btgatt_srvc_id_t *p_src);
+void btif_to_bta_response(tBTA_GATTS_RSP *p_dest, btgatt_response_t* p_src);
+
+void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
+void bta_to_btif_srvc_id(btgatt_srvc_id_t *p_dest, tBTA_GATT_SRVC_ID *p_src);
+void bta_to_btif_char_id(btgatt_char_id_t *p_dest, tBTA_GATT_ID *p_src);
+
+uint16_t set_read_value(btgatt_read_params_t *p_dest, tBTA_GATTC_READ *p_src);
+
+void btif_gatt_check_encrypted_link(BD_ADDR bd_addr);
+void btif_gatt_remove_encrypted_link(BD_ADDR bd_addr);
+
+
+#endif
+
diff --git a/btif/include/btif_hh.h b/btif/include/btif_hh.h
index 25063eb24..c77d59707 100644
--- a/btif/include/btif_hh.h
+++ b/btif/include/btif_hh.h
@@ -96,6 +96,7 @@ extern btif_hh_cb_t btif_hh_cb;
extern btif_hh_device_t *btif_hh_find_connected_dev_by_handle(UINT8 handle);
extern void btif_hh_remove_device(bt_bdaddr_t bd_addr);
+BOOLEAN btif_hh_add_added_dev(bt_bdaddr_t bda, tBTA_HH_ATTR_MASK attr_mask);
extern bt_status_t btif_hh_virtual_unplug(bt_bdaddr_t *bd_addr);
extern void btif_hh_disconnect(bt_bdaddr_t *bd_addr);
extern void btif_hh_setreport(btif_hh_device_t *p_dev, bthh_report_type_t r_type,
diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h
index 87dec3bb0..41507fbf8 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -105,7 +105,7 @@ bt_status_t btif_storage_set_remote_device_property(bt_bdaddr_t *remote_bd_addr,
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bdaddr,
+bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bd_addr,
uint32_t num_properties,
bt_property_t *properties);
@@ -231,19 +231,19 @@ bt_status_t btif_storage_write_hl_mdl_data(UINT8 app_idx, char *value, int value
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
+
bt_status_t btif_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr,
UINT16 attr_mask, UINT8 sub_class,
UINT8 app_id, UINT16 vendor_id,
UINT16 product_id, UINT16 version,
- UINT8 ctry_code, UINT16 dl_len,
- UINT8 *dsc_list);
+ UINT8 ctry_code, UINT16 dl_len, UINT8 *dsc_list);
/*******************************************************************************
**
** Function btif_storage_load_bonded_hid_info
**
-** Description BTIF storage API - Loads hid info for all the bonded devices
-** from NVRAM and adds those devices to the BTA_HH.
+** Description BTIF storage API - Loads hid info for all the bonded devices from NVRAM
+** and adds those devices to the BTA_HH.
**
** Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
**
@@ -284,7 +284,8 @@ bt_status_t btif_storage_load_autopair_device_list();
** FALSE otherwise
**
*******************************************************************************/
-BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_addr);
+
+BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_bd_addr);
/*******************************************************************************
**
@@ -296,7 +297,8 @@ BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_add
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_dev_addr);
+
+bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_bd_addr);
/*******************************************************************************
**
@@ -308,6 +310,45 @@ bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_de
** FALSE otherwise
**
*******************************************************************************/
-BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_dev_addr);
+BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_bd_addr);
+
+#if (BLE_INCLUDED == TRUE)
+bt_status_t btif_storage_add_ble_bonding_key( bt_bdaddr_t *remote_bd_addr,
+ char *key,
+ uint8_t key_type,
+ uint8_t key_length);
+bt_status_t btif_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+ UINT8 key_type,
+ char *key_value,
+ int key_length);
+
+bt_status_t btif_storage_add_ble_local_key(char *key,
+ uint8_t key_type,
+ uint8_t key_length);
+bt_status_t btif_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr);
+bt_status_t btif_storage_remove_ble_local_keys(void);
+bt_status_t btif_storage_get_ble_local_key(UINT8 key_type,
+ char *key_value,
+ int key_len);
+
+bt_status_t btif_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+ int *addr_type);
+
+bt_status_t btif_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+ UINT8 addr_type);
+
+#endif
+/*******************************************************************************
+**
+** Function btif_storage_get_remote_version
+**
+** Description Fetch remote version info on cached remote device
+**
+** Returns BT_STATUS_SUCCESS if found
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_get_remote_version(const bt_bdaddr_t *remote_bd_addr,
+ bt_remote_version_t *p_ver);
#endif /* BTIF_STORAGE_H */
diff --git a/btif/include/btif_util.h b/btif/include/btif_util.h
index 09dae6e33..ddb469966 100644
--- a/btif/include/btif_util.h
+++ b/btif/include/btif_util.h
@@ -22,6 +22,7 @@
#include <hardware/bluetooth.h>
#include <hardware/bt_hf.h>
#include <utils/Log.h>
+#include <sys/time.h>
#include "data_types.h"
#include "bt_types.h"
@@ -60,7 +61,7 @@ const char* dump_av_conn_state(UINT16 event);
const char* dump_av_audio_state(UINT16 event);
int str2bd(char *str, bt_bdaddr_t *addr);
-char *bd2str(bt_bdaddr_t *addr, bdstr_t *bdstr);
+char *bd2str(const bt_bdaddr_t *addr, bdstr_t *bdstr);
UINT32 devclass2uint(DEV_CLASS dev_class);
void uint2devclass(UINT32 dev, DEV_CLASS dev_class);
diff --git a/btif/include/uinput.h b/btif/include/uinput.h
index 5925703a7..9a25e4b45 100644
--- a/btif/include/uinput.h
+++ b/btif/include/uinput.h
@@ -262,6 +262,7 @@ extern "C" {
#define KEY_SUSPEND 205
#define KEY_CLOSE 206
#define KEY_PLAY 207
+#define KEY_FAST_FORWARD 208
#define KEY_UNKNOWN 220
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c
index 20d6a0702..ffeaaaf90 100644
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -35,6 +35,7 @@
#include <hardware/bt_hh.h>
#include <hardware/bt_hl.h>
#include <hardware/bt_pan.h>
+#include <hardware/bt_gatt.h>
#define LOG_NDDEBUG 0
#define LOG_TAG "bluedroid"
@@ -80,6 +81,8 @@ extern bthh_interface_t *btif_hh_get_interface();
extern bthl_interface_t *btif_hl_get_interface();
/*pan*/
extern btpan_interface_t *btif_pan_get_interface();
+/* gatt */
+extern btgatt_interface_t *btif_gatt_get_interface();
/************************************************************************************
** Functions
@@ -319,6 +322,8 @@ static const void* get_profile_interface (const char *profile_id)
if (is_profile(profile_id, BT_PROFILE_HEALTH_ID))
return btif_hl_get_interface();
+ if (is_profile(profile_id, BT_PROFILE_GATT_ID))
+ return btif_gatt_get_interface();
return NULL;
}
@@ -343,8 +348,20 @@ int dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len)
return btif_dut_mode_send(opcode, buf, len);
}
+int le_test_mode(uint16_t opcode, uint8_t* buf, uint8_t len)
+{
+ ALOGI("le_test_mode");
+
+ /* sanity check */
+ if (interface_ready() == FALSE)
+ return BT_STATUS_NOT_READY;
+
+ return btif_le_test_mode(opcode, buf, len);
+}
+
+
static const bt_interface_t bluetoothInterface = {
- sizeof(bt_interface_t),
+ sizeof(bluetoothInterface),
init,
enable,
disable,
@@ -366,7 +383,8 @@ static const bt_interface_t bluetoothInterface = {
ssp_reply,
get_profile_interface,
dut_mode_configure,
- dut_mode_send
+ dut_mode_send,
+ le_test_mode
};
const bt_interface_t* bluetooth__get_bluetooth_interface ()
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c
index 62339a907..ca39cc8f7 100755..100644
--- a/btif/src/btif_core.c
+++ b/btif/src/btif_core.c
@@ -290,6 +290,9 @@ static void btif_task(UINT32 params)
if (event == BT_EVT_TRIGGER_STACK_INIT)
{
BTIF_TRACE_DEBUG0("btif_task: received trigger stack init event");
+ #if (BLE_INCLUDED == TRUE)
+ btif_dm_load_ble_local_keys();
+ #endif
BTA_EnableBluetooth(bte_dm_evt);
}
@@ -830,6 +833,7 @@ bt_status_t btif_dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len)
BTM_VendorSpecificCommand(opcode, len, buf, btif_dut_mode_cback);
return BT_STATUS_SUCCESS;
}
+
/*****************************************************************************
**
** btif api adapter property functions
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index cb0971944..767cd0faa 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -38,10 +38,12 @@
#include "bta_api.h"
#include "btif_api.h"
#include "btif_util.h"
+#include "btif_dm.h"
#include "btif_storage.h"
#include "btif_hh.h"
#include "btif_config.h"
+#include "bta_gatt_api.h"
/******************************************************************************
** Constants & Macros
******************************************************************************/
@@ -61,7 +63,10 @@
#define BTIF_DM_DEFAULT_INQ_MAX_RESULTS 0
#define BTIF_DM_DEFAULT_INQ_MAX_DURATION 10
-typedef struct {
+
+
+typedef struct
+{
bt_bond_state_t state;
BD_ADDR bd_addr;
UINT8 is_temp;
@@ -70,9 +75,31 @@ typedef struct {
UINT8 autopair_attempts;
UINT8 is_local_initiated;
UINT8 bonded_pending_sdp;
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+ BOOLEAN is_le_only;
+ btif_dm_ble_cb_t ble;
+#endif
} btif_dm_pairing_cb_t;
-typedef struct {
+
+typedef struct
+{
+ UINT8 ir[BT_OCTET16_LEN];
+ UINT8 irk[BT_OCTET16_LEN];
+ UINT8 dhk[BT_OCTET16_LEN];
+}btif_dm_local_key_id_t;
+
+typedef struct
+{
+ BOOLEAN is_er_rcvd;
+ UINT8 er[BT_OCTET16_LEN];
+ BOOLEAN is_id_keys_rcvd;
+ btif_dm_local_key_id_t id_keys; /* ID kyes */
+
+}btif_dm_local_key_cb_t;
+
+typedef struct
+{
BD_ADDR bd_addr;
BD_NAME bd_name;
} btif_dm_remote_name_t;
@@ -98,7 +125,12 @@ static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr);
static void btif_dm_cb_hid_remote_name(tBTM_REMOTE_DEV_NAME *p_remote_name);
static void btif_update_remote_properties(BD_ADDR bd_addr, BD_NAME bd_name,
DEV_CLASS dev_class, tBT_DEVICE_TYPE dev_type);
-
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+static btif_dm_local_key_cb_t ble_local_key_cb;
+static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_ssp_key_notif);
+static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl);
+static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req);
+#endif
/******************************************************************************
** Externs
******************************************************************************/
@@ -283,6 +315,40 @@ static void bond_state_changed(bt_status_t status, bt_bdaddr_t *bd_addr, bt_bond
}
+/* store remote version in bt config to always have access
+ to it post pairing*/
+static void btif_update_remote_version_property(bt_bdaddr_t *p_bd)
+{
+ bt_property_t property;
+ UINT8 lmp_ver = 0;
+ UINT16 lmp_subver = 0;
+ UINT16 mfct_set = 0;
+ tBTM_STATUS btm_status;
+ bt_remote_version_t info;
+ bt_status_t status;
+ bdstr_t bdstr;
+
+ btm_status = BTM_ReadRemoteVersion(*(BD_ADDR*)p_bd, &lmp_ver,
+ &mfct_set, &lmp_subver);
+
+ ALOGD("remote version info [%s]: %x, %x, %x", bd2str(p_bd, &bdstr),
+ lmp_ver, mfct_set, lmp_subver);
+
+ if (btm_status == BTM_SUCCESS)
+ {
+ /* always update cache to ensure we have availability whenever BTM API
+ is not populated */
+ info.manufacturer = mfct_set;
+ info.sub_ver = lmp_subver;
+ info.version = lmp_ver;
+ BTIF_STORAGE_FILL_PROPERTY(&property,
+ BT_PROPERTY_REMOTE_VERSION_INFO, sizeof(bt_remote_version_t),
+ &info);
+ status = btif_storage_set_remote_device_property(p_bd, &property);
+ ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote version", status);
+ }
+}
+
static void btif_update_remote_properties(BD_ADDR bd_addr, BD_NAME bd_name,
DEV_CLASS dev_class, tBT_DEVICE_TYPE device_type)
@@ -379,12 +445,13 @@ static void btif_dm_cb_hid_remote_name(tBTM_REMOTE_DEV_NAME *p_remote_name)
int remove_hid_bond(bt_bdaddr_t *bd_addr)
{
- /* For HID device, inorder to avoid the HID device from re-connecting again after unpairing,
- * we need to do virtual unplug
- */
- bdstr_t bdstr;
- BTIF_TRACE_DEBUG2("%s---Removing HID bond--%s", __FUNCTION__,bd2str((bt_bdaddr_t *)bd_addr, &bdstr));
- return btif_hh_virtual_unplug(bd_addr);
+ /* For HID device, inorder to avoid the HID device from re-connecting again after unpairing,
+ * we need to do virtual unplug
+ */
+ bdstr_t bdstr;
+ BTIF_TRACE_DEBUG2("%s---Removing HID bond--%s", __FUNCTION__,bd2str((bt_bdaddr_t *)bd_addr, &bdstr));
+ return btif_hh_virtual_unplug(bd_addr);
+
}
/*******************************************************************************
**
@@ -398,18 +465,34 @@ int remove_hid_bond(bt_bdaddr_t *bd_addr)
*******************************************************************************/
static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr)
{
+ BOOLEAN is_hid = check_cod(bd_addr, COD_HID_POINTING);
+
+
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
- if (check_cod(bd_addr, COD_HID_POINTING)){
+
+ if (is_hid){
+
int status;
status = btif_hh_connect(bd_addr);
if(status != BT_STATUS_SUCCESS)
bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
}
else
+ {
+ int device_type;
+ int addr_type;
+ bdstr_t bdstr;
+ bd2str(bd_addr, &bdstr);
+ if(btif_config_get_int("Remote", (char const *)&bdstr,"DevType", &device_type) &&
+ (btif_storage_get_remote_addr_type(bd_addr, &addr_type) == BT_STATUS_SUCCESS) &&
+ (device_type == BT_DEVICE_TYPE_BLE))
+ {
+ BTA_DmAddBleDevice(bd_addr->address, addr_type, BT_DEVICE_TYPE_BLE);
+ }
BTA_DmBond ((UINT8 *)bd_addr->address);
-
- /* Track originator of bond creation */
- pairing_cb.is_local_initiated = TRUE;
+ }
+ /* Track originator of bond creation */
+ pairing_cb.is_local_initiated = TRUE;
}
@@ -629,7 +712,8 @@ static void btif_dm_ssp_cfm_req_evt(tBTA_DM_SP_CFM_REQ *p_ssp_cfm_req)
/* if just_works and bonding bit is not set treat this as temporary */
if (p_ssp_cfm_req->just_works && !(p_ssp_cfm_req->loc_auth_req & BTM_AUTH_BONDS) &&
- !(p_ssp_cfm_req->rmt_auth_req & BTM_AUTH_BONDS))
+ !(p_ssp_cfm_req->rmt_auth_req & BTM_AUTH_BONDS) &&
+ !(check_cod((bt_bdaddr_t*)&p_ssp_cfm_req->bd_addr, COD_HID_POINTING)))
pairing_cb.is_temp = TRUE;
else
pairing_cb.is_temp = FALSE;
@@ -1214,23 +1298,22 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
case BTA_DM_BUSY_LEVEL_EVT:
{
- UINT8 busy_level;
- busy_level = p_data->busy_level.level;
- if (busy_level & BTM_BL_INQUIRY_PAGING_MASK)
+
+ if (p_data->busy_level.level_flags & BTM_BL_INQUIRY_PAGING_MASK)
{
- if (busy_level == BTM_BL_INQUIRY_STARTED)
+ if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_STARTED)
{
HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
BT_DISCOVERY_STARTED);
btif_dm_inquiry_in_progress = TRUE;
}
- else if (busy_level == BTM_BL_INQUIRY_CANCELLED)
+ else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_CANCELLED)
{
HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
BT_DISCOVERY_STOPPED);
btif_dm_inquiry_in_progress = FALSE;
}
- else if (busy_level == BTM_BL_INQUIRY_COMPLETE)
+ else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_COMPLETE)
{
btif_dm_inquiry_in_progress = FALSE;
}
@@ -1240,6 +1323,9 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
case BTA_DM_LINK_UP_EVT:
bdcpy(bd_addr.address, p_data->link_up.bd_addr);
BTIF_TRACE_DEBUG0("BTA_DM_LINK_UP_EVT. Sending BT_ACL_STATE_CONNECTED");
+
+ btif_update_remote_version_property(&bd_addr);
+
HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
&bd_addr, BT_ACL_STATE_CONNECTED);
break;
@@ -1265,19 +1351,158 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
kill(getpid(), SIGKILL);
break;
- case BTA_DM_AUTHORIZE_EVT:
- case BTA_DM_SIG_STRENGTH_EVT:
- case BTA_DM_SP_RMT_OOB_EVT:
- case BTA_DM_SP_KEYPRESS_EVT:
- case BTA_DM_ROLE_CHG_EVT:
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
case BTA_DM_BLE_KEY_EVT:
+ BTIF_TRACE_DEBUG1("BTA_DM_BLE_KEY_EVT key_type=0x%02x ", p_data->ble_key.key_type);
+
+ /* If this pairing is by-product of local initiated GATT client Read or Write,
+ BTA would not have sent BTA_DM_BLE_SEC_REQ_EVT event and Bond state would not
+ have setup properly. Setup pairing_cb and notify App about Bonding state now*/
+ if (pairing_cb.state != BT_BOND_STATE_BONDING)
+ {
+ BTIF_TRACE_DEBUG0("Bond state not sent to App so far.Notify the app now");
+ bond_state_changed(BT_STATUS_SUCCESS, (bt_bdaddr_t*)p_data->ble_key.bd_addr,
+ BT_BOND_STATE_BONDING);
+ }
+ else if (memcmp (pairing_cb.bd_addr, p_data->ble_key.bd_addr, BD_ADDR_LEN)!=0)
+ {
+ BTIF_TRACE_ERROR1("BD mismatch discard BLE key_type=%d ",p_data->ble_key.key_type);
+ break;
+ }
+
+ switch (p_data->ble_key.key_type)
+ {
+ case BTA_LE_KEY_PENC:
+ BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_PENC");
+ pairing_cb.ble.is_penc_key_rcvd = TRUE;
+ memcpy(pairing_cb.ble.penc_key.ltk,p_data->ble_key.key_value.penc_key.ltk, 16);
+ memcpy(pairing_cb.ble.penc_key.rand, p_data->ble_key.key_value.penc_key.rand,8);
+ pairing_cb.ble.penc_key.ediv = p_data->ble_key.key_value.penc_key.ediv;
+ pairing_cb.ble.penc_key.sec_level = p_data->ble_key.key_value.penc_key.sec_level;
+
+ for (i=0; i<16; i++)
+ {
+ BTIF_TRACE_DEBUG2("pairing_cb.ble.penc_key.ltk[%d]=0x%02x",i,pairing_cb.ble.penc_key.ltk[i]);
+ }
+ for (i=0; i<8; i++)
+ {
+ BTIF_TRACE_DEBUG2("pairing_cb.ble.penc_key.rand[%d]=0x%02x",i,pairing_cb.ble.penc_key.rand[i]);
+ }
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.penc_key.ediv=0x%04x",pairing_cb.ble.penc_key.ediv);
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.penc_key.sec_level=0x%02x",pairing_cb.ble.penc_key.sec_level);
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.penc_key.key_size=0x%02x",pairing_cb.ble.penc_key.key_size);
+ break;
+
+ case BTA_LE_KEY_PID:
+ BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_PID");
+ pairing_cb.ble.is_pid_key_rcvd = TRUE;
+ memcpy(pairing_cb.ble.pid_key, p_data->ble_key.key_value.pid_key.irk, 16);
+ for (i=0; i<16; i++)
+ {
+ BTIF_TRACE_DEBUG2("pairing_cb.ble.pid_key[%d]=0x%02x",i,pairing_cb.ble.pid_key[i]);
+ }
+ break;
+
+ case BTA_LE_KEY_PCSRK:
+ BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_PCSRK");
+ pairing_cb.ble.is_pcsrk_key_rcvd = TRUE;
+ pairing_cb.ble.pcsrk_key.counter = p_data->ble_key.key_value.pcsrk_key.counter;
+ pairing_cb.ble.pcsrk_key.sec_level = p_data->ble_key.key_value.pcsrk_key.sec_level;
+ memcpy(pairing_cb.ble.pcsrk_key.csrk,p_data->ble_key.key_value.pcsrk_key.csrk,16);
+
+ for (i=0; i<16; i++)
+ {
+ BTIF_TRACE_DEBUG2("pairing_cb.ble.pcsrk_key.csrk[%d]=0x%02x",i,pairing_cb.ble.pcsrk_key.csrk[i]);
+ }
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.pcsrk_key.counter=0x%08x",pairing_cb.ble.pcsrk_key.counter);
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.pcsrk_key.sec_level=0x%02x",pairing_cb.ble.pcsrk_key.sec_level);
+ break;
+
+ case BTA_LE_KEY_LENC:
+ BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_LENC");
+ pairing_cb.ble.is_lenc_key_rcvd = TRUE;
+ pairing_cb.ble.lenc_key.div = p_data->ble_key.key_value.lenc_key.div;
+ pairing_cb.ble.lenc_key.key_size = p_data->ble_key.key_value.lenc_key.key_size;
+ pairing_cb.ble.lenc_key.sec_level = p_data->ble_key.key_value.lenc_key.sec_level;
+
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.lenc_key.div=0x%04x",pairing_cb.ble.lenc_key.div);
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.lenc_key.key_size=0x%02x",pairing_cb.ble.lenc_key.key_size);
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.lenc_key.sec_level=0x%02x",pairing_cb.ble.lenc_key.sec_level);
+ break;
+
+
+
+ case BTA_LE_KEY_LCSRK:
+ BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_LCSRK");
+ pairing_cb.ble.is_lcsrk_key_rcvd = TRUE;
+ pairing_cb.ble.lcsrk_key.counter = p_data->ble_key.key_value.lcsrk_key.counter;
+ pairing_cb.ble.lcsrk_key.div = p_data->ble_key.key_value.lcsrk_key.div;
+ pairing_cb.ble.lcsrk_key.sec_level = p_data->ble_key.key_value.lcsrk_key.sec_level;
+
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.lcsrk_key.div=0x%04x",pairing_cb.ble.lcsrk_key.div);
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.lcsrk_key.counter=0x%08x",pairing_cb.ble.lcsrk_key.counter);
+ BTIF_TRACE_DEBUG1("pairing_cb.ble.lcsrk_key.sec_level=0x%02x",pairing_cb.ble.lcsrk_key.sec_level);
+
+ break;
+
+ default:
+ BTIF_TRACE_ERROR1("unknown BLE key type (0x%02x)", p_data->ble_key.key_type);
+ break;
+ }
+
+ break;
case BTA_DM_BLE_SEC_REQ_EVT:
+ BTIF_TRACE_DEBUG0("BTA_DM_BLE_SEC_REQ_EVT. ");
+ btif_dm_ble_sec_req_evt(&p_data->ble_req);
+ break;
case BTA_DM_BLE_PASSKEY_NOTIF_EVT:
+ BTIF_TRACE_DEBUG0("BTA_DM_BLE_PASSKEY_NOTIF_EVT. ");
+ btif_dm_ble_key_notif_evt(&p_data->key_notif);
+ break;
case BTA_DM_BLE_PASSKEY_REQ_EVT:
+ BTIF_TRACE_DEBUG0("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
+ btif_dm_ble_passkey_req_evt(&p_data->pin_req);
+ break;
case BTA_DM_BLE_OOB_REQ_EVT:
+ BTIF_TRACE_DEBUG0("BTA_DM_BLE_OOB_REQ_EVT. ");
+ break;
case BTA_DM_BLE_LOCAL_IR_EVT:
+ BTIF_TRACE_DEBUG0("BTA_DM_BLE_LOCAL_IR_EVT. ");
+ ble_local_key_cb.is_id_keys_rcvd = TRUE;
+ memcpy(&ble_local_key_cb.id_keys.irk[0], &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16));
+ memcpy(&ble_local_key_cb.id_keys.ir[0], &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16));
+ memcpy(&ble_local_key_cb.id_keys.dhk[0], &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16));
+ btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.irk[0],
+ BTIF_DM_LE_LOCAL_KEY_IR,
+ BT_OCTET16_LEN);
+ btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.ir[0],
+ BTIF_DM_LE_LOCAL_KEY_IRK,
+ BT_OCTET16_LEN);
+ btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.dhk[0],
+ BTIF_DM_LE_LOCAL_KEY_DHK,
+ BT_OCTET16_LEN);
+ break;
case BTA_DM_BLE_LOCAL_ER_EVT:
+ BTIF_TRACE_DEBUG0("BTA_DM_BLE_LOCAL_ER_EVT. ");
+ ble_local_key_cb.is_er_rcvd = TRUE;
+ memcpy(&ble_local_key_cb.er[0], &p_data->ble_er[0], sizeof(BT_OCTET16));
+ btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.er[0],
+ BTIF_DM_LE_LOCAL_KEY_ER,
+ BT_OCTET16_LEN);
+ break;
+
case BTA_DM_BLE_AUTH_CMPL_EVT:
+ BTIF_TRACE_DEBUG0("BTA_DM_BLE_KEY_EVT. ");
+ btif_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl);
+ break;
+#endif
+
+ case BTA_DM_AUTHORIZE_EVT:
+ case BTA_DM_SIG_STRENGTH_EVT:
+ case BTA_DM_SP_RMT_OOB_EVT:
+ case BTA_DM_SP_KEYPRESS_EVT:
+ case BTA_DM_ROLE_CHG_EVT:
+
default:
BTIF_TRACE_WARNING1( "btif_dm_cback : unhandled event (%d)", event );
break;
@@ -1328,6 +1553,26 @@ static void btif_dm_generic_evt(UINT16 event, char* p_param)
bond_state_changed(BT_STATUS_SUCCESS, (bt_bdaddr_t *)p_param, BT_BOND_STATE_BONDING);
}
break;
+ case BTIF_DM_CB_LE_TX_TEST:
+ case BTIF_DM_CB_LE_RX_TEST:
+ {
+ uint8_t status;
+ STREAM_TO_UINT8(status, p_param);
+ HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
+ (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, 0);
+ }
+ break;
+ case BTIF_DM_CB_LE_TEST_END:
+ {
+ uint8_t status;
+ uint16_t count = 0;
+ STREAM_TO_UINT8(status, p_param);
+ if (status == 0)
+ STREAM_TO_UINT16(count, p_param);
+ HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
+ (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, count);
+ }
+ break;
default:
{
BTIF_TRACE_WARNING2("%s : Unknown event 0x%x", __FUNCTION__, event);
@@ -1469,7 +1714,7 @@ bt_status_t btif_dm_start_discovery(void)
/* TODO: Do we need to handle multiple inquiries at the same time? */
/* Set inquiry params and call API */
-#if (BLE_INCLUDED == TRUE)
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
inq_params.mode = BTA_DM_GENERAL_INQUIRY|BTA_BLE_GENERAL_INQUIRY;
#else
inq_params.mode = BTA_DM_GENERAL_INQUIRY;
@@ -1551,6 +1796,33 @@ bt_status_t btif_dm_cancel_bond(const bt_bdaddr_t *bd_addr)
*/
if (pairing_cb.state == BT_BOND_STATE_BONDING)
{
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+ if (pairing_cb.is_ssp)
+ {
+ if (pairing_cb.is_le_only)
+ {
+ BTA_DmBleSecurityGrant((UINT8 *)bd_addr->address,BTA_DM_SEC_PAIR_NOT_SPT);
+ }
+ else
+ BTA_DmConfirm( (UINT8 *)bd_addr->address, FALSE);
+ }
+ else
+ {
+ if (pairing_cb.is_le_only)
+ {
+ BTA_DmBondCancel ((UINT8 *)bd_addr->address);
+ }
+ else
+ {
+ BTA_DmPinReply( (UINT8 *)bd_addr->address, FALSE, 0, NULL);
+ }
+ /* Cancel bonding, in case it is in ACL connection setup state */
+ BTA_DmBondCancel ((UINT8 *)bd_addr->address);
+ }
+
+#else
if (pairing_cb.is_ssp)
{
BTA_DmConfirm( (UINT8 *)bd_addr->address, FALSE);
@@ -1562,6 +1834,7 @@ bt_status_t btif_dm_cancel_bond(const bt_bdaddr_t *bd_addr)
/* Cancel bonding, in case it is in ACL connection setup state */
BTA_DmBondCancel ((UINT8 *)bd_addr->address);
btif_storage_remove_bonded_device((bt_bdaddr_t *)bd_addr);
+#endif
}
return BT_STATUS_SUCCESS;
@@ -1602,12 +1875,35 @@ bt_status_t btif_dm_pin_reply( const bt_bdaddr_t *bd_addr, uint8_t accept,
uint8_t pin_len, bt_pin_code_t *pin_code)
{
BTIF_TRACE_EVENT2("%s: accept=%d", __FUNCTION__, accept);
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+ if (pairing_cb.is_le_only)
+ {
+ int i;
+ UINT32 passkey = 0;
+ int multi[] = {100000, 10000, 1000, 100, 10,1};
+ BD_ADDR remote_bd_addr;
+ bdcpy(remote_bd_addr, bd_addr->address);
+ for (i = 0; i < 6; i++)
+ {
+ passkey += (multi[i] * (pin_code->pin[i] - '0'));
+ }
+ BTIF_TRACE_DEBUG1("btif_dm_pin_reply: passkey: %d", passkey);
+ BTA_DmBlePasskeyReply(remote_bd_addr, accept, passkey);
+ }
+ else
+ {
+ BTA_DmPinReply( (UINT8 *)bd_addr->address, accept, pin_len, pin_code->pin);
+ if (accept)
+ pairing_cb.pin_code_len = pin_len;
+ }
+#else
BTA_DmPinReply( (UINT8 *)bd_addr->address, accept, pin_len, pin_code->pin);
if (accept)
pairing_cb.pin_code_len = pin_len;
-
+#endif
return BT_STATUS_SUCCESS;
}
@@ -1635,8 +1931,20 @@ bt_status_t btif_dm_ssp_reply(const bt_bdaddr_t *bd_addr,
}
/* BT_SSP_VARIANT_CONSENT & BT_SSP_VARIANT_PASSKEY_CONFIRMATION supported */
BTIF_TRACE_EVENT2("%s: accept=%d", __FUNCTION__, accept);
- BTA_DmConfirm( (UINT8 *)bd_addr->address, accept);
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+ if (pairing_cb.is_le_only)
+ {
+ if (accept)
+ BTA_DmBleSecurityGrant((UINT8 *)bd_addr->address,BTA_DM_SEC_GRANTED);
+ else
+ BTA_DmBleSecurityGrant((UINT8 *)bd_addr->address,BTA_DM_SEC_PAIR_NOT_SPT);
+ }
+ else
+ BTA_DmConfirm( (UINT8 *)bd_addr->address, accept);
+#else
+ BTA_DmConfirm( (UINT8 *)bd_addr->address, accept);
+#endif
return BT_STATUS_SUCCESS;
}
@@ -1888,6 +2196,314 @@ BOOLEAN btif_dm_proc_rmt_oob(BD_ADDR bd_addr, BT_OCTET16 p_c, BT_OCTET16 p_r)
return result;
}
#endif /* BTIF_DM_OOB_TEST */
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_ssp_key_notif)
+{
+ bt_bdaddr_t bd_addr;
+ bt_bdname_t bd_name;
+ UINT32 cod;
+
+ BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
+
+ /* Remote name update */
+ btif_update_remote_properties(p_ssp_key_notif->bd_addr , p_ssp_key_notif->bd_name,
+ NULL, BT_DEVICE_TYPE_BLE);
+ bdcpy(bd_addr.address, p_ssp_key_notif->bd_addr);
+ memcpy(bd_name.name, p_ssp_key_notif->bd_name, BD_NAME_LEN);
+
+ bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+ pairing_cb.is_ssp = FALSE;
+ cod = COD_UNCLASSIFIED;
+
+ HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name,
+ cod, BT_SSP_VARIANT_PASSKEY_NOTIFICATION,
+ p_ssp_key_notif->passkey);
+}
+
+/*******************************************************************************
+**
+** Function btif_dm_ble_auth_cmpl_evt
+**
+** Description Executes authentication complete event in btif context
+**
+** Returns void
+**
+*******************************************************************************/
+static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
+{
+ /* Save link key, if not temporary */
+ bt_bdaddr_t bd_addr;
+ bt_status_t status = BT_STATUS_FAIL;
+ bt_bond_state_t state = BT_BOND_STATE_NONE;
+
+ bdcpy(bd_addr.address, p_auth_cmpl->bd_addr);
+ if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) )
+ {
+ /* store keys */
+ }
+ if (p_auth_cmpl->success)
+ {
+ status = BT_STATUS_SUCCESS;
+ state = BT_BOND_STATE_BONDED;
+
+ btif_dm_save_ble_bonding_keys();
+ BTA_GATTC_Refresh(bd_addr.address);
+ btif_dm_get_remote_services(&bd_addr);
+ }
+ else
+ {
+ /*Map the HCI fail reason to bt status */
+ switch (p_auth_cmpl->fail_reason)
+ {
+
+ btif_dm_remove_ble_bonding_keys();
+ default:
+ status = BT_STATUS_FAIL;
+ break;
+ }
+ }
+ bond_state_changed(status, &bd_addr, state);
+}
+
+
+
+void btif_dm_load_ble_local_keys(void)
+{
+ bt_status_t bt_status;
+
+ memset(&ble_local_key_cb, 0, sizeof(btif_dm_local_key_cb_t));
+
+ if (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_ER,(char*)&ble_local_key_cb.er[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS)
+ {
+ ble_local_key_cb.is_er_rcvd = TRUE;
+ BTIF_TRACE_DEBUG1("%s BLE ER key loaded",__FUNCTION__ );
+ }
+
+ if ((btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IR,(char*)&ble_local_key_cb.id_keys.ir[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS )&&
+ (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IRK, (char*)&ble_local_key_cb.id_keys.irk[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS)&&
+ (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_DHK,(char*)&ble_local_key_cb.id_keys.dhk[0],
+ BT_OCTET16_LEN)== BT_STATUS_SUCCESS))
+ {
+ ble_local_key_cb.is_id_keys_rcvd = TRUE;
+ BTIF_TRACE_DEBUG1("%s BLE ID keys loaded",__FUNCTION__ );
+ }
+
+}
+void btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+ tBTA_BLE_LOCAL_ID_KEYS *p_id_keys)
+{
+ if (ble_local_key_cb.is_er_rcvd )
+ {
+ memcpy(&er[0], &ble_local_key_cb.er[0], sizeof(BT_OCTET16));
+ *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ER;
+ }
+
+ if (ble_local_key_cb.is_id_keys_rcvd)
+ {
+ memcpy(&p_id_keys->ir[0], &ble_local_key_cb.id_keys.ir[0], sizeof(BT_OCTET16));
+ memcpy(&p_id_keys->irk[0], &ble_local_key_cb.id_keys.irk[0], sizeof(BT_OCTET16));
+ memcpy(&p_id_keys->dhk[0], &ble_local_key_cb.id_keys.dhk[0], sizeof(BT_OCTET16));
+ *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ID;
+ }
+ BTIF_TRACE_DEBUG2("%s *p_key_mask=0x%02x",__FUNCTION__, *p_key_mask);
+}
+
+void btif_dm_save_ble_bonding_keys(void)
+{
+
+ bt_bdaddr_t bd_addr;
+
+ BTIF_TRACE_DEBUG1("%s",__FUNCTION__ );
+
+ bdcpy(bd_addr.address, pairing_cb.bd_addr);
+
+ if (pairing_cb.ble.is_penc_key_rcvd)
+ {
+ btif_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.penc_key,
+ BTIF_DM_LE_KEY_PENC,
+ sizeof(btif_dm_ble_penc_keys_t));
+ }
+
+ if (pairing_cb.ble.is_pid_key_rcvd)
+ {
+ btif_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.pid_key[0],
+ BTIF_DM_LE_KEY_PID,
+ BT_OCTET16_LEN);
+ }
+
+
+ if (pairing_cb.ble.is_pcsrk_key_rcvd)
+ {
+ btif_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.pcsrk_key,
+ BTIF_DM_LE_KEY_PCSRK,
+ sizeof(btif_dm_ble_pcsrk_keys_t));
+ }
+
+
+ if (pairing_cb.ble.is_lenc_key_rcvd)
+ {
+ btif_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.lenc_key,
+ BTIF_DM_LE_KEY_LENC,
+ sizeof(btif_dm_ble_lenc_keys_t));
+ }
+
+ if (pairing_cb.ble.is_lcsrk_key_rcvd)
+ {
+ btif_storage_add_ble_bonding_key(&bd_addr,
+ (char *) &pairing_cb.ble.lcsrk_key,
+ BTIF_DM_LE_KEY_LCSRK,
+ sizeof(btif_dm_ble_lcsrk_keys_t));
+ }
+
+}
+
+
+void btif_dm_remove_ble_bonding_keys(void)
+{
+ bt_bdaddr_t bd_addr;
+
+ BTIF_TRACE_DEBUG1("%s",__FUNCTION__ );
+
+ bdcpy(bd_addr.address, pairing_cb.bd_addr);
+ btif_storage_remove_ble_bonding_keys(&bd_addr);
+}
+
+
+/*******************************************************************************
+**
+** Function btif_dm_ble_sec_req_evt
+**
+** Description Eprocess security request event in btif context
+**
+** Returns void
+**
+*******************************************************************************/
+void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ *p_ble_req)
+{
+ bt_bdaddr_t bd_addr;
+ bt_bdname_t bd_name;
+ UINT32 cod;
+ BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
+
+ if (pairing_cb.state == BT_BOND_STATE_BONDING)
+ {
+ BTIF_TRACE_DEBUG1("%s Discard security request", __FUNCTION__);
+ return;
+ }
+
+ /* Remote name update */
+ btif_update_remote_properties(p_ble_req->bd_addr,p_ble_req->bd_name,NULL,BT_DEVICE_TYPE_BLE);
+
+ bdcpy(bd_addr.address, p_ble_req->bd_addr);
+ memcpy(bd_name.name, p_ble_req->bd_name, BD_NAME_LEN);
+
+ bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+
+ pairing_cb.is_temp = FALSE;
+ pairing_cb.is_le_only = TRUE;
+ pairing_cb.is_ssp = TRUE;
+
+ cod = COD_UNCLASSIFIED;
+
+ HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name, cod,
+ BT_SSP_VARIANT_CONSENT, 0);
+}
+
+
+
+/*******************************************************************************
+**
+** Function btif_dm_ble_passkey_req_evt
+**
+** Description Executes pin request event in btif context
+**
+** Returns void
+**
+*******************************************************************************/
+static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req)
+{
+ bt_bdaddr_t bd_addr;
+ bt_bdname_t bd_name;
+ UINT32 cod;
+
+ /* Remote name update */
+ btif_update_remote_properties(p_pin_req->bd_addr,p_pin_req->bd_name,NULL,BT_DEVICE_TYPE_BLE);
+
+ bdcpy(bd_addr.address, p_pin_req->bd_addr);
+ memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN);
+
+ bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+ pairing_cb.is_le_only = TRUE;
+
+ cod = COD_UNCLASSIFIED;
+
+ HAL_CBACK(bt_hal_cbacks, pin_request_cb,
+ &bd_addr, &bd_name, cod);
+}
+
+
+void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name,
+ tBT_DEVICE_TYPE dev_type)
+{
+ btif_update_remote_properties(bd_addr,bd_name,NULL,dev_type);
+}
+
+static void btif_dm_ble_tx_test_cback(void *p)
+{
+ btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_TX_TEST,
+ (char *)p, 1, NULL);
+}
+
+static void btif_dm_ble_rx_test_cback(void *p)
+{
+ btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_RX_TEST,
+ (char *)p, 1, NULL);
+}
+
+static void btif_dm_ble_test_end_cback(void *p)
+{
+ btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_TEST_END,
+ (char *)p, 3, NULL);
+}
+/*******************************************************************************
+**
+** Function btif_le_test_mode
+**
+** Description Sends a HCI BLE Test command to the Controller
+**
+** Returns BT_STATUS_SUCCESS on success
+**
+*******************************************************************************/
+bt_status_t btif_le_test_mode(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+ switch (opcode) {
+ case HCI_BLE_TRANSMITTER_TEST:
+ if (len != 3) return BT_STATUS_PARM_INVALID;
+ BTM_BleTransmitterTest(buf[0],buf[1],buf[2], btif_dm_ble_tx_test_cback);
+ break;
+ case HCI_BLE_RECEIVER_TEST:
+ if (len != 1) return BT_STATUS_PARM_INVALID;
+ BTM_BleReceiverTest(buf[0], btif_dm_ble_rx_test_cback);
+ break;
+ case HCI_BLE_TEST_END:
+ BTM_BleTestEnd((tBTM_CMPL_CB*) btif_dm_ble_test_end_cback);
+ break;
+ default:
+ BTIF_TRACE_ERROR2("%s: Unknown LE Test Mode Command 0x%x", __FUNCTION__, opcode);
+ return BT_STATUS_UNSUPPORTED;
+ }
+ return BT_STATUS_SUCCESS;
+}
+
+#endif
void btif_dm_on_disable()
{
diff --git a/btif/src/btif_gatt.c b/btif/src/btif_gatt.c
new file mode 100644
index 000000000..bc01c2ec5
--- /dev/null
+++ b/btif/src/btif_gatt.c
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ *
+ * Filename: btif_gatt.c
+ *
+ * Description: GATT Profile Bluetooth Interface
+ *
+ *******************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+
+const btgatt_callbacks_t *bt_gatt_callbacks = NULL;
+
+extern btgatt_client_interface_t btgattClientInterface;
+extern btgatt_server_interface_t btgattServerInterface;
+
+/*******************************************************************************
+**
+** Function btif_gatt_init
+**
+** Description Initializes the GATT interface
+**
+** Returns s bt_status_t
+**
+*******************************************************************************/
+static bt_status_t btif_gatt_init( const btgatt_callbacks_t* callbacks )
+{
+ bt_gatt_callbacks = callbacks;
+
+ BTA_GATTC_Init();
+ BTA_GATTS_Init();
+
+ return BT_STATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function btif_gatt_cleanup
+**
+** Description Closes the GATT interface
+**
+** Returns void
+**
+*******************************************************************************/
+static void btif_gatt_cleanup( void )
+{
+ if (bt_gatt_callbacks)
+ bt_gatt_callbacks = NULL;
+}
+
+static const btgatt_interface_t btgattInterface = {
+ sizeof(btgattInterface),
+
+ btif_gatt_init,
+ btif_gatt_cleanup,
+
+ &btgattClientInterface,
+ &btgattServerInterface,
+};
+
+/*******************************************************************************
+**
+** Function btif_gatt_get_interface
+**
+** Description Get the gatt callback interface
+**
+** Returns btgatt_interface_t
+**
+*******************************************************************************/
+const btgatt_interface_t *btif_gatt_get_interface()
+{
+ return &btgattInterface;
+}
+
+#endif
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
new file mode 100644
index 000000000..ac3df5278
--- /dev/null
+++ b/btif/src/btif_gatt_client.c
@@ -0,0 +1,998 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ *
+ * Filename: btif_gatt_client.c
+ *
+ * Description: GATT client implementation
+ *
+ *******************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+#include "btif_config.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+#include "btif_dm.h"
+#include "btif_storage.h"
+
+/*******************************************************************************
+** Constants & Macros
+********************************************************************************/
+
+#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
+ {\
+ ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
+ return BT_STATUS_NOT_READY;\
+ } else {\
+ ALOGD("%s", __FUNCTION__);\
+ }
+
+
+typedef enum {
+ BTIF_GATTC_REGISTER_APP = 1000,
+ BTIF_GATTC_UNREGISTER_APP,
+ BTIF_GATTC_SCAN_START,
+ BTIF_GATTC_SCAN_STOP,
+ BTIF_GATTC_OPEN,
+ BTIF_GATTC_CLOSE,
+ BTIF_GATTC_SEARCH_SERVICE,
+ BTIF_GATTC_GET_FIRST_CHAR,
+ BTIF_GATTC_GET_NEXT_CHAR,
+ BTIF_GATTC_GET_FIRST_CHAR_DESCR,
+ BTIF_GATTC_GET_NEXT_CHAR_DESCR,
+ BTIF_GATTC_GET_FIRST_INCL_SERVICE,
+ BTIF_GATTC_GET_NEXT_INCL_SERVICE,
+ BTIF_GATTC_READ_CHAR,
+ BTIF_GATTC_READ_CHAR_DESCR,
+ BTIF_GATTC_WRITE_CHAR,
+ BTIF_GATTC_WRITE_CHAR_DESCR,
+ BTIF_GATTC_EXECUTE_WRITE,
+ BTIF_GATTC_REG_FOR_NOTIFICATION,
+ BTIF_GATTC_DEREG_FOR_NOTIFICATION,
+ BTIF_GATTC_REFRESH,
+ BTIF_GATTC_READ_RSSI
+} btif_gattc_event_t;
+
+#define BTIF_GATT_MAX_OBSERVED_DEV 40
+
+#define BTIF_GATT_OBSERVE_EVT 0x1000
+#define BTIF_GATTC_RSSI_EVT 0x1001
+
+/*******************************************************************************
+** Local type definitions
+********************************************************************************/
+
+typedef struct
+{
+ uint8_t value[BTGATT_MAX_ATTR_LEN];
+ bt_bdaddr_t bd_addr;
+ btgatt_srvc_id_t srvc_id;
+ btgatt_srvc_id_t incl_srvc_id;
+ btgatt_char_id_t char_id;
+ bt_uuid_t uuid;
+ uint16_t conn_id;
+ uint16_t len;
+ uint8_t client_if;
+ uint8_t action;
+ uint8_t is_direct;
+ uint8_t search_all;
+ uint8_t auth_req;
+ uint8_t write_type;
+ uint8_t status;
+ uint8_t addr_type;
+ int8_t rssi;
+ tBT_DEVICE_TYPE device_type;
+} __attribute__((packed)) btif_gattc_cb_t;
+
+typedef struct
+{
+ bt_bdaddr_t bd_addr;
+ BOOLEAN in_use;
+}__attribute__((packed)) btif_gattc_dev_t;
+
+typedef struct
+{
+ btif_gattc_dev_t remote_dev[BTIF_GATT_MAX_OBSERVED_DEV];
+ uint8_t addr_type;
+ uint8_t next_storage_idx;
+}__attribute__((packed)) btif_gattc_dev_cb_t;
+
+/*******************************************************************************
+** Static variables
+********************************************************************************/
+
+extern const btgatt_callbacks_t *bt_gatt_callbacks;
+static btif_gattc_dev_cb_t btif_gattc_dev_cb;
+static btif_gattc_dev_cb_t *p_dev_cb = &btif_gattc_dev_cb;
+static uint8_t rssi_request_client_if;
+
+/*******************************************************************************
+** Static functions
+********************************************************************************/
+
+static void btif_gattc_init_dev_cb(void)
+{
+ memset(p_dev_cb, 0, sizeof(btif_gattc_dev_cb_t));
+}
+
+static void btif_gattc_add_remote_bdaddr (BD_ADDR p_bda, uint8_t addr_type)
+{
+ BOOLEAN found=FALSE;
+ uint8_t i;
+ for (i = 0; i < BTIF_GATT_MAX_OBSERVED_DEV; i++)
+ {
+ if (!p_dev_cb->remote_dev[i].in_use )
+ {
+ memcpy(p_dev_cb->remote_dev[i].bd_addr.address, p_bda, BD_ADDR_LEN);
+ p_dev_cb->addr_type = addr_type;
+ p_dev_cb->remote_dev[i].in_use = TRUE;
+ ALOGD("%s device added idx=%d", __FUNCTION__, i );
+ break;
+ }
+ }
+
+ if ( i == BTIF_GATT_MAX_OBSERVED_DEV)
+ {
+ i= p_dev_cb->next_storage_idx;
+ memcpy(p_dev_cb->remote_dev[i].bd_addr.address, p_bda, BD_ADDR_LEN);
+ p_dev_cb->addr_type = addr_type;
+ p_dev_cb->remote_dev[i].in_use = TRUE;
+ ALOGD("%s device overwrite idx=%d", __FUNCTION__, i );
+ p_dev_cb->next_storage_idx++;
+ if(p_dev_cb->next_storage_idx >= BTIF_GATT_MAX_OBSERVED_DEV)
+ p_dev_cb->next_storage_idx = 0;
+ }
+}
+
+static BOOLEAN btif_gattc_find_bdaddr (BD_ADDR p_bda)
+{
+ uint8_t i;
+ for (i = 0; i < BTIF_GATT_MAX_OBSERVED_DEV; i++)
+ {
+ if (p_dev_cb->remote_dev[i].in_use &&
+ !memcmp(p_dev_cb->remote_dev[i].bd_addr.address, p_bda, BD_ADDR_LEN))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void btif_gattc_update_properties ( btif_gattc_cb_t *p_btif_cb )
+{
+ uint8_t remote_name_len;
+ uint8_t *p_eir_remote_name=NULL;
+ bt_bdname_t bdname;
+
+ p_eir_remote_name = BTA_CheckEirData(p_btif_cb->value,
+ BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
+
+ if(p_eir_remote_name == NULL)
+ {
+ p_eir_remote_name = BTA_CheckEirData(p_btif_cb->value,
+ BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len);
+ }
+
+ if(p_eir_remote_name)
+ {
+ memcpy(bdname.name, p_eir_remote_name, remote_name_len);
+ bdname.name[remote_name_len]='\0';
+
+ ALOGD("%s BLE device name=%s len=%d dev_type=%d", __FUNCTION__, bdname.name,
+ remote_name_len, p_btif_cb->device_type );
+ btif_dm_update_ble_remote_properties( p_btif_cb->bd_addr.address, bdname.name,
+ p_btif_cb->device_type);
+ }
+
+ btif_storage_set_remote_addr_type( &p_btif_cb->bd_addr, p_btif_cb->addr_type);
+}
+
+static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
+{
+ ALOGD("%s: Event %d", __FUNCTION__, event);
+
+ tBTA_GATTC *p_data = (tBTA_GATTC*)p_param;
+ switch (event)
+ {
+ case BTA_GATTC_REG_EVT:
+ {
+ bt_uuid_t app_uuid;
+ bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid);
+ HAL_CBACK(bt_gatt_callbacks, client->register_client_cb
+ , p_data->reg_oper.status
+ , p_data->reg_oper.client_if
+ , &app_uuid
+ );
+ break;
+ }
+
+ case BTA_GATTC_DEREG_EVT:
+ break;
+
+ case BTA_GATTC_READ_CHAR_EVT:
+ {
+ btgatt_read_params_t data;
+ set_read_value(&data, &p_data->read);
+
+ HAL_CBACK(bt_gatt_callbacks, client->read_characteristic_cb
+ , p_data->read.conn_id, p_data->read.status, &data);
+ break;
+ }
+
+ case BTA_GATTC_WRITE_CHAR_EVT:
+ case BTA_GATTC_PREP_WRITE_EVT:
+ {
+ btgatt_write_params_t data;
+ bta_to_btif_srvc_id(&data.srvc_id, &p_data->write.srvc_id);
+ bta_to_btif_char_id(&data.char_id, &p_data->write.char_id);
+
+ HAL_CBACK(bt_gatt_callbacks, client->write_characteristic_cb
+ , p_data->write.conn_id, p_data->write.status, &data
+ );
+ break;
+ }
+
+ case BTA_GATTC_EXEC_EVT:
+ {
+ HAL_CBACK(bt_gatt_callbacks, client->execute_write_cb
+ , p_data->exec_cmpl.conn_id, p_data->exec_cmpl.status
+ );
+ break;
+ }
+
+ case BTA_GATTC_SEARCH_CMPL_EVT:
+ {
+ HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb
+ , p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
+ break;
+ }
+
+ case BTA_GATTC_SEARCH_RES_EVT:
+ {
+ btgatt_srvc_id_t data;
+ bta_to_btif_srvc_id(&data, &(p_data->srvc_res.service_uuid));
+ HAL_CBACK(bt_gatt_callbacks, client->search_result_cb
+ , p_data->srvc_res.conn_id, &data);
+ break;
+ }
+
+ case BTA_GATTC_READ_DESCR_EVT:
+ {
+ btgatt_read_params_t data;
+ set_read_value(&data, &p_data->read);
+
+ HAL_CBACK(bt_gatt_callbacks, client->read_descriptor_cb
+ , p_data->read.conn_id, p_data->read.status, &data);
+ break;
+ }
+
+ case BTA_GATTC_WRITE_DESCR_EVT:
+ {
+ btgatt_write_params_t data;
+ bta_to_btif_srvc_id(&data.srvc_id, &p_data->write.srvc_id);
+ bta_to_btif_char_id(&data.char_id, &p_data->write.char_id);
+ bta_to_btif_uuid(&data.descr_id, &p_data->write.descr_type);
+
+ HAL_CBACK(bt_gatt_callbacks, client->write_descriptor_cb
+ , p_data->write.conn_id, p_data->write.status, &data);
+ break;
+ }
+
+ case BTA_GATTC_NOTIF_EVT:
+ {
+ btgatt_notify_params_t data;
+
+ bdcpy(data.bda.address, p_data->notify.bda);
+
+ bta_to_btif_srvc_id(&data.srvc_id, &p_data->notify.char_id.srvc_id);
+ bta_to_btif_char_id(&data.char_id, &p_data->notify.char_id.char_id);
+ memcpy(data.value, p_data->notify.value, p_data->notify.len);
+
+ data.is_notify = p_data->notify.is_notify;
+ data.len = p_data->notify.len;
+
+ HAL_CBACK(bt_gatt_callbacks, client->notify_cb
+ , p_data->notify.conn_id, &data);
+
+ if (p_data->notify.is_notify == FALSE)
+ {
+ BTA_GATTC_SendIndConfirm(p_data->notify.conn_id,
+ &p_data->notify.char_id);
+ }
+ break;
+ }
+
+ case BTA_GATTC_OPEN_EVT:
+ {
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, p_data->open.remote_bda);
+
+ if (p_data->open.status == BTA_GATT_OK)
+ btif_gatt_check_encrypted_link(p_data->open.remote_bda);
+
+ HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id
+ , p_data->open.status, p_data->open.client_if, &bda);
+ break;
+ }
+
+ case BTA_GATTC_CLOSE_EVT:
+ {
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, p_data->close.remote_bda);
+ HAL_CBACK(bt_gatt_callbacks, client->close_cb, p_data->close.conn_id
+ , p_data->status, p_data->close.client_if, &bda);
+
+ if(p_data->status == BTA_GATT_OK)
+ btif_gatt_remove_encrypted_link(p_data->close.remote_bda);
+ break;
+ }
+
+ case BTA_GATTC_ACL_EVT:
+ ALOGD("BTA_GATTC_ACL_EVT: status = %d", p_data->status);
+ /* Ignore for now */
+ break;
+
+ case BTA_GATTC_CANCEL_OPEN_EVT:
+ break;
+
+ case BTIF_GATT_OBSERVE_EVT:
+ {
+ btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+ if (!btif_gattc_find_bdaddr(p_btif_cb->bd_addr.address))
+ {
+ btif_gattc_add_remote_bdaddr(p_btif_cb->bd_addr.address, p_btif_cb->addr_type);
+ btif_gattc_update_properties(p_btif_cb);
+ }
+ HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb,
+ &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value);
+ break;
+ }
+
+ case BTIF_GATTC_RSSI_EVT:
+ {
+ btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+ HAL_CBACK(bt_gatt_callbacks, client->read_remote_rssi_cb, p_btif_cb->client_if,
+ &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->status);
+ break;
+ }
+
+ default:
+ ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
+ break;
+ }
+}
+
+static void bte_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
+{
+ bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt,
+ (uint16_t) event, (void*)p_data, sizeof(tBTA_GATTC), NULL);
+ ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
+}
+
+static void bte_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
+{
+ btif_gattc_cb_t btif_cb;
+ uint8_t len;
+
+ switch (event)
+ {
+ case BTA_DM_INQ_RES_EVT:
+ {
+ bdcpy(btif_cb.bd_addr.address, p_data->inq_res.bd_addr);
+ btif_cb.device_type = p_data->inq_res.device_type;
+ btif_cb.rssi = p_data->inq_res.rssi;
+ btif_cb.addr_type = p_data->inq_res.ble_addr_type;
+ if (p_data->inq_res.p_eir)
+ {
+ memcpy(btif_cb.value, p_data->inq_res.p_eir, 62);
+ if (BTA_CheckEirData(p_data->inq_res.p_eir, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE,
+ &len))
+ {
+ p_data->inq_res.remt_name_not_required = TRUE;
+ }
+ }
+ }
+ break;
+
+ case BTA_DM_INQ_CMPL_EVT:
+ {
+ BTIF_TRACE_DEBUG2("%s BLE observe complete. Num Resp %d",
+ __FUNCTION__,p_data->inq_cmpl.num_resps);
+ return;
+ }
+
+ default:
+ BTIF_TRACE_WARNING2("%s : Unknown event 0x%x", __FUNCTION__, event);
+ return;
+ }
+ btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATT_OBSERVE_EVT,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static void btm_read_rssi_cb (tBTM_RSSI_RESULTS *p_result)
+{
+ btif_gattc_cb_t btif_cb;
+
+ bdcpy(btif_cb.bd_addr.address, p_result->rem_bda);
+ btif_cb.rssi = p_result->rssi;
+ btif_cb.status = p_result->status;
+ btif_cb.client_if = rssi_request_client_if;
+ btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATTC_RSSI_EVT,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+
+static void btgattc_handle_event(uint16_t event, char* p_param)
+{
+ tBTA_GATT_STATUS status;
+ tBT_UUID uuid;
+ tBTA_GATT_SRVC_ID srvc_id;
+ tGATT_CHAR_PROP out_char_prop;
+ tBTA_GATTC_CHAR_ID in_char_id;
+ tBTA_GATTC_CHAR_ID out_char_id;
+ tBTA_GATTC_CHAR_DESCR_ID in_char_descr_id;
+ tBTA_GATTC_CHAR_DESCR_ID out_char_descr_id;
+ tBTA_GATTC_INCL_SVC_ID in_incl_svc_id;
+ tBTA_GATTC_INCL_SVC_ID out_incl_svc_id;
+ tBTA_GATT_UNFMT descr_val;
+
+ btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
+ if (!p_cb) return;
+
+ ALOGD("%s: Event %d", __FUNCTION__, event);
+
+ switch (event)
+ {
+ case BTIF_GATTC_REGISTER_APP:
+ btif_to_bta_uuid(&uuid, &p_cb->uuid);
+ BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);
+ break;
+
+ case BTIF_GATTC_UNREGISTER_APP:
+ BTA_GATTC_AppDeregister(p_cb->client_if);
+ break;
+
+ case BTIF_GATTC_SCAN_START:
+ btif_gattc_init_dev_cb();
+ BTA_DmBleObserve(TRUE, 0, bte_scan_results_cb);
+ break;
+
+ case BTIF_GATTC_SCAN_STOP:
+ BTA_DmBleObserve(FALSE, 0, 0);
+ break;
+
+ case BTIF_GATTC_OPEN:
+ if (!p_cb->is_direct)
+ BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
+
+ BTA_GATTC_Open(p_cb->client_if, p_cb->bd_addr.address, p_cb->is_direct);
+ break;
+
+ case BTIF_GATTC_CLOSE:
+ // Disconnect establiched connections
+ if (p_cb->conn_id != 0)
+ BTA_GATTC_Close(p_cb->conn_id);
+ else
+ BTA_GATTC_CancelOpen(p_cb->client_if, p_cb->bd_addr.address, TRUE);
+
+ // Cancel pending background connections (remove from whitelist)
+ BTA_GATTC_CancelOpen(p_cb->client_if, p_cb->bd_addr.address, FALSE);
+ break;
+
+ case BTIF_GATTC_SEARCH_SERVICE:
+ {
+ if (p_cb->search_all)
+ {
+ BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, NULL);
+ } else {
+ btif_to_bta_uuid(&uuid, &p_cb->uuid);
+ BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &uuid);
+ }
+ break;
+ }
+
+ case BTIF_GATTC_GET_FIRST_CHAR:
+ {
+ btgatt_char_id_t char_id;
+ btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
+ status = BTA_GATTC_GetFirstChar(p_cb->conn_id, &srvc_id, NULL,
+ &out_char_id, &out_char_prop);
+
+ if (status == 0)
+ bta_to_btif_char_id(&char_id, &out_char_id.char_id);
+
+ HAL_CBACK(bt_gatt_callbacks, client->get_characteristic_cb,
+ p_cb->conn_id, status, &p_cb->srvc_id,
+ &char_id, out_char_prop);
+ break;
+ }
+
+ case BTIF_GATTC_GET_NEXT_CHAR:
+ {
+ btgatt_char_id_t char_id;
+ btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+ status = BTA_GATTC_GetNextChar(p_cb->conn_id, &in_char_id, NULL,
+ &out_char_id, &out_char_prop);
+
+ if (status == 0)
+ bta_to_btif_char_id(&char_id, &out_char_id.char_id);
+
+ HAL_CBACK(bt_gatt_callbacks, client->get_characteristic_cb,
+ p_cb->conn_id, status, &p_cb->srvc_id,
+ &char_id, out_char_prop);
+ break;
+ }
+
+ case BTIF_GATTC_GET_FIRST_CHAR_DESCR:
+ {
+ bt_uuid_t descr_id;
+ btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+ status = BTA_GATTC_GetFirstCharDescr(p_cb->conn_id, &in_char_id, NULL,
+ &out_char_descr_id);
+
+ if (status == 0)
+ bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_type);
+
+ HAL_CBACK(bt_gatt_callbacks, client->get_descriptor_cb,
+ p_cb->conn_id, status, &p_cb->srvc_id,
+ &p_cb->char_id, &descr_id);
+ break;
+ }
+
+ case BTIF_GATTC_GET_NEXT_CHAR_DESCR:
+ {
+ bt_uuid_t descr_id;
+ btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
+ btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+
+ status = BTA_GATTC_GetNextCharDescr(p_cb->conn_id, &in_char_descr_id
+ , NULL, &out_char_descr_id);
+
+ if (status == 0)
+ bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_type);
+
+ HAL_CBACK(bt_gatt_callbacks, client->get_descriptor_cb,
+ p_cb->conn_id, status, &p_cb->srvc_id,
+ &p_cb->char_id, &descr_id);
+ break;
+ }
+
+ case BTIF_GATTC_GET_FIRST_INCL_SERVICE:
+ {
+ btgatt_srvc_id_t incl_srvc_id;
+ btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
+
+ status = BTA_GATTC_GetFirstIncludedService(p_cb->conn_id,
+ &srvc_id, NULL, &out_incl_svc_id);
+
+ bta_to_btif_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
+
+ HAL_CBACK(bt_gatt_callbacks, client->get_included_service_cb,
+ p_cb->conn_id, status, &p_cb->srvc_id,
+ &incl_srvc_id);
+ break;
+ }
+
+ case BTIF_GATTC_GET_NEXT_INCL_SERVICE:
+ {
+ btgatt_srvc_id_t incl_srvc_id;
+ btif_to_bta_srvc_id(&in_incl_svc_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_srvc_id(&in_incl_svc_id.incl_svc_id, &p_cb->incl_srvc_id);
+
+ status = BTA_GATTC_GetNextIncludedService(p_cb->conn_id,
+ &in_incl_svc_id, NULL, &out_incl_svc_id);
+
+ bta_to_btif_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
+
+ HAL_CBACK(bt_gatt_callbacks, client->get_included_service_cb,
+ p_cb->conn_id, status, &p_cb->srvc_id,
+ &incl_srvc_id);
+ break;
+ }
+
+ case BTIF_GATTC_READ_CHAR:
+ btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+ BTA_GATTC_ReadCharacteristic(p_cb->conn_id, &in_char_id, p_cb->auth_req);
+ break;
+
+ case BTIF_GATTC_READ_CHAR_DESCR:
+ btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
+ btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+
+ BTA_GATTC_ReadCharDescr(p_cb->conn_id, &in_char_descr_id, p_cb->auth_req);
+ break;
+
+ case BTIF_GATTC_WRITE_CHAR:
+ btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+ BTA_GATTC_WriteCharValue(p_cb->conn_id, &in_char_id,
+ p_cb->write_type,
+ p_cb->len,
+ p_cb->value,
+ p_cb->auth_req);
+ break;
+
+ case BTIF_GATTC_WRITE_CHAR_DESCR:
+ btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
+ btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+
+ descr_val.len = p_cb->len;
+ descr_val.p_value = p_cb->value;
+
+ BTA_GATTC_WriteCharDescr(p_cb->conn_id, &in_char_descr_id,
+ p_cb->write_type, &descr_val,
+ p_cb->auth_req);
+ break;
+
+ case BTIF_GATTC_EXECUTE_WRITE:
+ BTA_GATTC_ExecuteWrite(p_cb->conn_id, p_cb->action);
+ break;
+
+ case BTIF_GATTC_REG_FOR_NOTIFICATION:
+ btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+ status = BTA_GATTC_RegisterForNotifications(p_cb->client_if,
+ p_cb->bd_addr.address, &in_char_id);
+
+ HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
+ p_cb->conn_id, 1, status, &p_cb->srvc_id,
+ &p_cb->char_id);
+ break;
+
+ case BTIF_GATTC_DEREG_FOR_NOTIFICATION:
+ btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+ btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+ status = BTA_GATTC_DeregisterForNotifications(p_cb->client_if,
+ p_cb->bd_addr.address, &in_char_id);
+
+ HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
+ p_cb->conn_id, 0, status, &p_cb->srvc_id,
+ &p_cb->char_id);
+ break;
+
+ case BTIF_GATTC_REFRESH:
+ BTA_GATTC_Refresh(p_cb->bd_addr.address);
+ break;
+
+ case BTIF_GATTC_READ_RSSI:
+ rssi_request_client_if = p_cb->client_if;
+ BTM_ReadRSSI (p_cb->bd_addr.address, (tBTM_CMPL_CB *)btm_read_rssi_cb);
+ break;
+
+ default:
+ ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
+ break;
+ }
+}
+
+/*******************************************************************************
+** Client API Functions
+********************************************************************************/
+
+static bt_status_t btif_gattc_register_app(bt_uuid_t *uuid)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REGISTER_APP,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_unregister_app(int client_if )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_UNREGISTER_APP,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_scan( int client_if, bool start )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ return btif_transfer_context(btgattc_handle_event, start ? BTIF_GATTC_SCAN_START : BTIF_GATTC_SCAN_STOP,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_open(int client_if, const bt_bdaddr_t *bd_addr, bool is_direct )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ btif_cb.is_direct = is_direct ? 1 : 0;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_OPEN,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_close( int client_if, const bt_bdaddr_t *bd_addr, int conn_id)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_CLOSE,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_refresh( int client_if, const bt_bdaddr_t *bd_addr )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REFRESH,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_search_service(int conn_id, bt_uuid_t *filter_uuid )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.search_all = filter_uuid ? 0 : 1;
+ if (filter_uuid)
+ memcpy(&btif_cb.uuid, filter_uuid, sizeof(bt_uuid_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SEARCH_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_get_characteristic( int conn_id
+ , btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *start_char_id)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ if (start_char_id)
+ {
+ memcpy(&btif_cb.char_id, start_char_id, sizeof(btgatt_char_id_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_NEXT_CHAR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+ }
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_FIRST_CHAR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_get_descriptor( int conn_id
+ , btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id
+ , bt_uuid_t *start_descr_id)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+ if (start_descr_id)
+ {
+ memcpy(&btif_cb.uuid, start_descr_id, sizeof(bt_uuid_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_NEXT_CHAR_DESCR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+ }
+
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_FIRST_CHAR_DESCR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
+ btgatt_srvc_id_t *start_incl_srvc_id)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ if (start_incl_srvc_id)
+ {
+ memcpy(&btif_cb.incl_srvc_id, start_incl_srvc_id, sizeof(btgatt_srvc_id_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_NEXT_INCL_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+ }
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_FIRST_INCL_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_read_char(int conn_id, btgatt_srvc_id_t* srvc_id,
+ btgatt_char_id_t* char_id, int auth_req )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.auth_req = (uint8_t) auth_req;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_READ_CHAR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_read_char_descr(int conn_id, btgatt_srvc_id_t* srvc_id,
+ btgatt_char_id_t* char_id, bt_uuid_t* descr_id,
+ int auth_req )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.auth_req = (uint8_t) auth_req;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+ memcpy(&btif_cb.uuid, descr_id, sizeof(bt_uuid_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_READ_CHAR_DESCR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_write_char(int conn_id, btgatt_srvc_id_t* srvc_id,
+ btgatt_char_id_t* char_id, int write_type,
+ int len, int auth_req, char* p_value)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.auth_req = (uint8_t) auth_req;
+ btif_cb.write_type = (uint8_t) write_type;
+ btif_cb.len = len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+ memcpy(btif_cb.value, p_value, btif_cb.len);
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_WRITE_CHAR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_write_char_descr(int conn_id, btgatt_srvc_id_t* srvc_id,
+ btgatt_char_id_t* char_id, bt_uuid_t* descr_id,
+ int write_type, int len, int auth_req,
+ char* p_value)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.auth_req = (uint8_t) auth_req;
+ btif_cb.write_type = (uint8_t) write_type;
+ btif_cb.len = len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+ memcpy(&btif_cb.uuid, descr_id, sizeof(bt_uuid_t));
+ memcpy(btif_cb.value, p_value, btif_cb.len);
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_WRITE_CHAR_DESCR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_execute_write(int conn_id, int execute)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.action = (uint8_t) execute;
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_EXECUTE_WRITE,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_reg_for_notification(int client_if, const bt_bdaddr_t *bd_addr,
+ btgatt_srvc_id_t* srvc_id,
+ btgatt_char_id_t* char_id)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REG_FOR_NOTIFICATION,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_dereg_for_notification(int client_if, const bt_bdaddr_t *bd_addr,
+ btgatt_srvc_id_t* srvc_id,
+ btgatt_char_id_t* char_id)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_DEREG_FOR_NOTIFICATION,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.client_if = (uint8_t) client_if;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_READ_RSSI,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static int btif_gattc_get_device_type( const bt_bdaddr_t *bd_addr )
+{
+ int device_type = 0;
+ char bd_addr_str[18] = {0};
+
+ bd2str(bd_addr, &bd_addr_str);
+ if (btif_config_get_int("Remote", bd_addr_str, "DevType", &device_type))
+ return device_type;
+ return 0;
+}
+
+extern bt_status_t btif_gattc_test_command_impl(int command, btgatt_test_params_t* params);
+
+static bt_status_t btif_gattc_test_command(int command, btgatt_test_params_t* params)
+{
+ return btif_gattc_test_command_impl(command, params);
+}
+
+
+const btgatt_client_interface_t btgattClientInterface = {
+ btif_gattc_register_app,
+ btif_gattc_unregister_app,
+ btif_gattc_scan,
+ btif_gattc_open,
+ btif_gattc_close,
+ btif_gattc_refresh,
+ btif_gattc_search_service,
+ btif_gattc_get_included_service,
+ btif_gattc_get_characteristic,
+ btif_gattc_get_descriptor,
+ btif_gattc_read_char,
+ btif_gattc_write_char,
+ btif_gattc_read_char_descr,
+ btif_gattc_write_char_descr,
+ btif_gattc_execute_write,
+ btif_gattc_reg_for_notification,
+ btif_gattc_dereg_for_notification,
+ btif_gattc_read_remote_rssi,
+ btif_gattc_get_device_type,
+ btif_gattc_test_command
+};
+
+#endif
diff --git a/btif/src/btif_gatt_server.c b/btif/src/btif_gatt_server.c
new file mode 100644
index 000000000..9de36f95f
--- /dev/null
+++ b/btif/src/btif_gatt_server.c
@@ -0,0 +1,579 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/************************************************************************************
+ *
+ * Filename: btif_gatt_server.c
+ *
+ * Description: GATT server implementation
+ *
+ ***********************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_dm.h"
+#include "btif_storage.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+
+/************************************************************************************
+** Constants & Macros
+************************************************************************************/
+
+#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
+ {\
+ ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
+ return BT_STATUS_NOT_READY;\
+ } else {\
+ ALOGD("%s", __FUNCTION__);\
+ }
+
+
+typedef enum {
+ BTIF_GATTS_REGISTER_APP = 2000,
+ BTIF_GATTS_UNREGISTER_APP,
+ BTIF_GATTS_OPEN,
+ BTIF_GATTS_CLOSE,
+ BTIF_GATTS_CREATE_SERVICE,
+ BTIF_GATTS_ADD_INCLUDED_SERVICE,
+ BTIF_GATTS_ADD_CHARACTERISTIC,
+ BTIF_GATTS_ADD_DESCRIPTOR,
+ BTIF_GATTS_START_SERVICE,
+ BTIF_GATTS_STOP_SERVICE,
+ BTIF_GATTS_DELETE_SERVICE,
+ BTIF_GATTS_SEND_INDICATION,
+ BTIF_GATTS_SEND_RESPONSE
+} btif_gatts_event_t;
+
+/************************************************************************************
+** Local type definitions
+************************************************************************************/
+
+typedef struct
+{
+ uint8_t value[BTGATT_MAX_ATTR_LEN];
+ btgatt_response_t response;
+ btgatt_srvc_id_t srvc_id;
+ bt_bdaddr_t bd_addr;
+ bt_uuid_t uuid;
+ uint32_t trans_id;
+ uint16_t conn_id;
+ uint16_t srvc_handle;
+ uint16_t incl_handle;
+ uint16_t attr_handle;
+ uint16_t permissions;
+ uint16_t len;
+ uint8_t server_if;
+ uint8_t is_direct;
+ uint8_t num_handles;
+ uint8_t properties;
+ uint8_t transport;
+ uint8_t confirm;
+ uint8_t status;
+} __attribute__((packed)) btif_gatts_cb_t;
+
+
+/************************************************************************************
+** Static variables
+************************************************************************************/
+
+extern const btgatt_callbacks_t *bt_gatt_callbacks;
+
+
+/************************************************************************************
+** Static functions
+************************************************************************************/
+
+static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
+{
+ ALOGD("%s: Event %d", __FUNCTION__, event);
+
+ tBTA_GATTS *p_data = (tBTA_GATTS*)p_param;
+ switch (event)
+ {
+ case BTA_GATTS_REG_EVT:
+ {
+ bt_uuid_t app_uuid;
+ bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
+ HAL_CBACK(bt_gatt_callbacks, server->register_server_cb
+ , p_data->reg_oper.status
+ , p_data->reg_oper.server_if
+ , &app_uuid
+ );
+ break;
+ }
+
+ case BTA_GATTS_DEREG_EVT:
+ break;
+
+ case BTA_GATTS_CONNECT_EVT:
+ {
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, p_data->conn.remote_bda);
+
+ btif_gatt_check_encrypted_link(p_data->conn.remote_bda);
+
+ HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
+ p_data->conn.conn_id, TRUE, &bda);
+ break;
+ }
+
+ case BTA_GATTS_DISCONNECT_EVT:
+ {
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, p_data->conn.remote_bda);
+
+ HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
+ p_data->conn.conn_id, FALSE, &bda);
+
+ btif_gatt_remove_encrypted_link(p_data->conn.remote_bda);
+ break;
+ }
+
+ case BTA_GATTS_CREATE_EVT:
+ {
+ btgatt_srvc_id_t srvc_id;
+ srvc_id.is_primary = p_data->create.is_primary;
+ srvc_id.id.inst_id = p_data->create.svc_instance;
+ bta_to_btif_uuid(&srvc_id.id.uuid, &p_data->create.uuid);
+
+ HAL_CBACK(bt_gatt_callbacks, server->service_added_cb,
+ p_data->create.status, p_data->create.server_if, &srvc_id,
+ p_data->create.service_id
+ );
+ }
+ break;
+
+ case BTA_GATTS_ADD_INCL_SRVC_EVT:
+ HAL_CBACK(bt_gatt_callbacks, server->included_service_added_cb,
+ p_data->add_result.status,
+ p_data->add_result.server_if,
+ p_data->add_result.service_id,
+ p_data->add_result.attr_id);
+ break;
+
+ case BTA_GATTS_ADD_CHAR_EVT:
+ {
+ bt_uuid_t uuid;
+ bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
+
+ HAL_CBACK(bt_gatt_callbacks, server->characteristic_added_cb,
+ p_data->add_result.status,
+ p_data->add_result.server_if,
+ &uuid,
+ p_data->add_result.service_id,
+ p_data->add_result.attr_id);
+ break;
+ }
+
+ case BTA_GATTS_ADD_CHAR_DESCR_EVT:
+ {
+ bt_uuid_t uuid;
+ bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
+
+ HAL_CBACK(bt_gatt_callbacks, server->descriptor_added_cb,
+ p_data->add_result.status,
+ p_data->add_result.server_if,
+ &uuid,
+ p_data->add_result.service_id,
+ p_data->add_result.attr_id);
+ break;
+ }
+
+ case BTA_GATTS_START_EVT:
+ HAL_CBACK(bt_gatt_callbacks, server->service_started_cb,
+ p_data->srvc_oper.status,
+ p_data->srvc_oper.server_if,
+ p_data->srvc_oper.service_id);
+ break;
+
+ case BTA_GATTS_STOP_EVT:
+ HAL_CBACK(bt_gatt_callbacks, server->service_stopped_cb,
+ p_data->srvc_oper.status,
+ p_data->srvc_oper.server_if,
+ p_data->srvc_oper.service_id);
+ break;
+
+ case BTA_GATTS_DELELTE_EVT:
+ HAL_CBACK(bt_gatt_callbacks, server->service_deleted_cb,
+ p_data->srvc_oper.status,
+ p_data->srvc_oper.server_if,
+ p_data->srvc_oper.service_id);
+ break;
+
+ case BTA_GATTS_READ_EVT:
+ {
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, p_data->req_data.remote_bda);
+
+ HAL_CBACK(bt_gatt_callbacks, server->request_read_cb,
+ p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+ p_data->req_data.p_data->read_req.handle,
+ p_data->req_data.p_data->read_req.offset,
+ p_data->req_data.p_data->read_req.is_long);
+ break;
+ }
+
+ case BTA_GATTS_WRITE_EVT:
+ {
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, p_data->req_data.remote_bda);
+
+ HAL_CBACK(bt_gatt_callbacks, server->request_write_cb,
+ p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+ p_data->req_data.p_data->write_req.handle,
+ p_data->req_data.p_data->write_req.offset,
+ p_data->req_data.p_data->write_req.len,
+ p_data->req_data.p_data->write_req.need_rsp,
+ p_data->req_data.p_data->write_req.is_prep,
+ p_data->req_data.p_data->write_req.value);
+ break;
+ }
+
+ case BTA_GATTS_EXEC_WRITE_EVT:
+ {
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, p_data->req_data.remote_bda);
+
+ HAL_CBACK(bt_gatt_callbacks, server->request_exec_write_cb,
+ p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+ p_data->req_data.p_data->exec_write);
+ break;
+ }
+
+ case BTA_GATTS_MTU_EVT:
+ case BTA_GATTS_OPEN_EVT:
+ case BTA_GATTS_CANCEL_OPEN_EVT:
+ case BTA_GATTS_CLOSE_EVT:
+ ALOGD("%s: Empty event (%d)!", __FUNCTION__, event);
+ break;
+
+ default:
+ ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
+ break;
+ }
+}
+
+static void btapp_gatts_cback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
+{
+ bt_status_t status;
+ status = btif_transfer_context(btapp_gatts_handle_cback, (uint16_t) event,
+ (void*)p_data, sizeof(tBTA_GATTS), NULL);
+ ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
+}
+
+static void btgatts_handle_event(uint16_t event, char* p_param)
+{
+ btif_gatts_cb_t* p_cb = (btif_gatts_cb_t*)p_param;
+ if (!p_cb) return;
+
+ ALOGD("%s: Event %d", __FUNCTION__, event);
+
+ switch (event)
+ {
+ case BTIF_GATTS_REGISTER_APP:
+ {
+ tBT_UUID uuid;
+ btif_to_bta_uuid(&uuid, &p_cb->uuid);
+ BTA_GATTS_AppRegister(&uuid, btapp_gatts_cback);
+ break;
+ }
+
+ case BTIF_GATTS_UNREGISTER_APP:
+ BTA_GATTS_AppDeregister(p_cb->server_if);
+ break;
+
+ case BTIF_GATTS_OPEN:
+ if (!p_cb->is_direct)
+ BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
+ BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
+ p_cb->is_direct);
+ break;
+
+ case BTIF_GATTS_CLOSE:
+ // Cancel pending foreground/background connections
+ BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
+ BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
+
+ // Close active connection
+ if (p_cb->conn_id != 0)
+ BTA_GATTS_Close(p_cb->conn_id);
+ break;
+
+ case BTIF_GATTS_CREATE_SERVICE:
+ {
+ tBTA_GATT_SRVC_ID srvc_id;
+ btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
+ BTA_GATTS_CreateService(p_cb->server_if, &srvc_id.id.uuid,
+ srvc_id.id.inst_id, p_cb->num_handles,
+ srvc_id.is_primary);
+ break;
+ }
+
+ case BTIF_GATTS_ADD_INCLUDED_SERVICE:
+ BTA_GATTS_AddIncludeService(p_cb->srvc_handle, p_cb->incl_handle);
+ break;
+
+ case BTIF_GATTS_ADD_CHARACTERISTIC:
+ {
+ tBT_UUID uuid;
+ btif_to_bta_uuid(&uuid, &p_cb->uuid);
+
+ BTA_GATTS_AddCharacteristic(p_cb->srvc_handle, &uuid,
+ p_cb->permissions, p_cb->properties);
+ break;
+ }
+
+ case BTIF_GATTS_ADD_DESCRIPTOR:
+ {
+ tBT_UUID uuid;
+ btif_to_bta_uuid(&uuid, &p_cb->uuid);
+
+ BTA_GATTS_AddCharDescriptor(p_cb->srvc_handle, p_cb->permissions,
+ &uuid);
+ break;
+ }
+
+ case BTIF_GATTS_START_SERVICE:
+ BTA_GATTS_StartService(p_cb->srvc_handle, p_cb->transport);
+ break;
+
+ case BTIF_GATTS_STOP_SERVICE:
+ BTA_GATTS_StopService(p_cb->srvc_handle);
+ break;
+
+ case BTIF_GATTS_DELETE_SERVICE:
+ BTA_GATTS_DeleteService(p_cb->srvc_handle);
+ break;
+
+ case BTIF_GATTS_SEND_INDICATION:
+ BTA_GATTS_HandleValueIndication(p_cb->conn_id, p_cb->attr_handle,
+ p_cb->len, p_cb->value, p_cb->confirm);
+ // TODO: Might need to send an ACK if handle value indication is
+ // invoked without need for confirmation.
+ break;
+
+ case BTIF_GATTS_SEND_RESPONSE:
+ {
+ tBTA_GATTS_RSP rsp_struct;
+ btgatt_response_t *p_rsp = &p_cb->response;
+ btif_to_bta_response(&rsp_struct, p_rsp);
+
+ BTA_GATTS_SendRsp(p_cb->conn_id, p_cb->trans_id,
+ p_cb->status, &rsp_struct);
+
+ HAL_CBACK(bt_gatt_callbacks, server->response_confirmation_cb,
+ 0, rsp_struct.attr_value.handle);
+ break;
+ }
+
+ default:
+ ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
+ break;
+ }
+}
+
+/************************************************************************************
+** Server API Functions
+************************************************************************************/
+
+static bt_status_t btif_gatts_register_app(bt_uuid_t *uuid)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_REGISTER_APP,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_unregister_app( int server_if )
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_UNREGISTER_APP,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_open( int server_if, const bt_bdaddr_t *bd_addr, bool is_direct )
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.is_direct = is_direct ? 1 : 0;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_OPEN,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CLOSE,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
+ int num_handles)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.num_handles = (uint8_t) num_handles;
+ memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CREATE_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_included_service(int server_if, int service_handle,
+ int included_handle)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.srvc_handle = (uint16_t) service_handle;
+ btif_cb.incl_handle = (uint16_t) included_handle;
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_INCLUDED_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_characteristic(int server_if, int service_handle,
+ bt_uuid_t *uuid, int properties,
+ int permissions)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.srvc_handle = (uint16_t) service_handle;
+ btif_cb.properties = (uint8_t) properties;
+ btif_cb.permissions = (uint16_t) permissions;
+ memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_CHARACTERISTIC,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_descriptor(int server_if, int service_handle, bt_uuid_t *uuid,
+ int permissions)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.srvc_handle = (uint16_t) service_handle;
+ btif_cb.permissions = (uint16_t) permissions;
+ memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_DESCRIPTOR,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_start_service(int server_if, int service_handle, int transport)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.srvc_handle = (uint16_t) service_handle;
+ btif_cb.transport = (uint8_t) transport;
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_START_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_stop_service(int server_if, int service_handle)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.srvc_handle = (uint16_t) service_handle;
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_STOP_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_delete_service(int server_if, int service_handle)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.srvc_handle = (uint16_t) service_handle;
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_DELETE_SERVICE,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_send_indication(int server_if, int attribute_handle, int conn_id,
+ int len, int confirm, char* p_value)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.server_if = (uint8_t) server_if;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.attr_handle = attribute_handle;
+ btif_cb.confirm = confirm;
+ btif_cb.len = len;
+ memcpy(btif_cb.value, p_value, len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len);
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_INDICATION,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_send_response(int conn_id, int trans_id,
+ int status, btgatt_response_t *response)
+{
+ CHECK_BTGATT_INIT();
+ btif_gatts_cb_t btif_cb;
+ btif_cb.conn_id = (uint16_t) conn_id;
+ btif_cb.trans_id = (uint32_t) trans_id;
+ btif_cb.status = (uint8_t) status;
+ memcpy(&btif_cb.response, response, sizeof(btgatt_response_t));
+ return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_RESPONSE,
+ (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+const btgatt_server_interface_t btgattServerInterface = {
+ btif_gatts_register_app,
+ btif_gatts_unregister_app,
+ btif_gatts_open,
+ btif_gatts_close,
+ btif_gatts_add_service,
+ btif_gatts_add_included_service,
+ btif_gatts_add_characteristic,
+ btif_gatts_add_descriptor,
+ btif_gatts_start_service,
+ btif_gatts_stop_service,
+ btif_gatts_delete_service,
+ btif_gatts_send_indication,
+ btif_gatts_send_response
+};
+
+#endif
diff --git a/btif/src/btif_gatt_test.c b/btif/src/btif_gatt_test.c
new file mode 100644
index 000000000..8c23d56ca
--- /dev/null
+++ b/btif/src/btif_gatt_test.c
@@ -0,0 +1,293 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif_test"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+#include "bte_appl.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+#include "btif_dm.h"
+
+#include "gatt_api.h"
+
+/*******************************************************************************
+ * Typedefs & Macros
+ *******************************************************************************/
+
+typedef struct
+{
+ tGATT_IF gatt_if;
+ UINT16 conn_id;
+} btif_test_cb_t;
+
+/*******************************************************************************
+ * Static variables
+ *******************************************************************************/
+
+static const char * disc_name[GATT_DISC_MAX] =
+{
+ "Unknown",
+ "GATT_DISC_SRVC_ALL",
+ "GATT_DISC_SRVC_BY_UUID",
+ "GATT_DISC_INC_SRVC",
+ "GATT_DISC_CHAR",
+ "GATT_DISC_CHAR_DSCPT"
+};
+
+static btif_test_cb_t test_cb;
+
+/*******************************************************************************
+ * Callback functions
+ *******************************************************************************/
+
+static char * format_uuid(tBT_UUID bt_uuid, char *str_buf)
+{
+ int x = 0;
+
+ if (bt_uuid.len == LEN_UUID_16)
+ {
+ sprintf(str_buf, "0x%04x", bt_uuid.uu.uuid16);
+ }
+ else if (bt_uuid.len == LEN_UUID_128)
+ {
+ x += sprintf(&str_buf[x], "%02x%02x%02x%02x-%02x%02x-%02x%02x",
+ bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
+ bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
+ bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
+ bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
+ sprintf(&str_buf[x], "%02x%02x-%02x%02x%02x%02x%02x%02x",
+ bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
+ bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
+ bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
+ bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
+ }
+ else
+ sprintf(str_buf, "Unknown (len=%d)", bt_uuid.len);
+
+ return str_buf;
+}
+
+static void btif_test_connect_cback(tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+ ALOGD("%s: conn_id=%d, connected=%d", __FUNCTION__, conn_id, connected);
+ test_cb.conn_id = connected ? conn_id : 0;
+}
+
+static void btif_test_command_complete_cback(UINT16 conn_id, tGATTC_OPTYPE op,
+ tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+{
+ ALOGD ("%s: op_code=0x%02x, conn_id=0x%x. status=0x%x",
+ __FUNCTION__, op, conn_id, status);
+
+ switch (op)
+ {
+ case GATTC_OPTYPE_READ:
+ case GATTC_OPTYPE_WRITE:
+ case GATTC_OPTYPE_CONFIG:
+ case GATTC_OPTYPE_EXE_WRITE:
+ case GATTC_OPTYPE_NOTIFICATION:
+ break;
+
+ case GATTC_OPTYPE_INDICATION:
+ GATTC_SendHandleValueConfirm(conn_id, p_data->handle);
+ break;
+
+ default:
+ ALOGD ("%s: Unknown op_code (0x%02x)", __FUNCTION__, op);
+ break;
+ }
+}
+
+
+static void btif_test_discovery_result_cback(UINT16 conn_id, tGATT_DISC_TYPE disc_type,
+ tGATT_DISC_RES *p_data)
+{
+ char str_buf[50];
+
+ ALOGD("------ GATT Discovery result %-22s -------", disc_name[disc_type]);
+ ALOGD(" Attribute handle: 0x%04x (%d)", p_data->handle, p_data->handle);
+
+ if (disc_type != GATT_DISC_CHAR_DSCPT) {
+ ALOGD(" Attribute type: %s", format_uuid(p_data->type, str_buf));
+ }
+
+ switch (disc_type)
+ {
+ case GATT_DISC_SRVC_ALL:
+ ALOGD(" Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
+ p_data->handle, p_data->value.group_value.e_handle,
+ p_data->handle, p_data->value.group_value.e_handle);
+ ALOGD(" Service UUID: %s",
+ format_uuid(p_data->value.group_value.service_type, str_buf));
+ break;
+
+ case GATT_DISC_SRVC_BY_UUID:
+ ALOGD(" Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
+ p_data->handle, p_data->value.handle,
+ p_data->handle, p_data->value.handle);
+ break;
+
+ case GATT_DISC_INC_SRVC:
+ ALOGD(" Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
+ p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle,
+ p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle);
+ ALOGD(" Service UUID: %s",
+ format_uuid(p_data->value.incl_service.service_type, str_buf));
+ break;
+
+ case GATT_DISC_CHAR:
+ ALOGD(" Properties: 0x%02x",
+ p_data->value.dclr_value.char_prop);
+ ALOGD(" Characteristic UUID: %s",
+ format_uuid(p_data->value.dclr_value.char_uuid, str_buf));
+ break;
+
+ case GATT_DISC_CHAR_DSCPT:
+ ALOGD(" Descriptor UUID: %s", format_uuid(p_data->type, str_buf));
+ break;
+ }
+
+ ALOGD("-----------------------------------------------------------");
+}
+
+static void btif_test_discovery_complete_cback(UINT16 conn_id,
+ tGATT_DISC_TYPE disc_type,
+ tGATT_STATUS status)
+{
+ ALOGD("%s: status=%d", __FUNCTION__, status);
+}
+
+static tGATT_CBACK btif_test_callbacks =
+{
+ btif_test_connect_cback ,
+ btif_test_command_complete_cback,
+ btif_test_discovery_result_cback,
+ btif_test_discovery_complete_cback,
+ NULL
+};
+
+/*******************************************************************************
+ * Implementation
+ *******************************************************************************/
+
+bt_status_t btif_gattc_test_command_impl(uint16_t command, btgatt_test_params_t* params)
+{
+ switch(command) {
+ case 0x01: /* Enable */
+ {
+ ALOGD("%s: ENABLE - enable=%d", __FUNCTION__, params->u1);
+ if (params->u1)
+ {
+ tBT_UUID app_uuid = {LEN_UUID_128,{0xAE}};
+ test_cb.gatt_if = GATT_Register(&app_uuid, &btif_test_callbacks);
+ GATT_StartIf(test_cb.gatt_if);
+ } else {
+ GATT_Deregister(test_cb.gatt_if);
+ test_cb.gatt_if = 0;
+ }
+ break;
+ }
+
+ case 0x02: /* Connect */
+ {
+ ALOGD("%s: CONNECT - device=%02x:%02x:%02x:%02x:%02x:%02x (dev_type=%d)",
+ __FUNCTION__,
+ params->bda1->address[0], params->bda1->address[1],
+ params->bda1->address[2], params->bda1->address[3],
+ params->bda1->address[4], params->bda1->address[5],
+ params->u1);
+
+ if (params->u1 == BT_DEVICE_TYPE_BLE)
+ BTM_SecAddBleDevice(params->bda1->address, NULL, BT_DEVICE_TYPE_BLE, 0);
+
+ if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, TRUE) )
+ {
+ ALOGE("%s: GATT_Connect failed!", __FUNCTION__);
+ }
+ break;
+ }
+
+ case 0x03: /* Disconnect */
+ {
+ ALOGD("%s: DISCONNECT - conn_id=%d", __FUNCTION__, test_cb.conn_id);
+ GATT_Disconnect(test_cb.conn_id);
+ break;
+ }
+
+ case 0x04: /* Discover */
+ {
+ char buf[50] = {0};
+ tGATT_DISC_PARAM param;
+ memset(&param, 0, sizeof(tGATT_DISC_PARAM));
+
+ if (params->u1 >= GATT_DISC_MAX)
+ {
+ ALOGE("%s: DISCOVER - Invalid type (%d)!", __FUNCTION__, params->u1);
+ return 0;
+ }
+
+ param.s_handle = params->u2;
+ param.e_handle = params->u3;
+ btif_to_bta_uuid(&param.service, params->uuid1);
+
+ ALOGD("%s: DISCOVER (%s), conn_id=%d, uuid=%s, handles=0x%04x-0x%04x",
+ __FUNCTION__, disc_name[params->u1], test_cb.conn_id,
+ format_uuid(param.service, buf), params->u2, params->u3);
+ GATTC_Discover(test_cb.conn_id, params->u1, &param);
+ break;
+ }
+
+ case 0xF0: /* Pairing configuration */
+ ALOGD("%s: Setting pairing config auth=%d, iocaps=%d, keys=%d/%d/%d",
+ __FUNCTION__, params->u1, params->u2, params->u3, params->u4,
+ params->u5);
+
+ bte_appl_cfg.ble_auth_req = params->u1;
+ bte_appl_cfg.ble_io_cap = params->u2;
+ bte_appl_cfg.ble_init_key = params->u3;
+ bte_appl_cfg.ble_resp_key = params->u4;
+ bte_appl_cfg.ble_max_key_size = params->u5;
+ break;
+
+ default:
+ ALOGE("%s: UNKNOWN TEST COMMAND 0x%02x", __FUNCTION__, command);
+ break;
+ }
+ return 0;
+}
+
+#endif
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
new file mode 100644
index 000000000..a3cbc3d8b
--- /dev/null
+++ b/btif/src/btif_gatt_util.c
@@ -0,0 +1,351 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+
+#include "btif_common.h"
+#include "btif_dm.h"
+#include "btif_util.h"
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+
+#define GATTC_READ_VALUE_TYPE_VALUE 0x0000 /* Attribute value itself */
+#define GATTC_READ_VALUE_TYPE_AGG_FORMAT 0x2905 /* Characteristic Aggregate Format*/
+
+#define BTIF_GATT_MAX_ENC_LINK_RECORDS 10
+
+typedef struct
+{
+ BD_ADDR bd_addr;
+ BOOLEAN in_use;
+}__attribute__((packed)) btif_gatt_encrypted_link_t;
+
+static char BASE_UUID[16] = {
+ 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static btif_gatt_encrypted_link_t encrypted_links[BTIF_GATT_MAX_ENC_LINK_RECORDS];
+
+int uuidType(unsigned char* p_uuid)
+{
+ int i = 0;
+ int match = 0;
+ int all_zero = 1;
+
+ for(i = 0; i != 16; ++i)
+ {
+ if (i == 12 || i == 13)
+ continue;
+
+ if (p_uuid[i] == BASE_UUID[i])
+ ++match;
+
+ if (p_uuid[i] != 0)
+ all_zero = 0;
+ }
+ if (all_zero)
+ return 0;
+ if (match == 12)
+ return LEN_UUID_32;
+ if (match == 14)
+ return LEN_UUID_16;
+ return LEN_UUID_128;
+}
+
+/*******************************************************************************
+ * BTIF -> BTA conversion functions
+ *******************************************************************************/
+
+void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src)
+{
+ char *p_byte = (char*)p_src;
+ int i = 0;
+
+ p_dest->len = uuidType(p_src->uu);
+
+ switch (p_dest->len)
+ {
+ case LEN_UUID_16:
+ p_dest->uu.uuid16 = (p_src->uu[13] << 8) + p_src->uu[12];
+ break;
+
+ case LEN_UUID_32:
+ p_dest->uu.uuid32 = (p_src->uu[13] << 8) + p_src->uu[12];
+ p_dest->uu.uuid32 += (p_src->uu[15] << 24) + (p_src->uu[14] << 16);
+ break;
+
+ case LEN_UUID_128:
+ for(i = 0; i != 16; ++i)
+ p_dest->uu.uuid128[i] = p_byte[i];
+ break;
+
+ default:
+ ALOGE("%s: Unknown UUID length %d!", __FUNCTION__, p_dest->len);
+ break;
+ }
+}
+
+void btif_to_bta_char_id(tBTA_GATT_ID *p_dest, btgatt_char_id_t *p_src)
+{
+ p_dest->inst_id = p_src->inst_id;
+ btif_to_bta_uuid(&p_dest->uuid, &p_src->uuid);
+}
+
+void btif_to_bta_srvc_id(tBTA_GATT_SRVC_ID *p_dest, btgatt_srvc_id_t *p_src)
+{
+ p_dest->id.inst_id = p_src->id.inst_id;
+ btif_to_bta_uuid(&p_dest->id.uuid, &p_src->id.uuid);
+ p_dest->is_primary = p_src->is_primary;
+}
+
+void btif_to_bta_response(tBTA_GATTS_RSP *p_dest, btgatt_response_t* p_src)
+{
+ p_dest->attr_value.auth_req = p_src->attr_value.auth_req;
+ p_dest->attr_value.handle = p_src->attr_value.handle;
+ p_dest->attr_value.len = p_src->attr_value.len;
+ p_dest->attr_value.offset = p_src->attr_value.offset;
+ memcpy(p_dest->attr_value.value, p_src->attr_value.value, GATT_MAX_ATTR_LEN);
+}
+
+/*******************************************************************************
+ * BTA -> BTIF conversion functions
+ *******************************************************************************/
+
+void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
+{
+ int i = 0;
+
+ if (p_src->len == LEN_UUID_16 || p_src->len == LEN_UUID_32)
+ {
+ for(i=0; i != 16; ++i)
+ p_dest->uu[i] = BASE_UUID[i];
+ }
+
+ switch (p_src->len)
+ {
+ case 0:
+ break;
+
+ case LEN_UUID_16:
+ p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
+ p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
+ break;
+
+ case LEN_UUID_32:
+ p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
+ p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
+ p_dest->uu[14] = (p_src->uu.uuid32 >> 16) & 0xff;
+ p_dest->uu[15] = (p_src->uu.uuid32 >> 24) & 0xff;
+ break;
+
+ case LEN_UUID_128:
+ for(i=0; i != 16; ++i)
+ p_dest->uu[i] = p_src->uu.uuid128[i];
+ break;
+
+ default:
+ ALOGE("%s: Unknown UUID length %d!", __FUNCTION__, p_src->len);
+ break;
+ }
+}
+
+
+void bta_to_btif_char_id(btgatt_char_id_t *p_dest, tBTA_GATT_ID *p_src)
+{
+ p_dest->inst_id = p_src->inst_id;
+ bta_to_btif_uuid(&p_dest->uuid, &p_src->uuid);
+}
+
+void bta_to_btif_srvc_id(btgatt_srvc_id_t *p_dest, tBTA_GATT_SRVC_ID *p_src)
+{
+ p_dest->id.inst_id = p_src->id.inst_id;
+ bta_to_btif_uuid(&p_dest->id.uuid, &p_src->id.uuid);
+ p_dest->is_primary = p_src->is_primary;
+}
+
+
+/*******************************************************************************
+ * Utility functions
+ *******************************************************************************/
+
+uint16_t get_uuid16(tBT_UUID *p_uuid)
+{
+ if (p_uuid->len == LEN_UUID_16)
+ {
+ return p_uuid->uu.uuid16;
+ }
+ else if (p_uuid->len == LEN_UUID_128)
+ {
+ UINT16 u16;
+ UINT8 *p = &p_uuid->uu.uuid128[LEN_UUID_128 - 4];
+ STREAM_TO_UINT16(u16, p);
+ return u16;
+ }
+ else /* p_uuid->len == LEN_UUID_32 */
+ {
+ return(UINT16) p_uuid->uu.uuid32;
+ }
+}
+
+uint16_t set_read_value(btgatt_read_params_t *p_dest, tBTA_GATTC_READ *p_src)
+{
+ int i = 0;
+ uint16_t descr_type = 0;
+ uint16_t len = 0;
+
+ p_dest->status = p_src->status;
+ bta_to_btif_srvc_id(&p_dest->srvc_id, &p_src->srvc_id);
+ bta_to_btif_char_id(&p_dest->char_id, &p_src->char_id);
+ bta_to_btif_uuid(&p_dest->descr_id, &p_src->descr_type);
+
+ descr_type = get_uuid16(&p_src->descr_type);
+
+ switch (descr_type)
+ {
+ case GATT_UUID_CHAR_AGG_FORMAT:
+ /* not supported */
+ p_dest->value_type = GATTC_READ_VALUE_TYPE_AGG_FORMAT;
+ break;
+
+ default:
+ if ( p_src->status == BTA_GATT_OK )
+ {
+ ALOGI("%s unformat.len = %d ", __FUNCTION__, p_src->p_value->unformat.len);
+ p_dest->value.len = p_src->p_value->unformat.len;
+ if ( p_src->p_value->unformat.len > 0 && p_src->p_value->unformat.p_value != NULL )
+ {
+ memcpy(p_dest->value.value, p_src->p_value->unformat.p_value,
+ p_src->p_value->unformat.len);
+ }
+ len += p_src->p_value->unformat.len;
+ }
+ else
+ {
+ p_dest->value.len = 0;
+ }
+
+ p_dest->value_type = GATTC_READ_VALUE_TYPE_VALUE;
+ break;
+ }
+
+ return len;
+}
+
+/*******************************************************************************
+ * Encrypted link map handling
+ *******************************************************************************/
+
+static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_STATUS result);
+
+static BOOLEAN btif_gatt_is_link_encrypted (BD_ADDR bd_addr)
+{
+ btif_gatt_encrypted_link_t *p_link = &encrypted_links[0];
+ int i;
+
+ if (bd_addr == NULL)
+ return FALSE;
+
+ for (i = 0; i != BTIF_GATT_MAX_ENC_LINK_RECORDS; ++i, ++p_link)
+ {
+ if (p_link->in_use && (!memcmp(p_link->bd_addr, bd_addr, BD_ADDR_LEN)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOLEAN btif_gatt_add_encrypted_link (BD_ADDR bd_addr)
+{
+ btif_gatt_encrypted_link_t *p_link = &encrypted_links[0];
+ int i;
+
+ if (bd_addr == NULL)
+ return FALSE;
+
+ if (btif_gatt_is_link_encrypted(bd_addr))
+ return TRUE;
+
+ for (i = 0; i != BTIF_GATT_MAX_ENC_LINK_RECORDS; ++i, ++p_link)
+ {
+ if (!p_link->in_use)
+ {
+ p_link->in_use = TRUE;
+ memcpy( p_link->bd_addr, bd_addr, sizeof(BD_ADDR) );
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void btif_gatt_remove_encrypted_link (BD_ADDR bd_addr)
+{
+ btif_gatt_encrypted_link_t *p_link = &encrypted_links[0];
+ int i;
+
+ if (bd_addr == NULL)
+ return;
+
+ for (i = 0; i != BTIF_GATT_MAX_ENC_LINK_RECORDS; ++i, ++p_link)
+ {
+ if (p_link->in_use && (!memcmp (p_link->bd_addr, bd_addr, BD_ADDR_LEN)))
+ {
+ p_link->in_use = FALSE;
+ break;
+ }
+ }
+}
+
+static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_STATUS result)
+{
+ if (result == BTA_SUCCESS)
+ {
+ btif_gatt_add_encrypted_link(bd_addr);
+ } else {
+ btif_gatt_remove_encrypted_link(bd_addr);
+ }
+}
+
+void btif_gatt_check_encrypted_link (BD_ADDR bd_addr)
+{
+ char buf[100];
+
+ bt_bdaddr_t bda;
+ bdcpy(bda.address, bd_addr);
+
+ if ((btif_storage_get_ble_bonding_key(&bda, BTIF_DM_LE_KEY_PENC,
+ buf, sizeof(btif_dm_ble_penc_keys_t)) == BT_STATUS_SUCCESS)
+ && !btif_gatt_is_link_encrypted(bd_addr))
+ {
+ BTA_DmSetEncryption(bd_addr,
+ &btif_gatt_set_encryption_cb, BTM_BLE_SEC_ENCRYPT);
+ }
+} \ No newline at end of file
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
index 7ce22b101..7688e68b6 100755..100644
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -1137,7 +1137,7 @@ static void cleanup( void )
}
static const bthf_interface_t bthfInterface = {
- sizeof(bt_interface_t),
+ sizeof(bthfInterface),
init,
connect,
disconnect,
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index e937a710e..61dd89487 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -266,6 +266,7 @@ static void update_keyboard_lockstates(btif_hh_device_t *p_dev)
if (p_dev->p_buf != NULL) {
p_dev->p_buf->len = len;
p_dev->p_buf->offset = BTA_HH_MIN_OFFSET;
+ p_dev->p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
/* LED status updated by data event */
UINT8 *pbuf_data = (UINT8 *)(p_dev->p_buf + 1)
@@ -1571,6 +1572,7 @@ static bt_status_t send_data (bt_bdaddr_t *bd_addr, char* data)
UINT8* pbuf_data;
pbuf_data = (UINT8*) (p_dev->p_buf + 1) + p_dev->p_buf->offset;
memcpy(pbuf_data, hexbuf, hex_bytes_filled);
+ p_dev->p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
BTA_HhSendData(p_dev->dev_handle, *bda, p_dev->p_buf);
return BT_STATUS_SUCCESS;
}
@@ -1619,7 +1621,7 @@ static void cleanup( void )
}
static const bthh_interface_t bthhInterface = {
- sizeof(bt_interface_t),
+ sizeof(bthhInterface),
init,
connect,
disconnect,
@@ -1649,7 +1651,7 @@ bt_status_t btif_hh_execute_service(BOOLEAN b_enable)
if (b_enable)
{
/* Enable and register with BTA-HH */
- BTA_HhEnable(BTA_SEC_NONE, FALSE, bte_hh_evt);
+ BTA_HhEnable(BTA_SEC_NONE, bte_hh_evt);
}
else {
/* Disable HH */
diff --git a/btif/src/btif_hl.c b/btif/src/btif_hl.c
index e6c3fb7f8..e22ca8aff 100644
--- a/btif/src/btif_hl.c
+++ b/btif/src/btif_hl.c
@@ -4542,7 +4542,7 @@ static void cleanup( void ){
}
static const bthl_interface_t bthlInterface = {
- sizeof(bthl_interface_t),
+ sizeof(bthlInterface),
init,
register_application,
unregister_application,
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index 2190b1cd4..055387410 100755..100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -59,6 +59,10 @@
#define BTIF_STORAGE_PATH_REMOTE_DEVCLASS "DevClass"
#define BTIF_STORAGE_PATH_REMOTE_DEVTYPE "DevType"
#define BTIF_STORAGE_PATH_REMOTE_NAME "Name"
+#define BTIF_STORAGE_PATH_REMOTE_VER_MFCT "Manufacturer"
+#define BTIF_STORAGE_PATH_REMOTE_VER_VER "LmpVer"
+#define BTIF_STORAGE_PATH_REMOTE_VER_SUBVER "LmpSubVer"
+
//#define BTIF_STORAGE_PATH_REMOTE_LINKKEYS "remote_linkkeys"
#define BTIF_STORAGE_PATH_REMOTE_ALIASE "Aliase"
#define BTIF_STORAGE_PATH_REMOTE_SERVICE "Service"
@@ -155,17 +159,30 @@ typedef struct
} btif_bonded_devices_t;
/************************************************************************************
-** Extern variables
+** External variables
************************************************************************************/
extern UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID];
extern bt_bdaddr_t btif_local_bd_addr;
+
+/************************************************************************************
+** External functions
+************************************************************************************/
+
+extern void btif_gatts_add_bonded_dev_from_nv(BD_ADDR bda);
+
/************************************************************************************
-** Static variables
+** Internal Functions
************************************************************************************/
+bt_status_t btif_in_fetch_bonded_ble_device(char *remote_bd_addr,int add,
+ btif_bonded_devices_t *p_bonded_devices);
+bt_status_t btif_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+ int *addr_type);
+
/************************************************************************************
** Static functions
************************************************************************************/
+
/*******************************************************************************
**
** Function btif_in_make_filename
@@ -292,6 +309,22 @@ static int prop2cfg(bt_bdaddr_t *remote_bd_addr, bt_property_t *prop)
btif_config_save();
break;
}
+ case BT_PROPERTY_REMOTE_VERSION_INFO:
+ {
+ bt_remote_version_t *info = (bt_remote_version_t *)prop->val;
+
+ if (!info)
+ return FALSE;
+
+ btif_config_set_int("Remote", bdstr,
+ BTIF_STORAGE_PATH_REMOTE_VER_MFCT, info->manufacturer);
+ btif_config_set_int("Remote", bdstr,
+ BTIF_STORAGE_PATH_REMOTE_VER_VER, info->version);
+ btif_config_set_int("Remote", bdstr,
+ BTIF_STORAGE_PATH_REMOTE_VER_SUBVER, info->sub_ver);
+ btif_config_save();
+ } break;
+
default:
BTIF_TRACE_ERROR1("Unknow prop type:%d", prop->type);
return FALSE;
@@ -381,8 +414,32 @@ static int cfg2prop(bt_bdaddr_t *remote_bd_addr, bt_property_t *prop)
prop->len = num_uuids * sizeof(bt_uuid_t);
ret = TRUE;
}
- break;
- }
+ else
+ {
+ prop->val = NULL;
+ prop->len = 0;
+ }
+ } break;
+
+ case BT_PROPERTY_REMOTE_VERSION_INFO:
+ {
+ bt_remote_version_t *info = (bt_remote_version_t *)prop->val;
+
+ if(prop->len >= (int)sizeof(bt_remote_version_t))
+ {
+ ret = btif_config_get_int("Remote", bdstr,
+ BTIF_STORAGE_PATH_REMOTE_VER_MFCT, &info->manufacturer);
+
+ if (ret == TRUE)
+ ret = btif_config_get_int("Remote", bdstr,
+ BTIF_STORAGE_PATH_REMOTE_VER_VER, &info->version);
+
+ if (ret == TRUE)
+ ret = btif_config_get_int("Remote", bdstr,
+ BTIF_STORAGE_PATH_REMOTE_VER_SUBVER, &info->sub_ver);
+ }
+ } break;
+
default:
BTIF_TRACE_ERROR1("Unknow prop type:%d", prop->type);
return FALSE;
@@ -412,6 +469,9 @@ static bt_status_t btif_in_fetch_bonded_devices(btif_bonded_devices_t *p_bonded_
kname_size = sizeof(kname);
kname[0] = 0;
kpos = 0;
+ BOOLEAN bt_linkkey_file_found=FALSE;
+ int device_type;
+
do
{
kpos = btif_config_next_key(kpos, "Remote", kname, &kname_size);
@@ -435,15 +495,38 @@ static bt_status_t btif_in_fetch_bonded_devices(btif_bonded_devices_t *p_bonded_
if(btif_config_get_int("Remote", kname, "DevClass", &cod))
uint2devclass((UINT32)cod, dev_class);
BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0, (UINT8)linkkey_type, 0);
+
+ if (btif_config_get_int("Remote", kname, "DevType", &device_type) &&
+ (device_type == BT_DEVICE_TYPE_DUMO) )
+ {
+ btif_gatts_add_bonded_dev_from_nv(bd_addr.address);
+ }
}
+ bt_linkkey_file_found = TRUE;
memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++], &bd_addr, sizeof(bt_bdaddr_t));
}
- else BTIF_TRACE_ERROR1("bounded device:%s, LinkKeyType or PinLength is invalid", kname);
+ else
+ {
+#if (BLE_INCLUDED == TRUE)
+ bt_linkkey_file_found = FALSE;
+#else
+ BTIF_TRACE_ERROR1("bounded device:%s, LinkKeyType or PinLength is invalid", kname);
+#endif
+ }
}
- else BTIF_TRACE_DEBUG1("Remote device:%s, no link key", kname);
+#if (BLE_INCLUDED == TRUE)
+ if(!(btif_in_fetch_bonded_ble_device(kname,add, p_bonded_devices)) && (!bt_linkkey_file_found))
+ {
+ BTIF_TRACE_DEBUG1("Remote device:%s, no link key or ble key found", kname);
+ }
+#else
+ if(!bt_linkkey_file_found)
+ BTIF_TRACE_DEBUG1("Remote device:%s, no link key", kname);
+#endif
kname_size = sizeof(kname);
kname[0] = 0;
} while(kpos != -1);
+ BTIF_TRACE_DEBUG0("out");
return BT_STATUS_SUCCESS;
}
@@ -640,7 +723,7 @@ bt_status_t btif_storage_set_remote_device_property(bt_bdaddr_t *remote_bd_addr,
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bdaddr,
+bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bd_addr,
uint32_t num_properties,
bt_property_t *properties)
{
@@ -659,12 +742,12 @@ bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bdaddr,
bt_property_t addr_prop;
memcpy(&addr_prop, &properties[i], sizeof(bt_property_t));
addr_prop.type = BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP;
- btif_storage_set_remote_device_property(remote_bdaddr,
+ btif_storage_set_remote_device_property(remote_bd_addr,
&addr_prop);
}
else
{
- btif_storage_set_remote_device_property(remote_bdaddr,
+ btif_storage_set_remote_device_property(remote_bd_addr,
&properties[i]);
}
}
@@ -846,6 +929,413 @@ bt_status_t btif_storage_load_bonded_devices(void)
return BT_STATUS_SUCCESS;
}
+#if (BLE_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** Function btif_storage_add_ble_bonding_key
+**
+** Description BTIF storage API - Adds the newly bonded device to NVRAM
+** along with the ble-key, Key type and Pin key length
+**
+** Returns BT_STATUS_SUCCESS if the store was successful,
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+
+bt_status_t btif_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+ char *key,
+ UINT8 key_type,
+ UINT8 key_length)
+{
+ bdstr_t bdstr;
+ bd2str(remote_bd_addr, &bdstr);
+ const char* name;
+ switch(key_type)
+ {
+ case BTIF_DM_LE_KEY_PENC:
+ name = "LE_KEY_PENC";
+ break;
+ case BTIF_DM_LE_KEY_PID:
+ name = "LE_KEY_PID";
+ break;
+ case BTIF_DM_LE_KEY_PCSRK:
+ name = "LE_KEY_PCSRK";
+ break;
+ case BTIF_DM_LE_KEY_LENC:
+ name = "LE_KEY_LENC";
+ break;
+ case BTIF_DM_LE_KEY_LCSRK:
+ name = "LE_KEY_LCSRK";
+ break;
+ default:
+ return BT_STATUS_FAIL;
+ }
+ int ret = btif_config_set("Remote", bdstr, name, (const char*)key, (int)key_length, BTIF_CFG_TYPE_BIN);
+ btif_config_save();
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function btif_storage_get_ble_bonding_key
+**
+** Description
+**
+** Returns BT_STATUS_SUCCESS if the fetch was successful,
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+ UINT8 key_type,
+ char *key_value,
+ int key_length)
+{
+ bdstr_t bdstr;
+ bd2str(remote_bd_addr, &bdstr);
+ const char* name;
+ int type = BTIF_CFG_TYPE_BIN;
+ switch(key_type)
+ {
+ case BTIF_DM_LE_KEY_PENC:
+ name = "LE_KEY_PENC";
+ break;
+ case BTIF_DM_LE_KEY_PID:
+ name = "LE_KEY_PID";
+ break;
+ case BTIF_DM_LE_KEY_PCSRK:
+ name = "LE_KEY_PCSRK";
+ break;
+ case BTIF_DM_LE_KEY_LENC:
+ name = "LE_KEY_LENC";
+ break;
+ case BTIF_DM_LE_KEY_LCSRK:
+ name = "LE_KEY_LCSRK";
+ break;
+ default:
+ return BT_STATUS_FAIL;
+ }
+ int ret = btif_config_get("Remote", bdstr, name, key_value, &key_length, &type);
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+
+}
+
+/*******************************************************************************
+**
+** Function btif_storage_remove_ble_keys
+**
+** Description BTIF storage API - Deletes the bonded device from NVRAM
+**
+** Returns BT_STATUS_SUCCESS if the deletion was successful,
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr)
+{
+ bdstr_t bdstr;
+ bd2str(remote_bd_addr, &bdstr);
+ BTIF_TRACE_DEBUG2(" %s in bd addr:%s",__FUNCTION__, bdstr);
+ int ret = 1;
+ if(btif_config_exist("Remote", bdstr, "LE_KEY_PENC"))
+ ret &= btif_config_remove("Remote", bdstr, "LE_KEY_PENC");
+ if(btif_config_exist("Remote", bdstr, "LE_KEY_PID"))
+ ret &= btif_config_remove("Remote", bdstr, "LE_KEY_PID");
+ if(btif_config_exist("Remote", bdstr, "LE_KEY_PCSRK"))
+ ret &= btif_config_remove("Remote", bdstr, "LE_KEY_PCSRK");
+ if(btif_config_exist("Remote", bdstr, "LE_KEY_LENC"))
+ ret &= btif_config_remove("Remote", bdstr, "LE_KEY_LENC");
+ if(btif_config_exist("Remote", bdstr, "LE_KEY_LCSRK"))
+ ret &= btif_config_remove("Remote", bdstr, "LE_KEY_LCSRK");
+ btif_config_save();
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function btif_storage_add_ble_local_key
+**
+** Description BTIF storage API - Adds the ble key to NVRAM
+**
+** Returns BT_STATUS_SUCCESS if the store was successful,
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_add_ble_local_key(char *key,
+ uint8_t key_type,
+ uint8_t key_length)
+{
+ const char* name;
+ switch(key_type)
+ {
+ case BTIF_DM_LE_LOCAL_KEY_IR:
+ name = "LE_LOCAL_KEY_IR";
+ break;
+ case BTIF_DM_LE_LOCAL_KEY_IRK:
+ name = "LE_LOCAL_KEY_IRK";
+ break;
+ case BTIF_DM_LE_LOCAL_KEY_DHK:
+ name = "LE_LOCAL_KEY_DHK";
+ break;
+ case BTIF_DM_LE_LOCAL_KEY_ER:
+ name = "LE_LOCAL_KEY_ER";
+ break;
+ default:
+ return BT_STATUS_FAIL;
+ }
+ int ret = btif_config_set("Local", "Adapter", name, (const char*)key, key_length, BTIF_CFG_TYPE_BIN);
+ btif_config_save();
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function btif_storage_get_ble_local_key
+**
+** Description
+**
+** Returns BT_STATUS_SUCCESS if the fetch was successful,
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_get_ble_local_key(UINT8 key_type,
+ char *key_value,
+ int key_length)
+{
+ const char* name;
+ int type = BTIF_CFG_TYPE_BIN;
+ switch(key_type)
+ {
+ case BTIF_DM_LE_LOCAL_KEY_IR:
+ name = "LE_LOCAL_KEY_IR";
+ break;
+ case BTIF_DM_LE_LOCAL_KEY_IRK:
+ name = "LE_LOCAL_KEY_IRK";
+ break;
+ case BTIF_DM_LE_LOCAL_KEY_DHK:
+ name = "LE_LOCAL_KEY_DHK";
+ break;
+ case BTIF_DM_LE_LOCAL_KEY_ER:
+ name = "LE_LOCAL_KEY_ER";
+ break;
+ default:
+ return BT_STATUS_FAIL;
+ }
+ int ret = btif_config_get("Local", "Adapter", name, key_value, &key_length, &type);
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+
+}
+
+/*******************************************************************************
+**
+** Function btif_storage_remove_ble_local_keys
+**
+** Description BTIF storage API - Deletes the bonded device from NVRAM
+**
+** Returns BT_STATUS_SUCCESS if the deletion was successful,
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_remove_ble_local_keys(void)
+{
+ int ret = 1;
+ if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_IR"))
+ ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_IR");
+ if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_IRK"))
+ ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_IRK");
+ if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_DHK"))
+ ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_DHK");
+ if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_ER"))
+ ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_ER");
+ btif_config_save();
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+bt_status_t btif_in_fetch_bonded_ble_device(char *remote_bd_addr,int add, btif_bonded_devices_t *p_bonded_devices)
+{
+ int device_type;
+ int addr_type;
+ char buf[100];
+ UINT32 i;
+ bt_bdaddr_t bd_addr;
+ BD_ADDR bta_bd_addr;
+ BOOLEAN is_device_added =FALSE;
+ tBTA_LE_KEY_VALUE *p;
+
+ if(!btif_config_get_int("Remote", remote_bd_addr,"DevType", &device_type))
+ return BT_STATUS_FAIL;
+ if(device_type == BT_DEVICE_TYPE_BLE)
+ {
+ BTIF_TRACE_DEBUG2("%s %s found a BLE device", __FUNCTION__,remote_bd_addr);
+ str2bd(remote_bd_addr, &bd_addr);
+ bdcpy(bta_bd_addr, bd_addr.address);
+ if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) != BT_STATUS_SUCCESS)
+ {
+ return BT_STATUS_FAIL;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (btif_storage_get_ble_bonding_key(&bd_addr,
+ BTIF_DM_LE_KEY_PENC,
+ buf,
+ sizeof(btif_dm_ble_penc_keys_t)) == BT_STATUS_SUCCESS)
+ {
+ if(add)
+ {
+ if (!is_device_added)
+ {
+ BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+ is_device_added = TRUE;
+ }
+ p = (tBTA_LE_KEY_VALUE *)buf;
+ for (i=0; i<16; i++)
+ {
+ BTIF_TRACE_DEBUG2("penc_key.ltk[%d]=0x%02x",i,p->penc_key.ltk[i]);
+ }
+ for (i=0; i<8; i++)
+ {
+ BTIF_TRACE_DEBUG2("penc_key.rand[%d]=0x%02x",i,p->penc_key.rand[i]);
+ }
+ BTIF_TRACE_DEBUG1("p->penc_key.ediv=0x%04x",p->penc_key.ediv);
+ BTIF_TRACE_DEBUG1("p->penc_key.sec_level=0x%02x",p->penc_key.sec_level);
+ BTIF_TRACE_DEBUG1("p->penc_key.key_size=0x%02x",p->penc_key.key_size);
+ BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PENC);
+ }
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (btif_storage_get_ble_bonding_key(&bd_addr,
+ BTIF_DM_LE_KEY_PID,
+ buf,
+ sizeof(btif_dm_ble_pcsrk_keys_t)) == BT_STATUS_SUCCESS)
+ {
+ if(add)
+ {
+ if (!is_device_added)
+ {
+ BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+ is_device_added = TRUE;
+ }
+ p = (tBTA_LE_KEY_VALUE *)buf;
+ for (i=0; i<16; i++)
+ {
+ BTIF_TRACE_DEBUG2("p->pid_key[%d]=0x%02x",i,p->pid_key.irk[i]);
+ }
+
+ BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PID);
+ }
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (btif_storage_get_ble_bonding_key(&bd_addr,
+ BTIF_DM_LE_KEY_PCSRK,
+ buf,
+ sizeof(btif_dm_ble_pcsrk_keys_t)) == BT_STATUS_SUCCESS)
+ {
+ if(add)
+ {
+ if (!is_device_added)
+ {
+ BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+ is_device_added = TRUE;
+ }
+
+ p = (tBTA_LE_KEY_VALUE *)buf;
+ for (i=0; i<16; i++)
+ {
+ BTIF_TRACE_DEBUG2("p->pcsrk_key.csrk[%d]=0x%02x",i, p->psrk_key.csrk[i]);
+ }
+ BTIF_TRACE_DEBUG1("p->pcsrk_key.counter=0x%08x",p->psrk_key.counter);
+ BTIF_TRACE_DEBUG1("p->pcsrk_key.sec_level=0x%02x",p->psrk_key.sec_level);
+
+ BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PCSRK);
+ }
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (btif_storage_get_ble_bonding_key(&bd_addr,
+ BTIF_DM_LE_KEY_LENC,
+ buf,
+ sizeof(btif_dm_ble_lenc_keys_t)) == BT_STATUS_SUCCESS)
+ {
+ if(add)
+ {
+ if (!is_device_added)
+ {
+ BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+ is_device_added = TRUE;
+ }
+ p = (tBTA_LE_KEY_VALUE *)buf;
+ BTIF_TRACE_DEBUG1("p->lenc_key.div=0x%04x",p->lenc_key.div);
+ BTIF_TRACE_DEBUG1("p->lenc_key.key_size=0x%02x",p->lenc_key.key_size);
+ BTIF_TRACE_DEBUG1("p->lenc_key.sec_level=0x%02x",p->lenc_key.sec_level);
+
+ BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LENC);
+ }
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (btif_storage_get_ble_bonding_key(&bd_addr,
+ BTIF_DM_LE_KEY_LCSRK,
+ buf,
+ sizeof(btif_dm_ble_lcsrk_keys_t)) == BT_STATUS_SUCCESS)
+ {
+ if(add)
+ {
+ if (!is_device_added)
+ {
+ BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+ is_device_added = TRUE;
+ }
+ p = (tBTA_LE_KEY_VALUE *)buf;
+ BTIF_TRACE_DEBUG1("p->lcsrk_key.div=0x%04x",p->lcsrk_key.div);
+ BTIF_TRACE_DEBUG1("p->lcsrk_key.counter=0x%08x",p->lcsrk_key.counter);
+ BTIF_TRACE_DEBUG1("p->lcsrk_key.sec_level=0x%02x",p->lcsrk_key.sec_level);
+
+ BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LCSRK);
+ }
+ }
+
+ /* Fill in the bonded devices */
+ if (is_device_added)
+ {
+ memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++], &bd_addr, sizeof(bt_bdaddr_t));
+ btif_gatts_add_bonded_dev_from_nv(bta_bd_addr);
+ }
+
+ return BT_STATUS_SUCCESS;
+ }
+ return BT_STATUS_FAIL;
+}
+
+bt_status_t btif_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+ UINT8 addr_type)
+{
+ bdstr_t bdstr;
+ bd2str(remote_bd_addr, &bdstr);
+ int ret = btif_config_set_int("Remote", bdstr, "AddrType", (int)addr_type);
+ btif_config_save();
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function btif_storage_get_remote_addr_type
+**
+** Description BTIF storage API - Fetches the remote addr type
+**
+** Returns BT_STATUS_SUCCESS if the fetch was successful,
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+ int*addr_type)
+{
+ bdstr_t bdstr;
+ bd2str(remote_bd_addr, &bdstr);
+ int ret = btif_config_get_int("Remote", bdstr, "AddrType", addr_type);
+ return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+#endif
/*******************************************************************************
**
** Function btif_storage_add_hid_device_info
@@ -1273,7 +1763,7 @@ bt_status_t btif_storage_load_autopair_device_list()
** FALSE otherwise
**
*******************************************************************************/
-BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_addr)
+BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_bd_addr)
{
char *token;
int ret;
@@ -1283,7 +1773,7 @@ BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_add
char value[BTIF_STORAGE_MAX_LINE_SZ];
int value_size = sizeof(value);
- bd2str(remote_dev_addr, &bdstr);
+ bd2str(remote_bd_addr, &bdstr);
/* Consider only Lower Address Part from BD Address */
bdstr[8] = '\0';
@@ -1295,7 +1785,7 @@ BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_add
return TRUE;
}
- dev_name_str = BTM_SecReadDevName((remote_dev_addr->address));
+ dev_name_str = BTM_SecReadDevName((remote_bd_addr->address));
if (dev_name_str != NULL)
{
@@ -1339,14 +1829,14 @@ BOOLEAN btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_add
** BT_STATUS_FAIL otherwise
**
*******************************************************************************/
-bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_dev_addr)
+bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_bd_addr)
{
int ret;
bdstr_t bdstr;
char linebuf[BTIF_STORAGE_MAX_LINE_SZ+20];
char input_value [20];
- bd2str(remote_dev_addr, &bdstr);
+ bd2str(remote_bd_addr, &bdstr);
strncpy(input_value, (char*)bdstr, 20);
strncat(input_value,BTIF_AUTO_PAIR_CONF_VALUE_SEPARATOR, 20);
int line_size = sizeof(linebuf);
@@ -1378,7 +1868,7 @@ bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_de
** FALSE otherwise
**
*******************************************************************************/
-BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_dev_addr)
+BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_bd_addr)
{
int ret;
bdstr_t bdstr;
@@ -1386,7 +1876,7 @@ BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_dev_addr)
uint8_t i = 0;
char linebuf[BTIF_STORAGE_MAX_LINE_SZ];
- bd2str(remote_dev_addr, &bdstr);
+ bd2str(remote_bd_addr, &bdstr);
/*consider on LAP part of BDA string*/
bdstr[8] = '\0';
diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c
index 5539c1132..0096effe9 100644
--- a/btif/src/btif_util.c
+++ b/btif/src/btif_util.c
@@ -89,7 +89,7 @@ int str2bd(char *str, bt_bdaddr_t *addr)
return 0;
}
-char *bd2str(bt_bdaddr_t *bdaddr, bdstr_t *bdstr)
+char *bd2str(const bt_bdaddr_t *bdaddr, bdstr_t *bdstr)
{
char *addr = (char *) bdaddr->address;
@@ -103,9 +103,11 @@ UINT32 devclass2uint(DEV_CLASS dev_class)
{
UINT32 cod = 0;
- /* if COD is 0, irrespective of the device type set it to Unclassified device */
- cod = (dev_class[2]) | (dev_class[1] << 8) | (dev_class[0] << 16);
-
+ if(dev_class != NULL)
+ {
+ /* if COD is 0, irrespective of the device type set it to Unclassified device */
+ cod = (dev_class[2]) | (dev_class[1] << 8) | (dev_class[0] << 16);
+ }
return cod;
}
void uint2devclass(UINT32 cod, DEV_CLASS dev_class)
@@ -459,4 +461,3 @@ const char* dump_bt_status(bt_status_t status)
}
-
diff --git a/conf/bt_stack.conf b/conf/bt_stack.conf
index 2cd2f62f4..2ca20ea89 100644
--- a/conf/bt_stack.conf
+++ b/conf/bt_stack.conf
@@ -16,6 +16,7 @@ TraceConf=true
# BT_TRACE_LEVEL_API 3 ( API traces )
# BT_TRACE_LEVEL_EVENT 4 ( Debug messages for events )
# BT_TRACE_LEVEL_DEBUG 5 ( Full debug messages )
+# BT_TRACE_LEVEL_VERBOSE 6 ( Verbose messages ) - Currently supported for TRC_BTAPP only.
TRC_BTM=2
TRC_HCI=2
TRC_L2CAP=2
diff --git a/gki/common/gki_buffer.c b/gki/common/gki_buffer.c
index f474bab6b..bcf6f06b3 100644
--- a/gki/common/gki_buffer.c
+++ b/gki/common/gki_buffer.c
@@ -434,6 +434,7 @@ void *GKI_getbuf (UINT16 size)
GKI_enable();
+ GKI_exception (GKI_ERROR_OUT_OF_BUFFERS, "getbuf: out of buffers");
return (NULL);
}
@@ -460,7 +461,10 @@ void *GKI_getpoolbuf (UINT8 pool_id)
tGKI_COM_CB *p_cb = &gki_cb.com;
if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ GKI_exception(GKI_ERROR_GETPOOLBUF_BAD_QID, "getpoolbuf bad pool");
return (NULL);
+ }
/* Make sure the buffers aren't disturbed til finished with allocation */
GKI_disable();
diff --git a/gki/common/gki_common.h b/gki/common/gki_common.h
index 9bc5005b3..ff5a67573 100644
--- a/gki/common/gki_common.h
+++ b/gki/common/gki_common.h
@@ -43,6 +43,8 @@
#define GKI_ERROR_BUF_SIZE_TOOBIG 0xFFF7
#define GKI_ERROR_BUF_SIZE_ZERO 0xFFF6
#define GKI_ERROR_ADDR_NOT_IN_BUF 0xFFF5
+#define GKI_ERROR_OUT_OF_BUFFERS 0xFFF4
+#define GKI_ERROR_GETPOOLBUF_BAD_QID 0xFFF3
/********************************************************************
diff --git a/hci/src/userial.c b/hci/src/userial.c
index afd301065..d87bea1bf 100644
--- a/hci/src/userial.c
+++ b/hci/src/userial.c
@@ -52,6 +52,10 @@
#define USERIALDBG(param, ...) {}
#endif
+#ifndef ENABLE_USERIAL_TIMING_LOGS
+#define ENABLE_USERIAL_TIMING_LOGS FALSE
+#endif
+
#define MAX_SERIAL_PORT (USERIAL_PORT_3 + 1)
#define READ_LIMIT (BTHC_USERIAL_READ_MEM_SIZE - BT_HC_HDR_SIZE)
@@ -91,6 +95,29 @@ static volatile uint8_t userial_running = 0;
** Static functions
******************************************************************************/
+#if defined(ENABLE_USERIAL_TIMING_LOGS) && (ENABLE_USERIAL_TIMING_LOGS==TRUE)
+
+static void log_userial_tx_timing(int len)
+{
+ #define USEC_PER_SEC 1000000L
+ static struct timespec prev = {0, 0};
+ struct timespec now, diff;
+ unsigned int diff_us = 0;
+ unsigned int now_us = 0;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
+ diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
+
+ ALOGW("[userial] ts %08d diff : %08d len %d", now_us, diff_us,
+ len);
+
+ prev = now;
+}
+
+#endif
+
+
/*****************************************************************************
** Socket signal functions to wake up userial_read_thread for termination
**
@@ -125,6 +152,7 @@ static inline int is_signaled(fd_set* set)
return FD_ISSET(signal_fds[0], set);
}
+
/*******************************************************************************
**
** Function select_read
@@ -454,6 +482,9 @@ uint16_t userial_write(uint16_t msg_id, uint8_t *p_data, uint16_t len)
while(len != 0)
{
+#if defined(ENABLE_USERIAL_TIMING_LOGS) && (ENABLE_USERIAL_TIMING_LOGS==TRUE)
+ log_userial_tx_timing(len);
+#endif
ret = write(userial_cb.fd, p_data+total, len);
total += ret;
len -= ret;
diff --git a/include/bt_target.h b/include/bt_target.h
index 836868e8b..98968f54f 100755..100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -260,7 +260,7 @@
#endif
#ifndef BTA_GATT_INCLUDED
-#define BTA_GATT_INCLUDED FALSE
+#define BTA_GATT_INCLUDED TRUE
#endif
#ifndef BTA_DISABLE_DELAY
@@ -555,11 +555,6 @@
#define BTM_CMD_POOL_ID GKI_POOL_ID_2
#endif
-/* Sends TCS messages. */
-#ifndef TCS_MSG_POOL_ID
-#define TCS_MSG_POOL_ID GKI_POOL_ID_2
-#endif
-
#ifndef OBX_CMD_POOL_SIZE
#define OBX_CMD_POOL_SIZE GKI_BUF2_SIZE
#endif
@@ -577,11 +572,6 @@
#define CTP_SDP_DB_POOL_ID GKI_POOL_ID_3
#endif
-/* Used for CTP data exchange feature. */
-#ifndef CTP_DATA_EXCHG_POOL_ID
-#define CTP_DATA_EXCHG_POOL_ID GKI_POOL_ID_2
-#endif
-
/* Used to send data to L2CAP. */
#ifndef GAP_DATA_POOL_ID
#define GAP_DATA_POOL_ID GKI_POOL_ID_3
@@ -596,24 +586,6 @@
#define SPP_DB_SIZE GKI_BUF3_SIZE
#endif
-/* HCRP protocol and internal commands. */
-#ifndef HCRP_CMD_POOL_ID
-#define HCRP_CMD_POOL_ID GKI_POOL_ID_2
-#endif
-
-#ifndef HCRP_CMD_POOL_SIZE
-#define HCRP_CMD_POOL_SIZE GKI_BUF2_SIZE
-#endif
-
-#ifndef BIP_EVT_POOL_SIZE
-#define BIP_EVT_POOL_SIZE GKI_BUF3_SIZE
-#endif
-
-#ifndef BIP_DB_SIZE
-#define BIP_DB_SIZE GKI_BUF3_SIZE
-#endif
-
-
/* BNEP data and protocol messages. */
#ifndef BNEP_POOL_ID
#define BNEP_POOL_ID GKI_POOL_ID_3
@@ -1245,7 +1217,7 @@ and USER_HW_DISABLE_API macros */
/* The maximum number of simultaneous channels that L2CAP can support. */
#ifndef MAX_L2CAP_CHANNELS
-#define MAX_L2CAP_CHANNELS 10
+#define MAX_L2CAP_CHANNELS 16
#endif
/* The maximum number of simultaneous applications that can register with L2CAP. */
@@ -1417,8 +1389,8 @@ and USER_HW_DISABLE_API macros */
**
******************************************************************************/
-#ifndef BLE_INCLUDED
-#define BLE_INCLUDED FALSE
+#ifndef _cac
+#define BLE_INCLUDED TRUE
#endif
#ifndef LOCAL_BLE_CONTROLLER_ID
@@ -1431,19 +1403,19 @@ and USER_HW_DISABLE_API macros */
**
******************************************************************************/
#ifndef ATT_INCLUDED
-#define ATT_INCLUDED FALSE
+#define ATT_INCLUDED TRUE
#endif
#ifndef ATT_DEBUG
-#define ATT_DEBUG FALSE
+#define ATT_DEBUG TRUE
#endif
#ifndef GATT_SERVER_ENABLED
-#define GATT_SERVER_ENABLED FALSE
+#define GATT_SERVER_ENABLED TRUE
#endif
#ifndef GATT_CLIENT_ENABLED
-#define GATT_CLIENT_ENABLED FALSE
+#define GATT_CLIENT_ENABLED TRUE
#endif
#ifndef GATT_MAX_SR_PROFILES
@@ -1479,11 +1451,11 @@ and USER_HW_DISABLE_API macros */
**
******************************************************************************/
#ifndef SMP_INCLUDED
-#define SMP_INCLUDED FALSE
+#define SMP_INCLUDED TRUE
#endif
#ifndef SMP_DEBUG
-#define SMP_DEBUG FALSE
+#define SMP_DEBUG TRUE
#endif
#ifndef SMP_DEFAULT_AUTH_REQ
@@ -2189,7 +2161,7 @@ Range: Minimum 12000 (12 secs) on BR/EDR when supporting PBF.
******************************************************************************/
#ifndef GAP_INCLUDED
-#define GAP_INCLUDED FALSE
+#define GAP_INCLUDED TRUE
#endif
/* This is set to enable use of GAP L2CAP connections. */
@@ -3749,9 +3721,6 @@ The maximum number of payload octets that the local device can receive in a sing
#define L2CAP_FEATURE_RSP_ID 173
-#define L2CAP_ENHANCED_FEATURES 0
-
-
/******************************************************************************
**
** BTA
diff --git a/include/bt_trace.h b/include/bt_trace.h
index 6c3e7b12a..e6a0b71fc 100644
--- a/include/bt_trace.h
+++ b/include/bt_trace.h
@@ -4668,6 +4668,28 @@ extern UINT8 btif_trace_level;
(m), (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5));}
#define APPL_TRACE_DEBUG6(m,p1,p2,p3,p4,p5,p6) {if (appl_trace_level >= BT_TRACE_LEVEL_DEBUG) LogMsg_6(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, \
(m), (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5), (UINT32)(p6));}
+
+#define APPL_TRACE_VERBOSE0(m) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+ LogMsg_0(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m));}
+#define APPL_TRACE_VERBOSE1(m,p1) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+ LogMsg_1(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+ (UINT32)(p1));}
+#define APPL_TRACE_VERBOSE2(m,p1,p2) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+ LogMsg_2(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+ (UINT32)(p1), (UINT32)(p2));}
+#define APPL_TRACE_VERBOSE3(m,p1,p2,p3) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+ LogMsg_3(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+ (UINT32)(p1), (UINT32)(p2), (UINT32)(p3));}
+#define APPL_TRACE_VERBOSE4(m,p1,p2,p3,p4) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+ LogMsg_4(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+ (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4));}
+#define APPL_TRACE_VERBOSE5(m,p1,p2,p3,p4,p5) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+ LogMsg_5(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+ (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5));}
+#define APPL_TRACE_VERBOSE6(m,p1,p2,p3,p4,p5,p6) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+ LogMsg_6(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+ (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5), (UINT32)(p6));}
+
#else
/* define traces for Application */
@@ -4711,6 +4733,14 @@ extern UINT8 btif_trace_level;
#define APPL_TRACE_DEBUG5(m,p1,p2,p3,p4,p5)
#define APPL_TRACE_DEBUG6(m,p1,p2,p3,p4,p5,p6)
+#define APPL_TRACE_VERBOSE0(m)
+#define APPL_TRACE_VERBOSE1(m,p1)
+#define APPL_TRACE_VERBOSE2(m,p1,p2)
+#define APPL_TRACE_VERBOSE3(m,p1,p2,p3)
+#define APPL_TRACE_VERBOSE4(m,p1,p2,p3,p4)
+#define APPL_TRACE_VERBOSE5(m,p1,p2,p3,p4,p5)
+#define APPL_TRACE_VERBOSE6(m,p1,p2,p3,p4,p5,p6)
+
#endif
#if ((MMI_INCLUDED == TRUE) && (!defined(HID_MSKB_INCLUDED) || (HID_MSKB_INCLUDED == FALSE)))
diff --git a/include/bte.h b/include/bte.h
index 103b6604e..968b68a40 100644
--- a/include/bte.h
+++ b/include/bte.h
@@ -100,9 +100,12 @@ extern int (*p_bte_hci_send)(UINT16 port, BT_HDR *p_msg);
/* Protocol trace mask */
extern UINT32 bte_proto_trace_mask;
-/* Version string */
+/* BTE version string */
extern const UINT8 bte_version_string[];
+/* BTIF version string */
+extern const UINT8 btif_version_string[];
+
typedef struct tBAUD_REG_tag {
UINT8 DHBR;
UINT8 DLBR;
diff --git a/include/bte_appl.h b/include/bte_appl.h
index 63689daa6..cf0baed24 100644
--- a/include/bte_appl.h
+++ b/include/bte_appl.h
@@ -70,25 +70,12 @@
#define BTE_APPL_CONTACTS_DB_PATH 256
typedef struct {
- char patchram_path[BTE_APPL_PATCHRAM_PATH_MAXLEN+1];
- UINT32 patchram_addr;
- UINT32 reconfig_baud;
- UINT32 clock_rate; /* clock rate (for uart baud calculation) */
- BD_ADDR local_addr; /* local bd addr */
- BD_ADDR rem_addr;
- UINT8 lpm_enabled;
- UINT8 bt_wake_polarity;
- UINT8 host_wake_polarity;
- BOOLEAN ag_enable_3way_conf;
- UINT16 ag_voice_settings;
- UINT8 ag_vsc_pcm_config[5];
- UINT8 ag_vsc_sco_pcm[5];
- /*tBTM_CMPL_CB*/ tBTM_DEV_STATUS_CB *p_reset_cplt_cb; /* Current reset_cplt_cb */
- char contacts_db[BTE_APPL_CONTACTS_DB_PATH+1];
- UINT32 bta_module_state[BTAPP_NUM_ID_BLOCKS]; /* state of enabled bta modules */
-#if (BTAPP_AHF_API_SUPPORT==TRUE)
- UINT8 afh_first;
- UINT8 afh_last;
+#if ((BLE_INCLUDED == TRUE) && (SMP_INCLUDED == TRUE))
+ UINT8 ble_auth_req;
+ UINT8 ble_io_cap;
+ UINT8 ble_init_key;
+ UINT8 ble_resp_key;
+ UINT8 ble_max_key_size;
#endif
} tBTE_APPL_CFG;
diff --git a/main/Android.mk b/main/Android.mk
index 8ecb3c3dc..3e311d4ac 100644
--- a/main/Android.mk
+++ b/main/Android.mk
@@ -37,6 +37,11 @@ LOCAL_SRC_FILES += \
../btif/src/btif_sock_sdp.c \
../btif/src/btif_sock_util.c \
../btif/src/btif_pan.c \
+ ../btif/src/btif_gatt.c \
+ ../btif/src/btif_gatt_client.c \
+ ../btif/src/btif_gatt_server.c \
+ ../btif/src/btif_gatt_util.c \
+ ../btif/src/btif_gatt_test.c \
../btif/src/btif_config.c \
../btif/src/btif_config_util.cpp \
../btif/src/btif_profile_queue.c
@@ -50,7 +55,9 @@ LOCAL_SRC_FILES+= \
../btif/co/bta_av_co.c \
../btif/co/bta_hh_co.c \
../btif/co/bta_hl_co.c \
- ../btif/co/bta_pan_co.c
+ ../btif/co/bta_pan_co.c \
+ ../btif/co/bta_gattc_co.c \
+ ../btif/co/bta_gatts_co.c \
# sbc encoder
LOCAL_SRC_FILES+= \
diff --git a/main/bte_logmsg.c b/main/bte_logmsg.c
index 7035a578f..6c9a5eb4f 100644
--- a/main/bte_logmsg.c
+++ b/main/bte_logmsg.c
@@ -91,6 +91,7 @@
#if (BLE_INCLUDED==TRUE)
#include "gatt_api.h"
+#include "smp_api.h"
#endif
/* LayerIDs for BTA, currently everything maps onto appl_trace_level */
@@ -282,7 +283,6 @@ ScrLog(UINT32 trace_set_mask, const char *fmt_str, ...)
int trace_layer = TRACE_GET_LAYER(trace_set_mask);
if (trace_layer >= TRACE_LAYER_MAX_NUM)
trace_layer = 0;
-
gettimeofday(&tv, &tz);
time(&t);
tm = localtime(&t);
@@ -467,8 +467,6 @@ tBTTRC_FUNC_MAP bttrc_set_level_map[] = {
{BTTRC_ID_STK_SDP, BTTRC_ID_STK_SDP, SDP_SetTraceLevel, "TRC_SDP", DEFAULT_CONF_TRACE_LEVEL},
#if (BLE_INCLUDED==TRUE)
{BTTRC_ID_STK_GATT, BTTRC_ID_STK_GATT, GATT_SetTraceLevel, "TRC_GATT", DEFAULT_CONF_TRACE_LEVEL},
-#endif
-#if (BLE_INCLUDED==TRUE)
{BTTRC_ID_STK_SMP, BTTRC_ID_STK_SMP, SMP_SetTraceLevel, "TRC_SMP", DEFAULT_CONF_TRACE_LEVEL},
#endif
diff --git a/main/bte_version.c b/main/bte_version.c
index 0751e1d17..826f31b6b 100644
--- a/main/bte_version.c
+++ b/main/bte_version.c
@@ -18,5 +18,6 @@
#include "bt_types.h"
-const UINT8 bte_version_string[] = "BCM1200_PI_10.3.20.33";
+const UINT8 bte_version_string[] = "BCM1200_PI_10.3.20.52";
+const UINT8 btif_version_string[] = "BDROID-PLUS-420-10_00.10";
diff --git a/stack/Android.mk b/stack/Android.mk
index dcbe961b5..e17f4c820 100644
--- a/stack/Android.mk
+++ b/stack/Android.mk
@@ -80,6 +80,10 @@ LOCAL_SRC_FILES:= \
./mcap/mca_csm.c \
./mcap/mca_cact.c \
./mcap/mca_api.c \
+ ./gap/gap_ble.c \
+ ./gap/gap_api.c \
+ ./gap/gap_utils.c \
+ ./gap/gap_conn.c \
./gatt/gatt_sr.c \
./gatt/gatt_cl.c \
./gatt/gatt_api.c \
@@ -96,6 +100,7 @@ LOCAL_SRC_FILES:= \
./avct/avct_lcb_act.c \
./smp/smp_main.c \
./smp/smp_l2c.c \
+ ./smp/aes.c \
./smp/smp_cmac.c \
./smp/smp_utils.c \
./smp/smp_act.c \
diff --git a/stack/avdt/avdt_api.c b/stack/avdt/avdt_api.c
index 67fe4524c..855f17e4d 100644
--- a/stack/avdt/avdt_api.c
+++ b/stack/avdt/avdt_api.c
@@ -883,7 +883,7 @@ UINT16 AVDT_SecurityRsp(UINT8 handle, UINT8 label, UINT8 error_code,
/*******************************************************************************
**
-** Function AVDT_WriteReq
+** Function AVDT_WriteReqOpt
**
** Description Send a media packet to the peer device. The stream must
** be started before this function is called. Also, this
@@ -901,7 +901,8 @@ UINT16 AVDT_SecurityRsp(UINT8 handle, UINT8 label, UINT8 error_code,
**
** The application passes the packet using the BT_HDR structure.
** This structure is described in section 2.1. The offset
-** field must be equal to or greater than AVDT_MEDIA_OFFSET.
+** field must be equal to or greater than AVDT_MEDIA_OFFSET
+** (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used).
** This allows enough space in the buffer for the L2CAP and
** AVDTP headers.
**
@@ -910,11 +911,13 @@ UINT16 AVDT_SecurityRsp(UINT8 handle, UINT8 label, UINT8 error_code,
** by the protocol stack; the application must not free
** this buffer.
**
+** The opt parameter allows passing specific options like:
+** - NO_RTP : do not add the RTP header to buffer
**
** Returns AVDT_SUCCESS if successful, otherwise error.
**
*******************************************************************************/
-UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
+UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt, tAVDT_DATA_OPT_MASK opt)
{
tAVDT_SCB *p_scb;
tAVDT_SCB_EVT evt;
@@ -932,6 +935,7 @@ UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
evt.apiwrite.p_buf = p_pkt;
evt.apiwrite.time_stamp = time_stamp;
evt.apiwrite.m_pt = m_pt;
+ evt.apiwrite.opt = opt;
#if AVDT_MULTIPLEXING == TRUE
GKI_init_q (&evt.apiwrite.frag_q);
#endif
@@ -943,6 +947,44 @@ UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
/*******************************************************************************
**
+** Function AVDT_WriteReq
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC.
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteReq(). If the applications calls
+** AVDT_WriteReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+** or AVDT_START_IND_EVT.
+**
+** The application passes the packet using the BT_HDR structure.
+** This structure is described in section 2.1. The offset
+** field must be equal to or greater than AVDT_MEDIA_OFFSET.
+** This allows enough space in the buffer for the L2CAP and
+** AVDTP headers.
+**
+** The memory pointed to by p_pkt must be a GKI buffer
+** allocated by the application. This buffer will be freed
+** by the protocol stack; the application must not free
+** this buffer.
+**
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
+{
+ return AVDT_WriteReqOpt(handle, p_pkt, time_stamp, m_pt, AVDT_DATA_OPT_NONE);
+}
+
+/*******************************************************************************
+**
** Function AVDT_ConnectReq
**
** Description This function initiates an AVDTP signaling connection
@@ -1248,7 +1290,7 @@ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type,
tAVDT_TC_TBL *p_tbl;
UINT8 *p, *plen, *pm1, *p_end;
#if AVDT_MULTIPLEXING == TRUE
- UINT8 *p_al, u;
+ UINT8 *p_al=NULL, u;
#endif
UINT32 ssrc;
UINT16 len;
diff --git a/stack/avdt/avdt_ccb_act.c b/stack/avdt/avdt_ccb_act.c
index 5719be963..12c11b4cb 100644
--- a/stack/avdt/avdt_ccb_act.c
+++ b/stack/avdt/avdt_ccb_act.c
@@ -167,10 +167,10 @@ void avdt_ccb_hdl_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
if (p_scb->allocated)
{
/* copy sep info */
- sep_info[i].in_use = p_scb->in_use;
- sep_info[i].seid = i + 1;
- sep_info[i].media_type = p_scb->cs.media_type;
- sep_info[i].tsep = p_scb->cs.tsep;
+ sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
+ sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
+ sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->cs.media_type;
+ sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;
p_data->msg.discover_rsp.num_seps++;
}
diff --git a/stack/avdt/avdt_int.h b/stack/avdt/avdt_int.h
index 9b101fc70..04968a6d5 100644
--- a/stack/avdt/avdt_int.h
+++ b/stack/avdt/avdt_int.h
@@ -459,6 +459,7 @@ typedef struct {
UINT32 data_len;
#endif
UINT8 m_pt;
+ tAVDT_DATA_OPT_MASK opt;
} tAVDT_SCB_APIWRITE;
/* type for AVDT_SCB_TC_CLOSE_EVT */
diff --git a/stack/avdt/avdt_scb_act.c b/stack/avdt/avdt_scb_act.c
index c2ced7499..66f9b7d3c 100644
--- a/stack/avdt/avdt_scb_act.c
+++ b/stack/avdt/avdt_scb_act.c
@@ -1213,19 +1213,22 @@ void avdt_scb_hdl_write_req_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
}
/* build a media packet */
+ /* Add RTP header if required */
+ if ( !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP) )
+ {
+ ssrc = avdt_scb_gen_ssrc(p_scb);
- ssrc = avdt_scb_gen_ssrc(p_scb);
-
- p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
- p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
+ p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
+ p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
- p = (UINT8 *)(p_data->apiwrite.p_buf + 1) + p_data->apiwrite.p_buf->offset;
+ p = (UINT8 *)(p_data->apiwrite.p_buf + 1) + p_data->apiwrite.p_buf->offset;
- UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
- UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
- UINT16_TO_BE_STREAM(p, p_scb->media_seq);
- UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
- UINT32_TO_BE_STREAM(p, ssrc);
+ UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
+ UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
+ UINT16_TO_BE_STREAM(p, p_scb->media_seq);
+ UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
+ UINT32_TO_BE_STREAM(p, ssrc);
+ }
p_scb->media_seq++;
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index e3ac11bea..eb847bbc3 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -127,8 +127,6 @@ UINT8 btm_handle_to_acl_index (UINT16 hci_handle)
/* If here, no BD Addr found */
return(xx);
}
-
-
/*******************************************************************************
**
** Function btm_acl_created
@@ -142,7 +140,7 @@ UINT8 btm_handle_to_acl_index (UINT16 hci_handle)
void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
UINT16 hci_handle, UINT8 link_role, UINT8 is_le_link)
{
- tBTM_SEC_DEV_REC *p_dev_rec;
+ tBTM_SEC_DEV_REC *p_dev_rec = NULL;
UINT8 yy;
tACL_CONN *p;
UINT8 xx;
@@ -173,8 +171,16 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
p->hci_handle = hci_handle;
p->link_role = link_role;
p->link_up_issued = FALSE;
+
#if BLE_INCLUDED == TRUE
p->is_le_link = is_le_link;
+
+ if (is_le_link)
+ {
+ p->conn_addr_type = BLE_ADDR_PUBLIC;
+ BTM_GetLocalDeviceAddr(p->conn_addr);
+ }
+
#endif
p->restore_pkt_types = 0; /* Only exists while SCO is active */
p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
@@ -193,8 +199,12 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
if (bdn)
memcpy (p->remote_name, bdn, BTM_MAX_REM_BD_NAME_LEN);
-
- /* Check if we already know features for this device */
+ /* if BR/EDR do something more */
+ if (!is_le_link)
+ {
+ btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
+ btsnd_hcic_rmt_ver_req (p->hci_handle);
+ }
p_dev_rec = btm_find_dev_by_handle (hci_handle);
#if (BLE_INCLUDED == TRUE)
@@ -204,18 +214,9 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
}
#endif
-
- if (p_dev_rec
-#if (BLE_INCLUDED == TRUE)
- && p_dev_rec->device_type != BT_DEVICE_TYPE_BLE
-#endif
- )
+ if (p_dev_rec && !is_le_link)
{
- /* if BR/EDR do something more */
- btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
- btsnd_hcic_rmt_ver_req (p->hci_handle);
-
for (yy = 0; yy < BD_FEATURES_LEN; yy++)
{
if (p_dev_rec->features[yy])
@@ -238,17 +239,15 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
}
}
}
+
#if (BLE_INCLUDED == TRUE)
/* If here, features are not known yet */
- if (p_dev_rec && p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+ if (p_dev_rec && is_le_link)
{
btm_establish_continue(p);
if (link_role == HCI_ROLE_MASTER)
{
- btm_ble_update_bg_state();
- btm_ble_resume_bg_conn (NULL, FALSE);
-
btsnd_hcic_ble_read_remote_feat(p->hci_handle);
}
}
@@ -282,10 +281,10 @@ void btm_acl_report_role_change (UINT8 hci_status, BD_ADDR bda)
if (btm_cb.devcb.p_switch_role_cb && (bda &&
(0 == memcmp(btm_cb.devcb.switch_role_ref_data.remote_bd_addr, bda, BD_ADDR_LEN))))
{
- memset (&btm_cb.devcb.switch_role_ref_data, 0, sizeof(tBTM_ROLE_SWITCH_CMPL));
- ref_data.hci_status = hci_status;
memcpy (&ref_data, &btm_cb.devcb.switch_role_ref_data, sizeof(tBTM_ROLE_SWITCH_CMPL));
+ ref_data.hci_status = hci_status;
(*btm_cb.devcb.p_switch_role_cb)(&ref_data);
+ memset (&btm_cb.devcb.switch_role_ref_data, 0, sizeof(tBTM_ROLE_SWITCH_CMPL));
btm_cb.devcb.p_switch_role_cb = NULL;
}
}
@@ -309,7 +308,6 @@ void btm_acl_removed (BD_ADDR bda)
#endif
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
tBTM_SEC_DEV_REC *p_dev_rec=NULL;
- UINT16 combined_mode;
#endif
BTM_TRACE_DEBUG0 ("btm_acl_removed");
@@ -351,23 +349,6 @@ void btm_acl_removed (BD_ADDR bda)
btm_cb.ble_ctr_cb.inq_var.connectable_mode,
p->link_role);
-
- /* If we are LE connectable, check if we need to start advertising again */
- if ( p->is_le_link && (btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE) )
- {
- tACL_CONN *pa = &btm_cb.acl_db[0];
- UINT16 xx;
-
- for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
- {
- /* If any other LE link is up, we are still not connectable */
- if (pa->in_use && pa->is_le_link)
- return;
- }
- combined_mode = (btm_cb.ble_ctr_cb.inq_var.connectable_mode | btm_cb.btm_inq_vars.connectable_mode);
- btm_ble_set_connectability ( combined_mode );
- }
-
p_dev_rec = btm_find_dev(bda);
if ( p_dev_rec)
{
@@ -451,7 +432,6 @@ void btm_acl_update_busy_level (tBTM_BLI_EVENT event)
case BTM_BLI_ACL_UP_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_ACL_UP_EVT");
btm_cb.num_acl++;
- busy_level = (UINT8)btm_cb.num_acl;
break;
case BTM_BLI_ACL_DOWN_EVT:
if (btm_cb.num_acl)
@@ -463,35 +443,39 @@ void btm_acl_update_busy_level (tBTM_BLI_EVENT event)
{
BTM_TRACE_ERROR0 ("BTM_BLI_ACL_DOWN_EVT issued, but num_acl already zero !!!");
}
- busy_level = (UINT8)btm_cb.num_acl;
break;
case BTM_BLI_PAGE_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_PAGE_EVT");
btm_cb.is_paging = TRUE;
- busy_level = BTM_BL_PAGING_STARTED;
+ evt.busy_level_flags= BTM_BL_PAGING_STARTED;
break;
case BTM_BLI_PAGE_DONE_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_PAGE_DONE_EVT");
btm_cb.is_paging = FALSE;
- busy_level = BTM_BL_PAGING_COMPLETE;
+ evt.busy_level_flags = BTM_BL_PAGING_COMPLETE;
break;
case BTM_BLI_INQ_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_EVT");
btm_cb.is_inquiry = TRUE;
- busy_level = BTM_BL_INQUIRY_STARTED;
+ evt.busy_level_flags = BTM_BL_INQUIRY_STARTED;
break;
case BTM_BLI_INQ_CANCEL_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_CANCEL_EVT");
btm_cb.is_inquiry = FALSE;
- busy_level = BTM_BL_INQUIRY_CANCELLED;
+ evt.busy_level_flags = BTM_BL_INQUIRY_CANCELLED;
break;
case BTM_BLI_INQ_DONE_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_DONE_EVT");
btm_cb.is_inquiry = FALSE;
- busy_level = BTM_BL_INQUIRY_COMPLETE;
+ evt.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;
break;
}
+ if (btm_cb.is_paging || btm_cb.is_inquiry)
+ busy_level = 10;
+ else
+ busy_level = (UINT8)btm_cb.num_acl;
+
if (busy_level != btm_cb.busy_level)
{
evt.event = BTM_BL_UPDATE_EVT;
@@ -631,10 +615,7 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, UINT8 new_role, tBTM_CMPL_CB
/* Wake up the link if in sniff or park before attempting switch */
if (pwr_mode == BTM_PM_MD_PARK || pwr_mode == BTM_PM_MD_SNIFF)
{
-/* Coverity FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-*/
+ memset( (void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
status = BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p->remote_addr, &settings);
if (status != BTM_CMD_STARTED)
@@ -646,7 +627,8 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, UINT8 new_role, tBTM_CMPL_CB
/* some devices do not support switch while encryption is on */
else
{
- if (((p_dev_rec = btm_find_dev (remote_bd_addr)) != NULL)
+ p_dev_rec = btm_find_dev (remote_bd_addr);
+ if ((p_dev_rec != NULL)
&& ((p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED) != 0)
&& !BTM_EPR_AVAILABLE(p))
{
@@ -741,10 +723,7 @@ tBTM_STATUS BTM_ChangeLinkKey (BD_ADDR remote_bd_addr, tBTM_CMPL_CB *p_cb)
/* Wake up the link if in park before attempting to change link keys */
if (pwr_mode == BTM_PM_MD_PARK)
{
-/* Coverity: FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-*/
+ memset( (void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
status = BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p->remote_addr, &settings);
if (status != BTM_CMD_STARTED)
@@ -863,12 +842,11 @@ void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
{
tACL_CONN *p;
UINT8 xx;
+ tBTM_SEC_DEV_REC *p_dev_rec;
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
tBTM_BL_ROLE_CHG_DATA evt;
#endif
-#if BTM_DISC_DURING_RS == TRUE
- tBTM_SEC_DEV_REC *p_dev_rec;
-#endif
+
BTM_TRACE_DEBUG3 ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d", handle, status, encr_enable);
xx = btm_handle_to_acl_index(handle);
/* don't assume that we can never get a bad hci_handle */
@@ -1044,8 +1022,36 @@ tBTM_STATUS BTM_SetLinkPolicy (BD_ADDR remote_bda, UINT16 *settings)
*******************************************************************************/
void BTM_SetDefaultLinkPolicy (UINT16 settings)
{
- BTM_TRACE_DEBUG0 ("BTM_SetDefaultLinkPolicy");
+ UINT8 *localFeatures = BTM_ReadLocalFeatures();
+
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy setting:0x%04x", settings);
+
+ if((settings & HCI_ENABLE_MASTER_SLAVE_SWITCH) && (!HCI_SWITCH_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy switch not supported (settings: 0x%04x)", settings);
+ }
+ if ((settings & HCI_ENABLE_HOLD_MODE) && (!HCI_HOLD_MODE_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_HOLD_MODE;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy hold not supported (settings: 0x%04x)", settings);
+ }
+ if ((settings & HCI_ENABLE_SNIFF_MODE) && (!HCI_SNIFF_MODE_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_SNIFF_MODE;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy sniff not supported (settings: 0x%04x)", settings);
+ }
+ if ((settings & HCI_ENABLE_PARK_MODE) && (!HCI_PARK_MODE_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_PARK_MODE;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy park not supported (settings: 0x%04x)", settings);
+ }
+ BTM_TRACE_DEBUG1("Set DefaultLinkPolicy:0x%04x", settings);
+
btm_cb.btm_def_link_policy = settings;
+
+ /* Set the default Link Policy of the controller */
+ btsnd_hcic_write_def_policy_set(settings);
}
@@ -1361,8 +1367,6 @@ static void btm_establish_continue (tACL_CONN *p_acl_cb)
if (btm_cb.btm_def_link_policy)
BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
-
- BTM_SetLinkSuperTout (p_acl_cb->remote_addr, btm_cb.btm_def_link_super_tout);
}
#endif
p_acl_cb->link_up_issued = TRUE;
@@ -1377,7 +1381,6 @@ static void btm_establish_continue (tACL_CONN *p_acl_cb)
evt_data.conn.p_dc = p_acl_cb->remote_dc;
evt_data.conn.p_features = p_acl_cb->features;
-
(*btm_cb.p_bl_changed_cb)(&evt_data);
}
btm_acl_update_busy_level (BTM_BLI_ACL_UP_EVT);
@@ -1410,6 +1413,30 @@ void BTM_SetDefaultLinkSuperTout (UINT16 timeout)
/*******************************************************************************
**
+** Function BTM_GetLinkSuperTout
+**
+** Description Read the link supervision timeout value of the connection
+**
+** Returns status of the operation
+**
+*******************************************************************************/
+tBTM_STATUS BTM_GetLinkSuperTout (BD_ADDR remote_bda, UINT16 *p_timeout)
+{
+ tACL_CONN *p = btm_bda_to_acl(remote_bda);
+
+ BTM_TRACE_DEBUG0 ("BTM_GetLinkSuperTout");
+ if (p != (tACL_CONN *)NULL)
+ {
+ *p_timeout = p->link_super_tout;
+ return(BTM_SUCCESS);
+ }
+ /* If here, no BD Addr found */
+ return(BTM_UNKNOWN_ADDR);
+}
+
+
+/*******************************************************************************
+**
** Function BTM_SetLinkSuperTout
**
** Description Create and send HCI "Write Link Supervision Timeout" command
@@ -1802,7 +1829,7 @@ BOOLEAN BTM_IsAclConnectionUp (BD_ADDR remote_bda)
{
tACL_CONN *p;
- BTM_TRACE_API6 ("BTM_ReadClockOffset: RemBdAddr: %02x%02x%02x%02x%02x%02x",
+ BTM_TRACE_API6 ("BTM_IsAclConnectionUp: RemBdAddr: %02x%02x%02x%02x%02x%02x",
remote_bda[0], remote_bda[1], remote_bda[2],
remote_bda[3], remote_bda[4], remote_bda[5]);
@@ -1967,12 +1994,11 @@ void btm_acl_role_changed (UINT8 hci_status, BD_ADDR bd_addr, UINT8 new_role)
UINT8 *p_bda = (bd_addr) ? bd_addr : btm_cb.devcb.switch_role_ref_data.remote_bd_addr;
tACL_CONN *p = btm_bda_to_acl(p_bda);
tBTM_ROLE_SWITCH_CMPL *p_data = &btm_cb.devcb.switch_role_ref_data;
+ tBTM_SEC_DEV_REC *p_dev_rec;
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
tBTM_BL_ROLE_CHG_DATA evt;
#endif
-#if BTM_DISC_DURING_RS == TRUE
- tBTM_SEC_DEV_REC *p_dev_rec;
-#endif
+
BTM_TRACE_DEBUG0 ("btm_acl_role_changed");
/* Ignore any stray events */
if (p == NULL)
@@ -2297,14 +2323,7 @@ UINT16 btm_get_max_packet_size (BD_ADDR addr)
pkt_size = HCI_DM1_PACKET_SIZE;
}
-#ifdef BRCM_VS
- /* Using HCI size 1017 instead of 1021 */
- if ((pkt_size == HCI_EDR3_DH5_PACKET_SIZE)
- && (btu_cb.hcit_acl_data_size == 1017))
- pkt_size = 1017;
-#endif
-
- return(pkt_size);
+ return(pkt_size);
}
/*******************************************************************************
@@ -2830,14 +2849,15 @@ tBTM_STATUS btm_remove_acl (BD_ADDR bd_addr)
}
else /* otherwise can disconnect right away */
#endif
-
- if (hci_handle != 0xFFFF)
{
- if (!btsnd_hcic_disconnect (hci_handle, HCI_ERR_PEER_USER))
- status = BTM_NO_RESOURCES;
+ if (hci_handle != 0xFFFF)
+ {
+ if (!btsnd_hcic_disconnect (hci_handle, HCI_ERR_PEER_USER))
+ status = BTM_NO_RESOURCES;
+ }
+ else
+ status = BTM_UNKNOWN_ADDR;
}
- else
- status = BTM_UNKNOWN_ADDR;
return status;
}
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 74b5767d1..1d2cdf30c 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -31,14 +31,15 @@
#include "btm_int.h"
#include "btm_ble_api.h"
#include "smp_api.h"
+#include "l2c_int.h"
+#include "gap_api.h"
#if SMP_INCLUDED == TRUE
extern BOOLEAN AES_CMAC ( BT_OCTET16 key, UINT8 *input, UINT16 length, UINT16 tlen, UINT8 *p_signature);
extern void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable);
extern BOOLEAN smp_proc_ltk_request(BD_ADDR bda);
#endif
-
-static void btm_ble_update_active_bgconn_scan_params(void);
+extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr);
/*******************************************************************************/
/* External Function to be called by other modules */
@@ -114,7 +115,7 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d
{
p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
- (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
+ (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
}
p_dev_rec->device_type = dev_type;
p_dev_rec->ble.ble_addr_type = addr_type;
@@ -158,9 +159,10 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_
p_dev_rec = btm_find_dev (bd_addr);
if (!p_dev_rec || !p_le_key ||
(key_type != BTM_LE_KEY_PENC && key_type != BTM_LE_KEY_PID &&
- key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC))
+ key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC &&
+ key_type != BTM_LE_KEY_LCSRK))
{
- BTM_TRACE_WARNING3 ("BTM_SecAddLeKey() No BT Link Key, Wrong Type, or No Device record \
+ BTM_TRACE_WARNING3 ("BTM_SecAddBleKey() Wrong Type, or No Device record \
for bdaddr: %08x%04x, Type: %d",
(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
(bd_addr[4]<<8)+bd_addr[5], key_type);
@@ -283,29 +285,54 @@ void BTM_GetDeviceDHK (BT_OCTET16 dhk)
**
** Function BTM_ReadConnectionAddr
**
-** Description This function is called to set the local device random address
+** Description This function is called to get the local device address information
** .
**
** Returns void
**
*******************************************************************************/
-void BTM_ReadConnectionAddr (BD_ADDR conn_addr)
+void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr, tBLE_ADDR_TYPE *p_addr_type)
{
#if BLE_INCLUDED == TRUE
- BTM_TRACE_DEBUG0 ("BTM_ReadConnectionAddr");
- if (btm_cb.ble_ctr_cb.inq_var.own_addr_type == BLE_ADDR_PUBLIC)
- {
- BTM_GetLocalDeviceAddr(conn_addr);
- }
- else
+ tACL_CONN *p_acl = btm_bda_to_acl(remote_bda);
+
+ if (p_acl == NULL)
{
- memcpy (conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
+ BTM_TRACE_ERROR0("No connection exist!");
+ return;
}
+ memcpy(local_conn_addr, p_acl->conn_addr, BD_ADDR_LEN);
+ * p_addr_type = p_acl->conn_addr_type;
+
+ BTM_TRACE_DEBUG2 ("BTM_ReadConnectionAddr address type: %d addr: 0x%02x",
+ p_acl->conn_addr_type, p_acl->conn_addr[0]);
+
#endif
}
/*******************************************************************************
**
+** Function BTM_ReadRemoteConnectionAddr
+**
+** Description This function is read the remote device address currently used
+** .
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr, BD_ADDR conn_addr, tBLE_ADDR_TYPE *p_addr_type)
+{
+ BOOLEAN st = TRUE;
+#if BLE_INCLUDED == TRUE
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_addr);
+
+ memcpy(conn_addr, pseudo_addr, BD_ADDR_LEN);
+ *p_addr_type = p_dev_rec->ble.ble_addr_type;
+#endif
+ return st;
+}
+/*******************************************************************************
+**
** Function BTM_SecurityGrant
**
** Description This function is called to grant security process.
@@ -346,6 +373,12 @@ void BTM_BlePasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
tSMP_STATUS res_smp = (res == BTM_SUCCESS) ? SMP_SUCCESS : SMP_PASSKEY_ENTRY_FAIL;
+ if (p_dev_rec == NULL)
+ {
+ BTM_TRACE_ERROR0("Passkey reply to Unknown device");
+ return;
+ }
+
p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
BTM_TRACE_DEBUG0 ("BTM_BlePasskeyReply");
SMP_PasskeyReply(bd_addr, res_smp, passkey);
@@ -371,6 +404,13 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data)
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
BTM_TRACE_DEBUG0 ("BTM_BleOobDataReply");
+
+ if (p_dev_rec == NULL)
+ {
+ BTM_TRACE_ERROR0("BTM_BleOobDataReply() to Unknown device");
+ return;
+ }
+
p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
SMP_OobDataReply(bd_addr, res_smp, len, p_data);
#endif
@@ -411,8 +451,10 @@ void BTM_BleSetConnScanParams (UINT16 scan_interval, UINT16 scan_window)
new_param = TRUE;
}
- if (new_param)
- btm_ble_update_active_bgconn_scan_params();
+ if (new_param && p_ble_cb->conn_state == BLE_BG_CONN)
+ {
+ btm_ble_suspend_bg_conn();
+ }
}
else
{
@@ -452,7 +494,7 @@ void BTM_BleSetPrefConnParams (BD_ADDR bd_addr,
if (BTM_BLE_VALID_PRAM(min_conn_int, BTM_BLE_CONN_INT_MIN, BTM_BLE_CONN_INT_MAX) &&
BTM_BLE_VALID_PRAM(max_conn_int, BTM_BLE_CONN_INT_MIN, BTM_BLE_CONN_INT_MAX) &&
BTM_BLE_VALID_PRAM(supervision_tout, BTM_BLE_CONN_SUP_TOUT_MIN, BTM_BLE_CONN_SUP_TOUT_MAX) &&
- slave_latency <= BTM_BLE_CONN_LATENCY_MAX)
+ (slave_latency <= BTM_BLE_CONN_LATENCY_MAX || slave_latency == BTM_BLE_CONN_PARAM_UNDEF))
{
if (p_dev_rec)
{
@@ -544,41 +586,83 @@ void BTM_ReadDevInfo (BD_ADDR remote_bda, tBT_DEVICE_TYPE *p_dev_type, tBLE_ADDR
return;
}
+/*******************************************************************************
+**
+** Function BTM_BleReceiverTest
+**
+** Description This function is called to start the LE Receiver test
+**
+** Parameter rx_freq - Frequency Range
+** p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+ if (btsnd_hcic_ble_receiver_test(rx_freq) == FALSE)
+ {
+ BTM_TRACE_ERROR1("%s: Unable to Trigger LE receiver test", __FUNCTION__);
+ }
+}
/*******************************************************************************
-** Internal Functions
+**
+** Function BTM_BleTransmitterTest
+**
+** Description This function is called to start the LE Transmitter test
+**
+** Parameter tx_freq - Frequency Range
+** test_data_len - Length in bytes of payload data in each packet
+** packet_payload - Pattern to use in the payload
+** p_cmd_cmpl_cback - Command Complete callback
+**
*******************************************************************************/
-#if BLE_INCLUDED == TRUE
+void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+ UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+ if (btsnd_hcic_ble_transmitter_test(tx_freq, test_data_len, packet_payload) == FALSE)
+ {
+ BTM_TRACE_ERROR1("%s: Unable to Trigger LE transmitter test", __FUNCTION__);
+ }
+}
/*******************************************************************************
**
-** Function btm_ble_update_active_bgconn_scan_params
+** Function BTM_BleTestEnd
+**
+** Description This function is called to stop the in-progress TX or RX test
**
-** Description This function is called to update the scan parameter if background
-** connection has been active.
+** Parameter p_cmd_cmpl_cback - Command complete callback
**
*******************************************************************************/
-static void btm_ble_update_active_bgconn_scan_params(void)
+void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- tBTM_BLE_SEL_CBACK *p_select_cback;
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+ if (btsnd_hcic_ble_test_end() == FALSE)
+ {
+ BTM_TRACE_ERROR1("%s: Unable to End the LE TX/RX test", __FUNCTION__);
+ }
+}
+
+/*******************************************************************************
+** Internal Functions
+*******************************************************************************/
+#if BLE_INCLUDED == TRUE
- /* if active , cancel and restart and apply the params */
- if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
+void btm_ble_test_command_complete(UINT8 *p)
+{
+ tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_le_test_cmd_cmpl_cb;
+ UINT8 status;
+
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = NULL;
+
+ if (p_cb)
{
- if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
- {
- if (btm_ble_start_auto_conn(FALSE))
- btm_ble_start_auto_conn(TRUE);
- }
- else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- p_select_cback = p_cb->p_select_cback;
- if (btm_ble_start_select_conn(FALSE, NULL))
- btm_ble_start_select_conn(TRUE, p_select_cback);
- }
+ (*p_cb)(p);
}
- return;
}
/*******************************************************************************
@@ -643,7 +727,7 @@ void btm_ble_rand_enc_complete (UINT8 *p, UINT16 op_code, tBTM_RAND_ENC_CB *p_en
}
-#if (SMP_INCLUDED == TRUE)
+ #if (SMP_INCLUDED == TRUE)
/*******************************************************************************
**
@@ -744,6 +828,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
{
tBTM_SEC_DEV_REC *p_rec;
tBTM_LE_EVT_DATA cb_data;
+ UINT8 i;
BTM_TRACE_DEBUG2 ("btm_sec_save_le_key key_type=0x%x pass_to_application=%d",key_type, pass_to_application);
/* Store the updated key in the device database */
@@ -776,7 +861,14 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
break;
case BTM_LE_KEY_PID:
- memcpy(p_rec->ble.keys.irk, p_keys->pid_key, BT_OCTET16_LEN);
+ for (i=0; i<BT_OCTET16_LEN; i++)
+ {
+ p_rec->ble.keys.irk[i] = p_keys->pid_key.irk[i];
+ }
+
+ //memcpy( p_rec->ble.keys.irk, p_keys->pid_key, BT_OCTET16_LEN); todo will crash the system
+ memcpy(p_rec->ble.static_addr, p_keys->pid_key.static_addr, BD_ADDR_LEN);
+ p_rec->ble.static_addr_type = p_keys->pid_key.addr_type;
p_rec->ble.key_type |= BTM_LE_KEY_PID;
BTM_TRACE_DEBUG1("BTM_LE_KEY_PID key_type=0x%x save peer IRK", p_rec->ble.key_type);
break;
@@ -839,7 +931,6 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
{
cb_data.key.p_key_value = p_keys;
cb_data.key.key_type = key_type;
-
(*btm_cb.api.p_le_callback) (BTM_LE_KEY_EVT, bd_addr, &cb_data);
}
return;
@@ -919,7 +1010,8 @@ void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE
return;
}
- if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING)
+ if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+ p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
{
/* race condition: discard the security request while master is encrypting the link */
*p_sec_req_act = BTM_BLE_SEC_REQ_ACT_DISCARD;
@@ -960,12 +1052,13 @@ void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE
}
else
{
- /* To avoid re-encryption on an encrypted link for an equal condition encryption
+ /* To avoid re-encryption on an encrypted link for an equal condition encryption */
+ /* if link has been encrypted, do nothing, go straight to furhter action
if (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)
*p_sec_req_act = BTM_BLE_SEC_REQ_ACT_DISCARD;
else
*/
- *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_ENCRYPT;
+ *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_ENCRYPT;
}
}
else
@@ -1000,13 +1093,14 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin
tBTM_BLE_SEC_ACT sec_act = *(tBTM_BLE_SEC_ACT *)p_ref_data ;
tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
- BTM_TRACE_DEBUG2 ("btm_ble_set_encryption sec_act=0x%x role_master=%d", sec_act, p_rec->role_master);
-
if (p_rec == NULL)
{
+ BTM_TRACE_WARNING1 ("btm_ble_set_encryption (NULL device record!! sec_act=0x%x", sec_act);
return(BTM_WRONG_MODE);
}
+ BTM_TRACE_DEBUG2 ("btm_ble_set_encryption sec_act=0x%x role_master=%d", sec_act, p_rec->role_master);
+
if (sec_act == BTM_BLE_SEC_ENCRYPT_MITM)
{
p_rec->security_required |= BTM_SEC_IN_MITM;
@@ -1018,9 +1112,11 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin
if (link_role == BTM_ROLE_MASTER)
{
/* start link layer encryption using the security info stored */
- btm_ble_start_encrypt(bd_addr, FALSE, NULL);
- p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
- cmd = BTM_CMD_STARTED;
+ if (btm_ble_start_encrypt(bd_addr, FALSE, NULL))
+ {
+ p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
+ cmd = BTM_CMD_STARTED;
+ }
break;
}
/* if salve role then fall through to call SMP_Pair below which will send a
@@ -1123,30 +1219,36 @@ BOOLEAN btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk)
void btm_ble_link_encrypted(BD_ADDR bd_addr, UINT8 encr_enable)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+ BOOLEAN enc_cback;
+
+ if (!p_dev_rec)
+ {
+ BTM_TRACE_WARNING1 ("btm_ble_link_encrypted (No Device Found!) encr_enable=%d", encr_enable);
+ return;
+ }
BTM_TRACE_DEBUG1 ("btm_ble_link_encrypted encr_enable=%d", encr_enable);
+ enc_cback = (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING);
+
smp_link_encrypted(bd_addr, encr_enable);
- if (p_dev_rec)
- {
- BTM_TRACE_DEBUG1(" p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
+ BTM_TRACE_DEBUG1(" p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
- if (encr_enable && p_dev_rec->enc_key_size == 0)
- p_dev_rec->enc_key_size = p_dev_rec->ble.keys.key_size;
+ if (encr_enable && p_dev_rec->enc_key_size == 0)
+ p_dev_rec->enc_key_size = p_dev_rec->ble.keys.key_size;
+
+ p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+ if (p_dev_rec->p_callback && enc_cback)
+ {
+ if (encr_enable)
+ btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS);
+ else if (p_dev_rec->role_master)
+ btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING);
- if (p_dev_rec->p_callback)
- {
- if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING)
- {
- if (encr_enable)
- btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS);
- else if (p_dev_rec->role_master)
- btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING);
- }
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
}
+ /* to notify GATT to send data if any request is pending */
+ gatt_notify_enc_cmpl(p_dev_rec->bd_addr);
}
/*******************************************************************************
@@ -1186,7 +1288,7 @@ static void btm_enc_proc_slave_y(tSMP_ENC *p)
p_dev_rec = btm_find_dev_by_handle (p_cb->enc_handle);
if ( p_dev_rec &&
- p_dev_rec->ble.keys.div == div )
+ p_dev_rec->ble.keys.div == div )
{
BTM_TRACE_DEBUG0 ("LTK request OK");
/* calculating LTK , LTK = E er(div) */
@@ -1305,6 +1407,110 @@ UINT8 btm_ble_io_capabilities_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p
return callback_rc;
}
+/*******************************************************************************
+**
+** Function btm_ble_connected
+**
+** Description This function is when a LE connection to the peer device is
+** establsihed
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role,
+ tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+
+ BTM_TRACE_EVENT0 ("btm_ble_connected");
+
+ /* Commenting out trace due to obf/compilation problems.
+ */
+#if (BT_USE_TRACES == TRUE)
+ if (p_dev_rec)
+ {
+ BTM_TRACE_EVENT4 ("Security Manager: btm_sec_connected : handle:%d enc_mode:%d bda:%x RName:%s",
+ handle, enc_mode,
+ (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5],
+ p_dev_rec->sec_bd_name);
+
+ BTM_TRACE_DEBUG1 ("btm_ble_connected sec_flags=0x%x",p_dev_rec->sec_flags);
+ }
+ else
+ {
+ BTM_TRACE_EVENT3 ("Security Manager: btm_sec_connected: handle:%d enc_mode:%d bda:%x ",
+ handle, enc_mode,
+ (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5]);
+ }
+#endif
+
+ if (!p_dev_rec)
+ {
+ /* There is no device record for new connection. Allocate one */
+ p_dev_rec = btm_sec_alloc_dev (bda);
+ }
+ else /* Update the timestamp for this device */
+ {
+ p_dev_rec->timestamp = btm_cb.dev_rec_count++;
+ }
+
+ /* update device information */
+ p_dev_rec->device_type |= BT_DEVICE_TYPE_BLE;
+ p_dev_rec->hci_handle = handle;
+ p_dev_rec->ble.ble_addr_type = addr_type;
+
+ if (role == HCI_ROLE_MASTER)
+ p_dev_rec->role_master = TRUE;
+
+ if (role == HCI_ROLE_SLAVE)
+ p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+ p_cb->inq_var.directed_conn = FALSE;
+
+ return;
+}
+
+/*****************************************************************************
+** Function btm_ble_conn_complete
+**
+** Description LE connection complete.
+**
+******************************************************************************/
+void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
+{
+ UINT8 role, status, bda_type;
+ UINT16 handle;
+ BD_ADDR bda;
+ UINT16 conn_interval, conn_latency, conn_timeout;
+ BOOLEAN match = FALSE;
+
+ STREAM_TO_UINT8 (status, p);
+ STREAM_TO_UINT16 (handle, p);
+ STREAM_TO_UINT8 (role, p);
+ STREAM_TO_UINT8 (bda_type, p);
+ STREAM_TO_BDADDR (bda, p);
+
+ if (status == 0)
+ {
+ STREAM_TO_UINT16 (conn_interval, p);
+ STREAM_TO_UINT16 (conn_latency, p);
+ STREAM_TO_UINT16 (conn_timeout, p);
+ handle = HCID_GET_HANDLE (handle);
+
+ btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type, match);
+ l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
+ conn_latency, conn_timeout);
+ }
+ else
+ {
+ role = HCI_ROLE_UNKNOWN;
+
+ if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+ btm_ble_dir_adv_tout();
+ }
+ btm_ble_update_mode_operation(role, bda, TRUE);
+}
+
/*****************************************************************************
** Function btm_proc_smp_cback
**
@@ -1314,7 +1520,7 @@ UINT8 btm_ble_io_capabilities_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p
UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
- UINT8 res;
+ UINT8 res = 0;
BTM_TRACE_DEBUG1 ("btm_proc_smp_cback event = %d", event);
@@ -1336,11 +1542,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
{
/* the callback function implementation may change the IO capability... */
BTM_TRACE_DEBUG1 ("btm_cb.api.p_le_callback=0x%x", btm_cb.api.p_le_callback );
- (*btm_cb.api.p_le_callback) (event, bd_addr, (tBTM_LE_EVT_DATA *)p_data);
- }
- else
- {
- BTM_TRACE_ERROR0 ("btm_proc_smp_cback: btm_cb.api.p_le_callback ==NULL");
+ (*btm_cb.api.p_le_callback) (event, bd_addr, (tBTM_LE_EVT_DATA *)p_data);
}
if (event == SMP_COMPLT_EVT)
@@ -1370,7 +1572,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
else
{
BTM_TRACE_DEBUG0 ("Pairing failed - Not Removing ACL");
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+ p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
}
}
#else
@@ -1406,7 +1608,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
return 0;
}
-#endif /* SMP_INCLUDED */
+ #endif /* SMP_INCLUDED */
#endif /* BLE_INCLUDED */
@@ -1548,7 +1750,7 @@ BOOLEAN BTM_BleDataSignature (BD_ADDR bd_addr, UINT8 *p_text, UINT16 len,
**
*******************************************************************************/
BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT32 counter,
- UINT8 *p_comp)
+ UINT8 *p_comp)
{
BOOLEAN verified = FALSE;
#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
@@ -1844,7 +2046,7 @@ void btm_ble_reset_id( void )
}
}
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
+ #if BTM_BLE_CONFORMANCE_TESTING == TRUE
/*******************************************************************************
**
** Function btm_ble_set_no_disc_if_pair_fail
@@ -1894,6 +2096,33 @@ void btm_ble_set_test_local_sign_cntr_value(BOOLEAN enable, UINT32 test_local_si
btm_cb.devcb.test_local_sign_cntr = test_local_sign_cntr;
}
+/*******************************************************************************
+**
+** Function btm_set_random_address
+**
+** Description This function set a random address to local controller.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_set_random_address(BD_ADDR random_bda)
+{
+ tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+ BOOLEAN adv_mode = btm_cb.ble_ctr_cb.inq_var.adv_mode ;
+
+ BTM_TRACE_DEBUG0 ("btm_set_random_address");
+
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
+
+ memcpy(p_cb->private_addr, random_bda, BD_ADDR_LEN);
+ btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE);
+
+
+}
#endif /* BTM_BLE_CONFORMANCE_TESTING */
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index 04872f919..9ae37f957 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -28,11 +28,13 @@
#include "hcimsgs.h"
#include "btu.h"
#include "btm_int.h"
-
+#include "btm_ble_int.h"
+#include "gap_api.h"
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
- #include "smp_api.h"
- #define BTM_BLE_PRIVATE_ADDR_INT 900 /* 15 minutes minimum for random address refreshing */
+#include "smp_api.h"
+#define BTM_BLE_PRIVATE_ADDR_INT 900 /* 15 minutes minimum for
+ random address refreshing */
/*******************************************************************************
**
@@ -47,42 +49,24 @@
static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p)
{
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
- tBTM_BLE_INQ_CB *p_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
BTM_TRACE_EVENT0 ("btm_gen_resolve_paddr_cmpl");
- if (p && p->param_buf)
+
+ if (p)
{
- /* get the high bytes of the random address */
- p_cb->private_addr[2] = p->param_buf[0];
- p_cb->private_addr[1] = p->param_buf[1];
- p_cb->private_addr[0] = p->param_buf[2];
- /* mask off the 1st MSB */
- p_cb->private_addr[0] &= 0xfe;
- /* set the 2nd MSB to be 1 */
- p_cb->private_addr[0] |= 0x02;
+ /* set hash to be LSB of rpAddress */
+ p_cb->private_addr[5] = p->param_buf[0];
+ p_cb->private_addr[4] = p->param_buf[1];
+ p_cb->private_addr[3] = p->param_buf[2];
/* set it to controller */
btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
- p_inq_cb->own_addr_type = BLE_ADDR_RANDOM;
+ p_cb->own_addr_type = BLE_ADDR_RANDOM;
/* start a periodical timer to refresh random addr */
btu_stop_timer(&p_cb->raddr_timer_ent);
btu_start_timer (&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
BTM_BLE_PRIVATE_ADDR_INT);
- /* if adv is active, restart adv with new private addr */
- if (p_inq_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
-
- btsnd_hcic_ble_write_adv_params (p_inq_cb->adv_interval_min,
- p_inq_cb->adv_interval_max,
- p_inq_cb->evt_type,
- p_inq_cb->own_addr_type,
- p_inq_cb->direct_bda.type,
- p_inq_cb->direct_bda.bda,
- p_inq_cb->adv_chnl_map,
- p_inq_cb->afp);
- }
}
else
{
@@ -107,11 +91,14 @@ static void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p)
tSMP_ENC output;
BTM_TRACE_EVENT0 ("btm_gen_resolve_paddr_low");
- if (p && p->param_buf)
+ if (p)
{
- p_cb->private_addr[5] = p->param_buf[0];
- p_cb->private_addr[4] = p->param_buf[1];
- p_cb->private_addr[3] = p->param_buf[2];
+ p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
+ p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
+
+ p_cb->private_addr[2] = p->param_buf[0];
+ p_cb->private_addr[1] = p->param_buf[1];
+ p_cb->private_addr[0] = p->param_buf[2];
/* encrypt with ur IRK */
if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output))
@@ -154,22 +141,31 @@ void btm_gen_resolvable_private_addr (void)
static void btm_gen_non_resolve_paddr_cmpl(tBTM_RAND_ENC *p)
{
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+ tBTM_BLE_ADDR_CBACK *p_cback = p_cb->p_generate_cback;
+ void *p_data = p_cb->p;
UINT8 *pp;
+ BD_ADDR static_random;
+
BTM_TRACE_EVENT0 ("btm_gen_non_resolve_paddr_cmpl");
- if (p && p->param_buf)
+
+ p_cb->p_generate_cback = NULL;
+ if (p)
{
+
pp = p->param_buf;
- STREAM_TO_BDADDR(p_cb->private_addr, pp);
+ STREAM_TO_BDADDR(static_random, pp);
/* mask off the 2 MSB */
- p_cb->private_addr[0] &= 0xfc;
- /* write to controller */
- btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+ static_random[0] &= BLE_STATIC_PRIVATE_MSB_MASK;
- btm_cb.ble_ctr_cb.inq_var.own_addr_type = BLE_ADDR_RANDOM;
+ /* report complete */
+ if (p_cback)
+ (* p_cback)(static_random, p_data);
}
else
{
BTM_TRACE_DEBUG0("btm_gen_non_resolvable_private_addr failed");
+ if (p_cback)
+ (* p_cback)(NULL, p_data);
}
}
/*******************************************************************************
@@ -182,13 +178,22 @@ static void btm_gen_non_resolve_paddr_cmpl(tBTM_RAND_ENC *p)
** Returns void
**
*******************************************************************************/
-void btm_gen_non_resolvable_private_addr (void)
+void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p)
{
+ tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+
BTM_TRACE_EVENT0 ("btm_gen_non_resolvable_private_addr");
+
+ if (p_mgnt_cb->p_generate_cback != NULL)
+ return;
+
+ p_mgnt_cb->p_generate_cback = p_cback;
+ p_mgnt_cb->p = p;
if (!btsnd_hcic_ble_rand((void *)btm_gen_non_resolve_paddr_cmpl))
{
btm_gen_non_resolve_paddr_cmpl(NULL);
}
+
}
#if SMP_INCLUDED == TRUE
/*******************************************************************************
@@ -209,9 +214,12 @@ static void btm_ble_resolve_address_cmpl(void)
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
- BTM_TRACE_EVENT0 ("btm_ble_resolve_address_cmpl");
+ BTM_TRACE_EVENT1 ("btm_ble_resolve_address_cmpl p_mgnt_cb->index = %d", p_mgnt_cb->index);
+
if (p_mgnt_cb->index < BTM_SEC_MAX_DEVICE_RECORDS)
+ {
p_dev_rec = &btm_cb.sec_dev_rec[p_mgnt_cb->index];
+ }
p_mgnt_cb->busy = FALSE;
@@ -237,7 +245,7 @@ static BOOLEAN btm_ble_proc_resolve_x(tSMP_ENC *p)
comp[1] = p_mgnt_cb->random_bda[4];
comp[2] = p_mgnt_cb->random_bda[3];
- if (p && p->param_buf)
+ if (p)
{
if (!memcmp(p->param_buf, &comp[0], 3))
{
@@ -329,11 +337,12 @@ void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_
/* check for next security record */
while (TRUE)
{
- if (btm_ble_match_random_bda(p_mgnt_cb->index++))
+ if (btm_ble_match_random_bda(p_mgnt_cb->index))
{
- // match found or went through the list
+ /* atch found or went through the list */
break;
}
+ p_mgnt_cb->index ++;
}
}
else
@@ -366,18 +375,7 @@ tBLE_ADDR_TYPE btm_ble_map_bda_to_conn_bda(BD_ADDR bd_addr)
else
return BLE_ADDR_PUBLIC;
}
-/*******************************************************************************
-**
-** Function btm_ble_map_bda_to_pseudo_bda
-**
-** Description This function map a BD address to a pseudo address when the
-** address given is a random address.
-**
-*******************************************************************************/
-void btm_ble_map_bda_to_pseudo_bda(BD_ADDR bd_addr)
-{
- BTM_TRACE_EVENT0 ("btm_ble_map_bda_to_pseudo_bda");
-}
+
#endif
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index aa002e8ef..3b8b1e2ff 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -30,11 +30,16 @@
#include "l2c_int.h"
#include "hcimsgs.h"
+
#ifndef BTM_BLE_SCAN_PARAM_TOUT
#define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */
#endif
#if (BLE_INCLUDED == TRUE)
+
+static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state);
+static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state);
+
/*******************************************************************************
**
** Function btm_update_scanner_filter_policy
@@ -45,9 +50,11 @@ void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy)
{
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
BTM_TRACE_EVENT0 ("btm_update_scanner_filter_policy");
- btm_cb.ble_ctr_cb.inq_var.sfp = scan_policy;
- btsnd_hcic_ble_set_scan_params ((UINT8)((p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type),
+ p_inq->sfp = scan_policy;
+ p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
+
+ btsnd_hcic_ble_set_scan_params (p_inq->scan_type,
(UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval),
(UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window),
BLE_ADDR_PUBLIC,
@@ -55,88 +62,68 @@ void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy)
}
/*******************************************************************************
**
-** Function btm_update_adv_filter_policy
-**
-** Description This function update the filter policy of scnner or advertiser.
-*******************************************************************************/
-void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy)
-{
- tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
- BTM_TRACE_EVENT0 ("btm_update_adv_filter_policy");
- p_cb->afp = adv_policy;
-}
-/*******************************************************************************
-**
** Function btm_update_dev_to_white_list
**
** Description This function adds a device into white list.
*******************************************************************************/
-BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type)
+BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr)
{
/* look up the sec device record, and find the address */
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- tBTM_SEC_DEV_REC *p_dev_rec;
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
BD_ADDR dummy_bda = {0};
- BOOLEAN started = FALSE, suspend = FALSE;
+ BOOLEAN started = FALSE;
+ UINT8 wl_state = p_cb->wl_state;
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC;
- if (btm_cb.btm_inq_vars.inq_active)
+ if ((to_add && p_cb->num_empty_filter == 0) ||
+ (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
{
- suspend = TRUE;
- btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+ BTM_TRACE_ERROR1("WL full or empty, unable to update to WL. num_entry available: %d", p_cb->num_empty_filter);
+ return started;
}
- if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL &&
+ btm_suspend_wl_activity(wl_state);
+
+ if (p_dev_rec != NULL &&
p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
{
- BTM_TRACE_DEBUG0("btm_update_dev_to_white_list 1");
-
- if ((to_add && p_cb->num_empty_filter == 0) ||
- (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
- {
- BTM_TRACE_ERROR1("num_entry available in controller: %d", p_cb->num_empty_filter);
- return started;
- }
-
- if ( p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC)
+ if (to_add)
{
- if (to_add)
- started = btsnd_hcic_ble_add_white_list (BLE_ADDR_PUBLIC, bd_addr);
- else
- started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_PUBLIC, bd_addr);
+ if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
+ {
+ started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
+ }
+ if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
+ memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
+ {
+ started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
+ }
}
else
{
- if (BLE_ADDR_IS_STATIC(bd_addr))
+ if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
{
- if (to_add)
- started = btsnd_hcic_ble_add_white_list (BLE_ADDR_RANDOM, bd_addr);
- else
- started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_RANDOM, bd_addr);
-
+ started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
}
- if (memcmp(p_dev_rec->ble.reconn_addr, dummy_bda, BD_ADDR_LEN) != 0)
+ if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
{
- if (to_add)
- started = btsnd_hcic_ble_add_white_list (BLE_ADDR_RANDOM, p_dev_rec->ble.reconn_addr);
- else
- started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_RANDOM, p_dev_rec->ble.reconn_addr);
+ started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
}
}
- }
- /* if not a known device, shall we add it? */
+ } /* if not a known device, shall we add it? */
else
{
+ BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
if (to_add)
started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
else
started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
}
- if (suspend)
- {
- btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE);
- }
+ btm_resume_wl_activity(wl_state);
return started;
}
@@ -175,12 +162,12 @@ void btm_ble_clear_white_list_complete(UINT8 *p_data, UINT16 evt_len)
**
** Description This function read the current white list size.
*******************************************************************************/
-void btm_ble_add_2_white_list_complete(UINT8 *p, UINT16 evt_len)
+void btm_ble_add_2_white_list_complete(UINT8 status)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
BTM_TRACE_EVENT0 ("btm_ble_add_2_white_list_complete");
- if (*p == HCI_SUCCESS)
+ if (status == HCI_SUCCESS)
{
p_cb->num_empty_filter --;
}
@@ -202,54 +189,25 @@ void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len)
}
/*******************************************************************************
**
-** Function btm_ble_find_dev_in_whitelist
-**
-** Description This function check if the device is in the white list
-*******************************************************************************/
-BOOLEAN btm_ble_find_dev_in_whitelist(BD_ADDR bd_addr)
-{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 i;
-
- BTM_TRACE_EVENT0 ("btm_ble_find_dev_in_whitelist");
-
- /* empty wl */
- if (p_cb->num_empty_filter == p_cb->max_filter_entries)
- {
- BTM_TRACE_DEBUG0("white list empty");
- return FALSE;
- }
-
- for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
- {
- if (memcmp(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN) == 0)
- return TRUE;
- }
- return FALSE;
-}
-/*******************************************************************************
-**
** Function btm_ble_count_unconn_dev_in_whitelist
**
-** Description This function check the number of unconnected device in white list.
+** Description This function find the number of un-connected background device
*******************************************************************************/
UINT8 btm_ble_count_unconn_dev_in_whitelist(void)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 count = 0, i;
- BD_ADDR dummy_bda ={0};
-
- BTM_TRACE_EVENT0 ("btm_ble_find_dev_in_whitelist");
+ UINT8 i, count = 0;
- for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
+ for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++)
{
- if (memcmp(p_cb->bg_conn_dev_list[i], dummy_bda, BD_ADDR_LEN) != 0 &&
- !BTM_IsAclConnectionUp(p_cb->bg_conn_dev_list[i]))
+ if (p_cb->bg_dev_list[i].in_use &&
+ !BTM_IsAclConnectionUp(p_cb->bg_dev_list[i].bd_addr))
{
count ++;
}
}
return count;
+
}
/*******************************************************************************
**
@@ -257,59 +215,63 @@ UINT8 btm_ble_count_unconn_dev_in_whitelist(void)
**
** Description This function update the local background connection device list.
*******************************************************************************/
-BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr)
+BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 i;
- BD_ADDR dummy_bda = {0};
+ UINT8 white_list_type = *p_attr_tag;
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+ tBTM_LE_BG_CONN_DEV *p_bg_dev = &p_cb->bg_dev_list[0], *p_next, *p_cur;
+ UINT8 i, j;
+ BOOLEAN ret = FALSE;
+
BTM_TRACE_EVENT0 ("btm_update_bg_conn_list");
- if ((to_add && (p_cb->bg_conn_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0)) ||
- (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
+
+ if ((to_add && (p_cb->bg_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0)))
{
BTM_TRACE_DEBUG1("num_empty_filter = %d", p_cb->num_empty_filter);
- return FALSE;
+ return ret;
}
- for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
+ for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++)
{
- /* to add */
- if (memcmp(p_cb->bg_conn_dev_list[i], dummy_bda, BD_ADDR_LEN) == 0 && to_add)
+ if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0)
{
- memcpy(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN);
- p_cb->bg_conn_dev_num ++;
- return TRUE;
+ if (to_add)
+ p_bg_dev->attr |= white_list_type;
+ else
+ p_bg_dev->attr &= ~white_list_type;
+
+ if (p_bg_dev->attr == 0)
+ {
+ memset(p_bg_dev, 0, sizeof(tBTM_LE_BG_CONN_DEV));
+ p_cb->bg_dev_num --;
+ p_cur = p_bg_dev;
+ p_next = p_bg_dev + 1;
+ for (j = i + 1 ;j < BTM_BLE_MAX_BG_CONN_DEV_NUM && p_next->in_use ; j ++, p_cur ++, p_next ++ )
+ memcpy(p_cur, p_next, sizeof(tBTM_LE_BG_CONN_DEV));
+ }
+ ret = TRUE;
+ break;
}
- /* to remove */
- if (!to_add && memcmp(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN) == 0)
+ else if (!p_bg_dev->in_use && to_add)
{
- memset(p_cb->bg_conn_dev_list[i], 0, BD_ADDR_LEN);
- p_cb->bg_conn_dev_num --;
- return TRUE;
- }
- }
- return FALSE;
-}
-/*******************************************************************************
-**
-** Function btm_write_bg_conn_wl
-**
-** Description This function write background connection device list into
-** controller.
-*******************************************************************************/
-void btm_write_bg_conn_wl(void)
-{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 i;
- BTM_TRACE_EVENT0 ("btm_write_bg_conn_wl");
- btm_ble_clear_white_list();
+ BTM_TRACE_DEBUG0("add new WL entry in bg_dev_list");
- for (i = 0; i < p_cb->bg_conn_dev_num; i ++)
- {
- if (!btm_update_dev_to_white_list(TRUE, p_cb->bg_conn_dev_list[i], BLE_ADDR_PUBLIC))
+ memcpy(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN);
+ p_bg_dev->in_use = TRUE;
+ p_bg_dev->attr |= white_list_type;
+ p_cb->bg_dev_num ++;
+
+ ret = TRUE;
break;
+ }
}
- return;
+
+ if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM)
+ *p_attr_tag = p_bg_dev->attr;
+
+ return ret;
}
+
/*******************************************************************************
**
** Function btm_ble_start_auto_conn
@@ -326,51 +288,58 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start)
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
BD_ADDR dummy_bda = {0};
BOOLEAN exec = TRUE;
+ UINT8 own_addr_type = BLE_ADDR_PUBLIC;
UINT16 scan_int, scan_win;
- scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_INT : p_cb->scan_int;
- scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_WIND : p_cb->scan_win;
-
if (start)
{
- if (!l2cb.is_ble_connecting &&
- btm_ble_count_unconn_dev_in_whitelist() > 0)
+ if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
{
- if (p_cb->bg_conn_state != BLE_BG_CONN_ACTIVE && p_cb->bg_conn_dev_num > 0)
+
+ scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
+ scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
+
+ if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */
+ scan_win, /* UINT16 scan_win */
+ 0x01, /* UINT8 white_list */
+ BLE_ADDR_PUBLIC, /* UINT8 addr_type_peer */
+ dummy_bda, /* BD_ADDR bda_peer */
+ own_addr_type, /* UINT8 addr_type_own, not allow random address for central */
+ BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */
+ BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */
+ BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */
+ BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */
+ 0, /* UINT16 min_len */
+ 0)) /* UINT16 max_len */
+ {
+ /* start auto connection failed */
+ exec = FALSE;
+ }
+ else
{
- if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */
- scan_win, /* UINT16 scan_win */
- 0x01, /* UINT8 white_list */
- BLE_ADDR_PUBLIC, /* UINT8 addr_type_peer */
- dummy_bda, /* BD_ADDR bda_peer */
- BLE_ADDR_PUBLIC, /* UINT8 addr_type_own */
- BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */
- BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */
- BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */
- BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */
- 0, /* UINT16 min_len */
- 0)) /* UINT16 max_len */
- {
- /* start auto connection failed */
- exec = FALSE;
- }
- else
- {
- p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
- }
+ p_cb->conn_state = BLE_BG_CONN;
+
}
}
else
+ {
exec = FALSE;
+ }
}
else
{
- if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
+ if (p_cb->conn_state == BLE_BG_CONN)
{
- if (!btsnd_hcic_ble_create_conn_cancel())
- exec = FALSE;
- else
- p_cb->bg_conn_state = BLE_BG_CONN_IDLE;
+ btsnd_hcic_ble_create_conn_cancel();
+ p_cb->conn_state = BLE_CONN_IDLE;
+
+ }
+ else
+ {
+#if 0
+ BTM_TRACE_ERROR1("conn_st = %d, not in auto conn state, can not stop.", p_cb->conn_state);
+ exec = FALSE;
+#endif
}
}
return exec;
@@ -396,16 +365,18 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_c
BTM_TRACE_EVENT0 ("btm_ble_start_select_conn");
- scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_INT : p_cb->scan_int;
- scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_WIND : p_cb->scan_win;
+ scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
+ scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
if (start)
{
- if (!btm_cb.btm_inq_vars.inq_active)
+ if (btm_cb.btm_inq_vars.inq_active == BTM_INQUIRY_INACTIVE)
{
- btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
+ if (p_select_cback != NULL)
+ btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
btm_update_scanner_filter_policy(SP_ADV_WL);
+ btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;
if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS, /* use passive scan by default */
scan_int, /* scan interval */
@@ -415,23 +386,22 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_c
)
return FALSE;
- if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE)
+ if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE
+ )
{
BTM_TRACE_ERROR0("peripheral device cannot initiate a selective connection");
return FALSE;
}
- else if (p_cb->bg_conn_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
+ else if (p_cb->bg_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
{
if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
return FALSE;
/* mark up inquiry status flag */
- btm_cb.btm_inq_vars.inq_active = TRUE;
- btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_SELECT_SCAN;
-
- p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
-
+ btm_cb.btm_inq_vars.inq_active |= BTM_LE_SELECT_CONN_ACTIVE;
+ p_cb->inq_var.proc_mode = BTM_BLE_SELECT_SCAN;
+ p_cb->conn_state = BLE_BG_CONN;
}
}
else
@@ -442,14 +412,12 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_c
}
else /* disable selective connection mode */
{
- p_cb->p_select_cback = NULL;
- btm_cb.btm_inq_vars.inq_active = FALSE;
+ btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_SELECT_CONN_ACTIVE;
btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
btm_update_scanner_filter_policy(SP_ADV_ALL);
-
/* stop scanning */
- if (p_cb->bg_conn_dev_num > 0)
+ if (p_cb->bg_dev_num > 0)
{
if (!btsnd_hcic_ble_set_scan_enable(FALSE, TRUE)) /* duplicate filtering enabled */
return FALSE;
@@ -472,9 +440,7 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_c
*******************************************************************************/
void btm_ble_initiate_select_conn(BD_ADDR bda)
{
- UINT8 addr_type;
BTM_TRACE_EVENT0 ("btm_ble_initiate_select_conn");
- addr_type = btm_ble_map_bda_to_conn_bda(bda);
/* use direct connection procedure to initiate connection */
if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda))
@@ -484,7 +450,7 @@ void btm_ble_initiate_select_conn(BD_ADDR bda)
}
/*******************************************************************************
**
-** Function btm_ble_suspend_bg_sele_conn
+** Function btm_ble_suspend_bg_conn
**
** Description This function is to suspend an active background connection
** procedure.
@@ -494,50 +460,63 @@ void btm_ble_initiate_select_conn(BD_ADDR bda)
** Returns none.
**
*******************************************************************************/
-void btm_ble_suspend_bg_sele_conn(void)
+void btm_ble_suspend_bg_conn(void)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- BTM_TRACE_EVENT0 ("btm_ble_suspend_bg_sele_conn");
+ BTM_TRACE_EVENT0 ("btm_ble_suspend_bg_conn");
- if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
+ if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
+ {
+ btm_ble_start_auto_conn(FALSE);
+ }
+ else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
{
- p_cb->bg_conn_state = BLE_BG_CONN_SUSPEND;
btm_ble_start_select_conn(FALSE, NULL);
}
}
/*******************************************************************************
**
-** Function btm_ble_suspend_bg_conn
-**
-** Description This function is to suspend an active background connection
-** procedure.
+** Function btm_suspend_wl_activity
**
-** Parameters none.
+** Description This function is to suspend white list related activity
**
** Returns none.
**
*******************************************************************************/
-void btm_ble_suspend_bg_conn(void)
+static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- BTM_TRACE_EVENT0 ("btm_ble_suspend_bg_conn");
-
- if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
+ if (wl_state & BTM_BLE_WL_INIT)
+ {
+ btm_ble_start_auto_conn(FALSE);
+ }
+ if (wl_state & BTM_BLE_WL_SCAN)
{
- if (btm_ble_start_auto_conn(FALSE))
- p_cb->bg_conn_state = BLE_BG_CONN_SUSPEND;
+ btm_ble_start_select_conn(FALSE, NULL);
}
+ if (wl_state & BTM_BLE_WL_ADV)
+ {
+ btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_DISABLE);
+ }
+
}
/*******************************************************************************
**
-** Function btm_ble_scan_param_idle
+** Function btm_resume_wl_activity
**
-** Description This function is to process the scan parameter idle timeout
-** timeout.
-********************************************************************************/
-void btm_ble_scan_param_idle(void)
+** Description This function is to resume white list related activity
+**
+** Returns none.
+**
+*******************************************************************************/
+static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state)
{
- BTM_BleSetConnScanParams(BTM_BLE_CONN_EST_SCAN_INT_LO, BTM_BLE_CONN_EST_SCAN_WIND_LO);
+ btm_ble_resume_bg_conn();
+
+ if (wl_state & BTM_BLE_WL_ADV)
+ {
+ btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_ENABLE);
+ }
+
}
/*******************************************************************************
**
@@ -551,66 +530,91 @@ void btm_ble_scan_param_idle(void)
** Returns none.
**
*******************************************************************************/
-BOOLEAN btm_ble_resume_bg_conn(tBTM_BLE_SEL_CBACK *p_sele_callback, BOOLEAN def_param)
+BOOLEAN btm_ble_resume_bg_conn(void)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
BOOLEAN ret = FALSE;
- if (p_cb->bg_conn_state != BLE_BG_CONN_ACTIVE )
+ if (p_cb->bg_conn_type != BTM_BLE_CONN_NONE)
{
- if (def_param)
- {
- p_cb->scan_int = BTM_BLE_CONN_PARAM_UNDEF;
- p_cb->scan_win = BTM_BLE_CONN_PARAM_UNDEF;
-
- /* start scan param idle timer */
- btu_start_timer(&p_cb->scan_param_idle_timer,
- BTU_TTYPE_BLE_SCAN_PARAM_IDLE,
- BTM_BLE_SCAN_PARAM_TOUT);
- }
-
if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
ret = btm_ble_start_auto_conn(TRUE);
if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- /* terminate selective connection mode if all devices are connected */
- if (btm_ble_count_unconn_dev_in_whitelist() == 0)
- {
- btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_DISABLE);
- btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
- btm_cb.btm_inq_vars.inq_active = FALSE;
- }
- else if (!btm_cb.btm_inq_vars.inq_active)
- btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
- }
-
- if (ret)
- p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
-
+ ret = btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
}
return ret;
}
/*******************************************************************************
**
-** Function btm_ble_update_bg_state
+** Function btm_ble_get_conn_st
**
-** Description This function is to update the bg connection status.
+** Description This function get BLE connection state
**
-** Parameters none.
+** Returns connection state
**
-** Returns none.
+*******************************************************************************/
+tBTM_BLE_CONN_ST btm_ble_get_conn_st(void)
+{
+ return btm_cb.ble_ctr_cb.conn_state;
+}
+/*******************************************************************************
+**
+** Function btm_ble_set_conn_st
+**
+** Description This function set BLE connection state
+**
+** Returns None.
**
*******************************************************************************/
-void btm_ble_update_bg_state(void)
+void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+ btm_cb.ble_ctr_cb.conn_state = new_st;
+}
- if (!l2cb.is_ble_connecting && (p_cb->bg_conn_state != BLE_BG_CONN_SUSPEND))
- p_cb->bg_conn_state = BLE_BG_CONN_IDLE;
+/*******************************************************************************
+**
+** Function btm_ble_enqueue_direct_conn_req
+**
+** Description This function enqueue the direct connection request
+**
+** Returns None.
+**
+*******************************************************************************/
+void btm_ble_enqueue_direct_conn_req(void *p_param)
+{
+ tBTM_BLE_CONN_REQ *p = (tBTM_BLE_CONN_REQ *)GKI_getbuf(sizeof(tBTM_BLE_CONN_REQ));
+ p->p_param = p_param;
+
+ GKI_enqueue (&btm_cb.ble_ctr_cb.conn_pending_q, p);
}
+/*******************************************************************************
+**
+** Function btm_send_pending_direct_conn
+**
+** Description This function send the pending direct connection request in queue
+**
+** Returns TRUE if started, FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN btm_send_pending_direct_conn(void )
+{
+ tBTM_BLE_CONN_REQ *p_req;
+ BOOLEAN rt = FALSE;
+
+ if ( btm_cb.ble_ctr_cb.conn_pending_q.count )
+ {
+ p_req = (tBTM_BLE_CONN_REQ*)GKI_dequeue (&btm_cb.ble_ctr_cb.conn_pending_q);
+ rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param));
+
+ GKI_freebuf((void *)p_req);
+ }
+
+ return rt;
+}
#endif
+
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index b9e17c0f9..d13e36bce 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -33,23 +33,16 @@
#if (GAP_INCLUDED == TRUE)
#include "gap_api.h"
#endif
-
#if (BLE_INCLUDED == TRUE)
+#include "gattdefs.h"
+
#define BTM_BLE_NAME_SHORT 0x01
#define BTM_BLE_NAME_CMPL 0x02
#define BTM_BLE_FILTER_TARGET_UNKNOWN 0xff
#define BTM_BLE_POLICY_UNKNOWN 0xff
-#define BLE_RESOLVE_ADDR_MSB 0x40 /* most significant bit, bit7, bit6 is 01 to be resolvable random */
-#define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */
-#define BTM_BLE_IS_RESOLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
-
#define BTM_EXT_BLE_RMT_NAME_TIMEOUT 30
-static tBLE_BD_ADDR le_bda_any ={BLE_ADDR_PUBLIC, {0x00,0x00,0x00,0x00,0x00,0x00}};
-
-
-#define BTM_BLE_VALID_CONN_DIRECT(x) (memcmp(&le_bda_any, x, sizeof(tBLE_BD_ADDR)) != 0)
/*******************************************************************************
** Local functions
@@ -57,11 +50,12 @@ static tBLE_BD_ADDR le_bda_any ={BLE_ADDR_PUBLIC, {0x00,0x00,0x00,0x00,0x00,0x00
static void btm_ble_update_adv_flag(UINT8 flag);
static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p);
static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data);
-
-
-
-
-
+static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
+ BD_ADDR_PTR p_addr_ptr,
+ tBLE_ADDR_TYPE *p_init_addr_type,
+ tBLE_ADDR_TYPE *p_own_addr_type);
+static BOOLEAN btm_ble_start_adv(void);
+static tBTM_STATUS btm_ble_stop_adv(void);
@@ -80,9 +74,65 @@ void BTM_BleReset(void)
{
btsnd_hcic_ble_reset();
}
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvWhitelist
+**
+** Description Add or remove device from advertising white list
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR remote_bda)
+{
+ return FALSE;
+}
/*******************************************************************************
**
+** Function BTM_BleUpdateAdvFilterPolicy
+**
+** Description This function update the filter policy of advertiser.
+**
+** Parameter adv_policy: advertising filter policy
+**
+** Return void
+*******************************************************************************/
+void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy)
+{
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
+ BD_ADDR p_addr_ptr= {0};
+ UINT8 adv_mode = p_cb->adv_mode;
+
+ BTM_TRACE_EVENT0 ("BTM_BleUpdateAdvFilterPolicy");
+
+ if (p_cb->afp != adv_policy)
+ {
+ p_cb->afp = adv_policy;
+
+ /* if adv active, stop and restart */
+ btm_ble_stop_adv ();
+
+ if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &p_cb->adv_addr_type);
+
+ btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
+ p_cb->adv_interval_max,
+ p_cb->evt_type,
+ p_cb->adv_addr_type,
+ init_addr_type,
+ p_addr_ptr,
+ p_cb->adv_chnl_map,
+ p_cb->afp);
+
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btm_ble_start_adv ();
+
+ }
+}
+/*******************************************************************************
+**
** Function BTM_BleObserve
**
** Description This procedure keep the device listening for advertising
@@ -104,14 +154,16 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration,
if (start)
{
- if (p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
+ /* shared inquiry database, do not allow observe if any inquiry is active */
+ if (btm_cb.btm_inq_vars.inq_active || p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
return BTM_BUSY;
btm_cb.btm_inq_vars.p_inq_results_cb = p_results_cb;
btm_cb.btm_inq_vars.p_inq_cmpl_cb = p_cmpl_cb;
+ p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
/* allow config scanning type */
- if (btsnd_hcic_ble_set_scan_params ((UINT8)((p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type),
+ if (btsnd_hcic_ble_set_scan_params (p_inq->scan_type,
(UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval),
(UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window),
BLE_ADDR_PUBLIC,
@@ -122,7 +174,7 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration,
{
status = BTM_SUCCESS;
p_inq->proc_mode = BTM_BLE_OBSERVE;
- btm_cb.btm_inq_vars.inq_active = TRUE;
+ btm_cb.btm_inq_vars.inq_active |= BTM_LE_OBSERVE_ACTIVE;
if (duration != 0)
{
@@ -134,6 +186,7 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration,
}
else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
{
+ btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
btm_ble_stop_scan();
}
@@ -154,6 +207,7 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration,
tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
{
tBTM_STATUS status = BTM_NO_RESOURCES;
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT8 evt_type = p_cb->scan_rsp ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
@@ -170,8 +224,9 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
(UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type, p_cb->direct_bda.bda,
+ p_addr_cb->own_addr_type,
+ p_cb->direct_bda.type,
+ p_cb->direct_bda.bda,
p_cb->adv_chnl_map,
p_cb->afp))
@@ -179,21 +234,11 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
else
p_cb->evt_type = evt_type;
- if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
- {
- p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
-
- status = BTM_SUCCESS;
- }
+ status = btm_ble_start_adv ();
}
else if (!start && p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
{
- if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
- {
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-
- status = BTM_SUCCESS;
- }
+ status = btm_ble_stop_adv();
}
else
{
@@ -201,16 +246,9 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
BTM_TRACE_ERROR2("Can not %s Broadcast, device %s in Broadcast mode",
(start ? "Start" : "Stop"), (start ? "alerady" :"not"));
}
-
return status;
}
-
-
-
-
-
-
/*******************************************************************************
**
** Function BTM_RegisterScanReqEvt
@@ -226,32 +264,14 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
*******************************************************************************/
void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback)
{
-#ifdef BTM_BLE_PC_ADV_TEST_MODE // For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include
- if (BTM_BLE_PC_ADV_TEST_MODE) // For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode
+#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
+ if (BTM_BLE_PC_ADV_TEST_MODE) /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
p_cb->p_scan_req_cback = p_scan_req_cback;
}
#endif
}
-/*******************************************************************************
-**
-** Function BTM_BleConfigPrivacy
-**
-** Description This function is called to enable or disable the privacy in
-** the local device.
-**
-** Parameters enable: TRUE to enable it; FALSE to disable it.
-**
-** Returns void
-**
-*******************************************************************************/
-void BTM_BleConfigPrivacy(BOOLEAN enable)
-{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- BTM_TRACE_EVENT0 (" BTM_BleConfigPrivacy");
- p_cb->privacy = enable;
-}
/*******************************************************************************
**
@@ -331,46 +351,8 @@ BOOLEAN BTM_BleSetBgConnType(tBTM_BLE_CONN_TYPE bg_conn_type,
*******************************************************************************/
BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR remote_bda)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- tBTM_BLE_SEL_CBACK *p_select_cback;
BOOLEAN ret = TRUE;
- BTM_TRACE_EVENT0 (" BTM_BleUpdateBgConnDev");
-
- /* if auto connection is active */
- if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
- {
- if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
- {
- /* terminate auto connection first */
- ret = btm_ble_start_auto_conn(FALSE);
- }
- else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- p_select_cback = btm_cb.ble_ctr_cb.p_select_cback;
- ret = btm_ble_start_select_conn(FALSE, NULL);
- }
- }
- if (ret)
- {
- /* update white list */
- ret = btm_update_bg_conn_list(add_remove, remote_bda);
- btm_update_dev_to_white_list(add_remove, remote_bda, BLE_ADDR_PUBLIC);
- }
-
- if (ret && p_cb->bg_conn_state == BLE_BG_CONN_IDLE)
- {
- if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
- {
- /* restart auto connection */
- btm_ble_start_auto_conn(TRUE);
- }
- else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- p_select_cback = btm_cb.ble_ctr_cb.p_select_cback;
- btm_ble_start_select_conn(TRUE, p_select_cback);
- }
- }
return ret;
}
@@ -387,44 +369,49 @@ BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR remote_bda)
** Returns void
**
*******************************************************************************/
-tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed, tBLE_BD_ADDR *p_dir_bda)
+tBTM_STATUS BTM_BleSetConnMode(BOOLEAN is_directed)
{
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
- tBTM_STATUS status = BTM_SUCCESS;
- BD_ADDR reconn_bda;
- BTM_TRACE_EVENT0 ("BTM_BleSetConnMode ");
+ BTM_TRACE_EVENT1 ("BTM_BleSetConnMode is_directed = %d ", is_directed);
- memcpy(&p_cb->direct_bda, &le_bda_any, sizeof(tBLE_BD_ADDR));
- p_cb->own_addr_type = BLE_ADDR_PUBLIC;
+ p_cb->directed_conn = is_directed;
+ return btm_ble_set_connectability( p_cb->connectable_mode);
- if (directed)
- {
- if (p_dir_bda)
- {
- memcpy(&p_cb->direct_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
+}
- if (btm_cb.ble_ctr_cb.privacy /* && GAP privacy ad reconnect addr exist */)
- {
- /* write reconnect address to controller*/
- btsnd_hcic_ble_set_random_addr(reconn_bda);
- }
- /* else use static address or publich address */
+/*******************************************************************************
+**
+** Function btm_set_conn_mode_adv_init_addr
+**
+** Description set initator address type and local address type based on adv
+** mode.
+**
+**
+*******************************************************************************/
+static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
+ BD_ADDR_PTR p_addr_ptr,
+ tBLE_ADDR_TYPE *p_init_addr_type,
+ tBLE_ADDR_TYPE *p_own_addr_type)
+{
+ UINT8 evt_type;
- }
- else
- status = BTM_ILLEGAL_VALUE;
+ if ( p_cb->directed_conn)
+ {
+ /* direct adv mode does not have privacy if privacy
+ is not enabled or no reconn addr config */
+ *p_own_addr_type = BLE_ADDR_PUBLIC;
+ *p_init_addr_type = p_cb->direct_bda.type;
+ memcpy(p_addr_ptr, p_cb->direct_bda.bda, BD_ADDR_LEN);
+ evt_type = BTM_BLE_CONNECT_DIR_EVT;
}
- else /* undirected connecatable */
+ else /* undirect adv mode */
{
- if (btm_cb.ble_ctr_cb.privacy /* GAP privacy flag enabled */)
- {
- /* generate resolvable private address */
- btm_gen_resolvable_private_addr();
- } /* else use publich address */
-
+ evt_type = BTM_BLE_CONNECT_EVT;
}
- return status;
+
+ return evt_type;
+
}
/*******************************************************************************
@@ -445,8 +432,13 @@ tBTM_STATUS BTM_BleSetAdvParams(UINT16 adv_int_min, UINT16 adv_int_max,
tBLE_BD_ADDR *p_dir_bda,
tBTM_BLE_ADV_CHNL_MAP chnl_map)
{
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS status = BTM_SUCCESS;
+ BD_ADDR p_addr_ptr = {0};
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
+ tBLE_ADDR_TYPE own_addr_type = p_addr_cb->own_addr_type;
+ UINT8 adv_mode = p_cb->adv_mode;
BTM_TRACE_EVENT0 ("BTM_BleSetAdvParams");
@@ -464,46 +456,26 @@ tBTM_STATUS BTM_BleSetAdvParams(UINT16 adv_int_min, UINT16 adv_int_max,
{
memcpy(&p_cb->direct_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
}
- else
- memcpy(&p_cb->direct_bda, &le_bda_any, sizeof(tBLE_BD_ADDR));
- if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- BTM_TRACE_EVENT0 ("update params for an active adv");
+ BTM_TRACE_EVENT0 ("update params for an active adv");
- if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE)
- {
- if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
- p_cb->evt_type = BTM_BLE_CONNECT_DIR_EVT;
- else
- p_cb->evt_type = BTM_BLE_CONNECT_EVT;
+ btm_ble_stop_adv();
- BTM_TRACE_DEBUG1(" evt_type = %d", p_cb->evt_type);
- }
+ if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
- if (!btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
- status = BTM_NO_RESOURCES;
- else
- /* update adv params */
- if (!btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
- p_cb->adv_interval_max,
- p_cb->evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type,
- p_cb->direct_bda.bda,
- p_cb->adv_chnl_map,
- p_cb->afp))
+ /* update adv params */
+ btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
+ p_cb->adv_interval_max,
+ p_cb->evt_type,
+ own_addr_type,
+ init_addr_type,
+ p_addr_ptr,
+ p_cb->adv_chnl_map,
+ p_cb->afp);
- status = BTM_NO_RESOURCES;
-
- else if (!btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
- {
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-
- status = BTM_NO_RESOURCES;
- }
-
- }
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btm_ble_start_adv();
return status;
}
@@ -539,7 +511,6 @@ void BTM_BleReadAdvParams (UINT16 *adv_int_min, UINT16 *adv_int_max,
}
}
-
/*******************************************************************************
**
** Function BTM_BleSetScanParams
@@ -606,7 +577,7 @@ tBTM_STATUS BTM_BleWriteScanRsp(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p
{
status = BTM_SUCCESS;
- if (p_data != NULL)
+ if (data_mask != 0)
btm_cb.ble_ctr_cb.inq_var.scan_rsp = TRUE;
else
btm_cb.ble_ctr_cb.inq_var.scan_rsp = FALSE;
@@ -711,7 +682,6 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
*p_flag = NULL;
UINT16 len = BTM_BLE_AD_DATA_LEN, cp_len = 0;
UINT8 i = 0;
- tBTM_BLE_ATTR *p_attr;
tBTM_BLE_PROP_ELEM *p_elem;
BTM_TRACE_EVENT0 (" btm_ble_build_adv_data");
@@ -734,7 +704,18 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
data_mask &= ~BTM_BLE_AD_BIT_FLAGS;
}
+ /* appearance data */
+ if (len > 3 && data_mask & BTM_BLE_AD_BIT_APPEARANCE)
+ {
+ *p++ = 3; /* length */
+ *p++ = BTM_BLE_AD_TYPE_APPEARANCE;
+ UINT16_TO_STREAM(p, p_data->appearance);
+ len -= 4;
+
+ data_mask &= ~BTM_BLE_AD_BIT_APPEARANCE;
+ }
/* device name */
+#if BTM_MAX_LOC_BD_NAME_LEN > 0
if (len > 2 && data_mask & BTM_BLE_AD_BIT_DEV_NAME)
{
if (strlen(btm_cb.cfg.bd_name) > (UINT16)(len - 2))
@@ -750,10 +731,10 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
*p++ = BTM_BLE_AD_TYPE_NAME_CMPL;
ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, cp_len);
}
-
len -= (cp_len + 2);
data_mask &= ~BTM_BLE_AD_BIT_DEV_NAME;
}
+#endif
/* manufacturer data */
if (len > 2 && data_mask & BTM_BLE_AD_BIT_MANU &&
p_data && p_data->manu.len != 0 && p_data->manu.p_val)
@@ -789,13 +770,13 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
{
cp_len = (len - 2)/2;
*p ++ = 1 + cp_len * 2;
- *p++ = BTM_BLE_AD_TYPE_SRV_PART;
+ *p++ = BTM_BLE_AD_TYPE_16SRV_PART;
}
else
{
cp_len = p_data->services.num_service;
*p++ = 1 + cp_len * 2;
- *p++ = BTM_BLE_AD_TYPE_SRV_CMPL;
+ *p++ = BTM_BLE_AD_TYPE_16SRV_CMPL;
}
for (i = 0; i < cp_len; i ++)
{
@@ -815,27 +796,6 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
len -= 6;
data_mask &= ~BTM_BLE_AD_BIT_INT_RANGE;
}
- if (data_mask & BTM_BLE_AD_BIT_ATTR && p_data && p_data->attr.num_attr != 0)
- {
- for (i = 0; i < p_data->attr.num_attr ; i ++)
- {
- p_attr = p_data->attr.attr_list + i;
-
- if (len >= (2 + 2 + p_attr->data_len))/* len byte(1) + ATTR type(1) + Uuid len(2) + value length */
- {
- *p ++ = p_attr->data_len + 2 + 1; /* Uuid len + value length */
- *p ++ = BTM_BLE_AD_TYPE_ATTR;
- UINT16_TO_STREAM(p, p_attr->uuid);
- ARRAY_TO_STREAM(p, p_attr->p_data, p_attr->data_len);
-
- len -= (4 + p_attr->data_len);
- }
- else
- break;
- }
- if (i == p_data->attr.num_attr)
- data_mask &= ~BTM_BLE_AD_BIT_ATTR;
- }
if (data_mask & BTM_BLE_AD_BIT_PROPRIETARY && p_data && p_data->p_proprietary)
{
for (i = 0; i < p_data->p_proprietary->num_elem ; i ++)
@@ -879,6 +839,7 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
*******************************************************************************/
tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
{
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT16 mode = (combined_mode & BTM_BLE_DISCOVERABLE_MASK);
UINT8 flag = 0;
@@ -887,6 +848,9 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
: BTM_BLE_CONNECT_EVT;
tBTM_STATUS status = BTM_SUCCESS;
+ BD_ADDR p_addr_ptr= {0};
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC,
+ own_addr_type = p_addr_cb->own_addr_type;;
BTM_TRACE_EVENT2 ("btm_ble_set_discoverability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
@@ -925,55 +889,47 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode if no scan rsp ");
if (!p_cb->scan_rsp )
new_mode = BTM_BLE_ADV_DISABLE;
+
}
else
{
- if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
- {
- BTM_TRACE_DEBUG0("evt_type = BTM_BLE_CONNECT_DIR_EVT");
- evt_type = BTM_BLE_CONNECT_DIR_EVT;
- }
- else
- {
- BTM_TRACE_DEBUG0(" evt_type = BTM_BLE_CONNECT_EVT");
- evt_type = BTM_BLE_CONNECT_EVT;
- }
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
}
}
btm_ble_update_adv_flag(flag);
/* update adv params if start advertising */
BTM_TRACE_EVENT2 ("evt_type=0x%x p-cb->evt_type=0x%x ", evt_type, p_cb->evt_type);
- if (new_mode == BTM_BLE_ADV_ENABLE && evt_type != p_cb->evt_type)
+ if (new_mode == BTM_BLE_ADV_ENABLE &&
+ (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type))
{
- if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- BTM_TRACE_EVENT0 ("Set Adv disable");
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
- btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
- }
+ btm_ble_stop_adv();
/* update adv params */
if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
(UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type, p_cb->direct_bda.bda,
+ own_addr_type,
+ init_addr_type,
+ p_addr_ptr,
p_cb->adv_chnl_map,
p_cb->afp))
status = BTM_NO_RESOURCES;
else
+ {
p_cb->evt_type = evt_type;
+ p_cb->adv_addr_type = own_addr_type;
+ }
}
+
if (status == BTM_SUCCESS && p_cb->adv_mode != new_mode)
{
- /* update advertising mode */
- if (!btsnd_hcic_ble_set_adv_enable (new_mode))
- status = BTM_NO_RESOURCES;
+ if (new_mode == BTM_BLE_ADV_ENABLE)
+ status = btm_ble_start_adv();
else
- p_cb->adv_mode = new_mode;
+ status = btm_ble_stop_adv();
}
/* set up stop advertising timer */
@@ -1000,6 +956,7 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
*******************************************************************************/
tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
{
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT16 mode = (combined_mode & BTM_BLE_CONNECTABLE_MASK);
UINT8 cur_flag = 0;
@@ -1008,9 +965,11 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
UINT8 new_mode = BTM_BLE_ADV_ENABLE;
UINT8 evt_type = (p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
tBTM_STATUS status = BTM_SUCCESS;
+ BD_ADDR p_addr_ptr = {0};
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC,
+ own_addr_type = p_addr_cb->own_addr_type;
BTM_TRACE_EVENT2 ("btm_ble_set_connectability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
-
/*** Check mode parameter ***/
if (mode > BTM_BLE_MAX_CONNECTABLE)
return(BTM_ILLEGAL_VALUE);
@@ -1035,45 +994,36 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode with no scan rsp");
if(!p_cb->scan_rsp)
new_mode = BTM_BLE_ADV_DISABLE;
+
}
}
else /* connectable */
{
- BTM_TRACE_DEBUG2("btm_ble_set_connectability: mode = %04x discoverable_mode= %02x", mode, p_cb->discoverable_mode);
-
- if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
- {
- BTM_TRACE_DEBUG0("evt_type = BTM_BLE_CONNECT_DIR_EVT");
- evt_type = BTM_BLE_CONNECT_DIR_EVT;
- }
- else
- {
- BTM_TRACE_DEBUG0(" evt_type = BTM_BLE_CONNECT_EVT");
- evt_type = BTM_BLE_CONNECT_EVT;
- }
+ evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
}
/* update adv params if needed */
- if (p_cb->evt_type != evt_type && new_mode == BTM_BLE_ADV_ENABLE)
+ if ((p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type)
+ && new_mode == BTM_BLE_ADV_ENABLE)
{
- if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
- btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
- }
+ btm_ble_stop_adv();
if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
(UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type,
- p_cb->direct_bda.bda,
+ own_addr_type,
+ init_addr_type,
+ p_addr_ptr,
p_cb->adv_chnl_map,
p_cb->afp))
status = BTM_NO_RESOURCES;
else
+ {
p_cb->evt_type = evt_type;
+ p_cb->adv_addr_type = own_addr_type;
+ }
}
+
/* update advertising mode */
if (status == BTM_SUCCESS && new_mode != p_cb->adv_mode)
{
@@ -1082,6 +1032,13 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
status = BTM_SUCCESS;
p_cb->adv_mode = new_mode;
+
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE &&
+ p_cb->afp != AP_SCAN_CONN_ALL)
+ btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
+ else
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+
}
}
@@ -1103,11 +1060,8 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
**
**
** Returns BTM_CMD_STARTED if successfully started
-** BTM_ILLEGAL_VALUE if a bad parameter is detected
** BTM_NO_RESOURCES if could not allocate a message buffer
-** BTM_SUCCESS - if cancelling the periodic inquiry
** BTM_BUSY - if an inquiry is already active
-** BTM_WRONG_MODE if the device is not up.
**
*******************************************************************************/
tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration)
@@ -1128,7 +1082,7 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration)
/* start scan, already enable duplicate filtering */
if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE))
{
- status = BTM_SUCCESS;
+ status = BTM_CMD_STARTED;
p_inq->proc_mode = mode;
if (duration != 0)
@@ -1155,7 +1109,7 @@ void btm_ble_read_remote_name_cmpl(BOOLEAN status, BD_ADDR bda, UINT16 length, c
UINT8 hci_status = HCI_SUCCESS;
BD_NAME bd_name;
- memset(bd_name, 0, BD_NAME_LEN);
+ memset(bd_name, 0, (BD_NAME_LEN + 1));
memcpy((UINT8*)bd_name, p_name, length);
if ((!status) || (length==0))
@@ -1163,7 +1117,7 @@ void btm_ble_read_remote_name_cmpl(BOOLEAN status, BD_ADDR bda, UINT16 length, c
hci_status = HCI_ERR_HOST_TIMEOUT;
}
- btm_process_remote_name(bda, bd_name, length, hci_status);
+ btm_process_remote_name(bda, bd_name, length +1, hci_status);
btm_sec_rmt_name_request_complete (bda, (UINT8 *)p_name, hci_status);
}
@@ -1298,7 +1252,6 @@ static void btm_ble_parse_adv_data(tBTM_INQ_INFO *p_info, UINT8 *p_data,
{
UINT8 *p_cur = p_data;
UINT8 ad_len, ad_type, ad_flag;
- tBTM_BLE_ATTR *p_attr;
BTM_TRACE_EVENT0 (" btm_ble_parse_adv_data");
@@ -1348,35 +1301,38 @@ static void btm_ble_parse_adv_data(tBTM_INQ_INFO *p_info, UINT8 *p_data,
BTM_TRACE_DEBUG1("BTM_BLE_AD_TYPE_TX_PWR tx_level = %d", p_adv_data->tx_power_level);
break;
- case BTM_BLE_AD_TYPE_ATTR:
- p_adv_data->ad_mask |= BTM_BLE_AD_BIT_ATTR;
- p_attr = &p_adv_data->attr_data.attr_list[p_adv_data->attr_data.num_attr];
- p_attr->uuid = *p_cur ++;
-
- if (ad_len > 3)
- {
- p_attr->data_len = ad_len - 3;
- p_attr->p_data = p_buf;
- memcpy(p_attr->p_data, p_cur, p_attr->data_len);
- p_buf += p_attr->data_len;
- }
+ case BTM_BLE_AD_TYPE_MANU:
- p_adv_data->attr_data.num_attr ++;
- BTM_TRACE_DEBUG2("BTM_BLE_AD_TYPE_ATTR[%d] uuid = 0x%04x",p_adv_data->attr_data.num_attr, p_attr->uuid);
+ case BTM_BLE_AD_TYPE_16SRV_PART:
+ case BTM_BLE_AD_TYPE_16SRV_CMPL:
+ p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE;
+ /* need allocate memory to store UUID list */
+ p_adv_data->service.num_service = (ad_len - 1)/2;
+ BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
+ p_cur += (ad_len - 1);
break;
- case BTM_BLE_AD_TYPE_MANU:
-
- case BTM_BLE_AD_TYPE_SRV_CMPL:
- case BTM_BLE_AD_TYPE_SRV_PART:
- p_adv_data->ad_mask |= ad_type;
+ case BTM_BLE_AD_TYPE_SOL_SRV_UUID:
+ p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE_SOL;
/* need allocate memory to store UUID list */
p_adv_data->service.num_service = (ad_len - 1)/2;
BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
+ p_cur += (ad_len - 1);
+ break;
- default:
+ case BTM_BLE_AD_TYPE_128SOL_SRV_UUID:
+ p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE_128SOL;
+ /* need allocate memory to store UUID list */
+ p_adv_data->service.num_service = (ad_len - 1)/16;
+ BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
p_cur += (ad_len - 1);
break;
+
+ case BTM_BLE_AD_TYPE_APPEARANCE:
+ case BTM_BLE_AD_TYPE_PUBLIC_TARGET:
+ case BTM_BLE_AD_TYPE_RANDOM_TARGET:
+ default:
+ break;
}
len -= (ad_len + 1);
}
@@ -1426,6 +1382,7 @@ void btm_ble_cache_adv_data(tBTM_INQ_RESULTS *p_cur, UINT8 data_len, UINT8 *p, U
/* parse service UUID from adv packet and save it in inq db eir_uuid */
/* TODO */
}
+
/*******************************************************************************
**
** Function btm_ble_is_discoverable
@@ -1501,6 +1458,7 @@ BOOLEAN btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p)
return is_discoverable;
}
+
/*******************************************************************************
**
** Function btm_ble_update_inq_result
@@ -1567,9 +1525,10 @@ BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_t
}
/* if BR/EDR not supported is not set, assume is a DUMO device */
- if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0)
+ if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0 &&
+ evt_type != BTM_BLE_CONNECT_DIR_EVT)
{
- BTM_TRACE_ERROR0("BR/EDR NOT support bit not set, treat as DUMO");
+ BTM_TRACE_DEBUG0("BR/EDR NOT support bit not set, treat as DUMO");
p_cur->device_type |= BT_DEVICE_TYPE_DUMO;
}
else
@@ -1625,45 +1584,6 @@ void btm_send_sel_conn_callback(BD_ADDR remote_bda, UINT8 evt_type, UINT8 *p_dat
/*******************************************************************************
**
-** Function btm_ble_resolve_random_addr_cmpl
-**
-** Description resolve random address complete callback.
-**
-** Returns void
-**
-*******************************************************************************/
-static void btm_ble_resolve_random_addr_cmpl(void * p_rec, void *p)
-{
- tBTM_SEC_DEV_REC *match_rec = (tBTM_SEC_DEV_REC *) p_rec;
- UINT8 addr_type = BLE_ADDR_RANDOM;
- BD_ADDR bda;
- UINT8 *pp = (UINT8 *)p + 1;
- UINT8 evt_type;
-
- BTM_TRACE_EVENT0 ("btm_ble_resolve_random_addr_cmpl ");
-
- STREAM_TO_UINT8 (evt_type, pp);
- STREAM_TO_UINT8 (addr_type, pp);
- STREAM_TO_BDADDR (bda, pp);
-
- if (match_rec)
- {
- BTM_TRACE_ERROR0("Random match");
- memcpy(match_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
- memcpy(bda, match_rec->bd_addr, BD_ADDR_LEN);
- }
- else
- {
- BTM_TRACE_ERROR0("Random unmatch");
- }
-
- btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, pp);
-
- return;
-}
-
-/*******************************************************************************
-**
** Function btm_ble_process_adv_pkt
**
** Description This function is called when adv packet report events are
@@ -1681,8 +1601,6 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
UINT8 evt_type = 0, *p = p_data;
UINT8 addr_type = 0;
- BTM_TRACE_EVENT0 ("btm_ble_process_adv_pkt ");
-
/* always get one device at a time */
p ++;
@@ -1691,30 +1609,24 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
STREAM_TO_UINT8 (addr_type, p);
STREAM_TO_BDADDR (bda, p);
-#ifdef BTM_BLE_PC_ADV_TEST_MODE // For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include
- if (BTM_BLE_PC_ADV_TEST_MODE) // For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode
+#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
+ if (BTM_BLE_PC_ADV_TEST_MODE) /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
{
if (btm_cb.ble_ctr_cb.p_scan_req_cback)
(*btm_cb.ble_ctr_cb.p_scan_req_cback)(bda, addr_type, evt_type);
}
#endif
+
+
/* Only process the results if the inquiry is still active */
- if (!btm_cb.btm_inq_vars.inq_active &&
+ if ((btm_cb.btm_inq_vars.inq_active & BTM_LE_SCAN_ACTIVE_MASK) == 0 &&
(btm_cb.ble_ctr_cb.bg_conn_type != BTM_BLE_CONN_SELECTIVE ||
/* or selective auto connection is active */
btm_cb.ble_ctr_cb.p_select_cback == NULL))
return;
-
-#if SMP_INCLUDED == TRUE
- if (addr_type == BLE_ADDR_RANDOM && BTM_BLE_IS_RESOLVE_BDA(bda))
- {
- btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_cmpl, p_data);
- }
- else
-#endif
- btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
+ btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
}
/*******************************************************************************
@@ -1755,14 +1667,12 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
}
else
{
- BTM_TRACE_DEBUG0("LE in le_bd_db already");
/* if yes, skip it */
return; /* assumption: one result per event */
}
}
else /* not been processed int his round */
{
- BTM_TRACE_DEBUG0("new LE BD_ADDR");
to_report = TRUE;
}
@@ -1774,7 +1684,6 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
if ((p_i = btm_inq_db_new (bda)) != NULL)
{
p_inq->inq_cmpl_info.num_resp++;
- BTM_TRACE_DEBUG0("adv pkt process: new record is added into inq db");
to_report = TRUE;
}
else
@@ -1809,7 +1718,9 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
{
BTM_TRACE_WARNING0("INQ RES: Extra Response Received...cancelling inquiry..");
- if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) )
+ /* if is non-periodic inquiry active, cancel now */
+ if ((p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK) != 0 &&
+ (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) == 0)
btsnd_hcic_inq_cancel();
/* stop LE scan now */
@@ -1825,14 +1736,17 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
/* background connection in selective connection mode */
if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)
{
- btm_send_sel_conn_callback(bda, evt_type, p, addr_type);
+ if (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BLE &&
+ (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT))
+ btm_send_sel_conn_callback(bda, evt_type, p, addr_type);
+ else
+ {
+ BTM_TRACE_DEBUG0("None LE device, can not initiate selective connection");
+ }
}
else if (p_inq_results_cb && to_report)
{
- BTM_TRACE_DEBUG0("BTMINQ LE: Found devices, send callback btm_inqrslt_cb");
-
- if (p_inq->inq_active)
- (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+ (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
}
}
@@ -1873,6 +1787,36 @@ void btm_ble_stop_scan(void)
/*******************************************************************************
**
+** Function btm_ble_start_adv
+**
+** Description Stop the BLE advertising.
+**
+** Returns void
+**
+*******************************************************************************/
+static tBTM_STATUS btm_ble_start_adv(void)
+{
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+ tBTM_STATUS rt = BTM_NO_RESOURCES;
+
+ if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
+ {
+ if (p_cb->afp != AP_SCAN_CONN_ALL)
+ btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
+
+ p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
+
+ rt = BTM_SUCCESS;
+ }
+ else
+ {
+ p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+ }
+ return rt;
+}
+/*******************************************************************************
+**
** Function btm_ble_stop_adv
**
** Description Stop the BLE advertising.
@@ -1880,14 +1824,23 @@ void btm_ble_stop_scan(void)
** Returns void
**
*******************************************************************************/
-void btm_ble_stop_adv(void)
+static tBTM_STATUS btm_ble_stop_adv(void)
{
- BTM_TRACE_EVENT0 (" btm_ble_stop_adv");
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+ tBTM_STATUS rt = BTM_SUCCESS;
- if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
{
- btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+ if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
+ {
+ p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+ }
+ else
+ rt = BTM_NO_RESOURCES;
}
+ return rt;
+
}
/*******************************************************************************
@@ -1917,8 +1870,7 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
break;
case BTU_TTYPE_BLE_RANDOM_ADDR:
- if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_ENABLE &&
- btm_cb.ble_ctr_cb.inq_var.own_addr_type == BLE_ADDR_RANDOM)
+ if (btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type == BLE_ADDR_RANDOM)
{
/* refresh the random addr */
btm_gen_resolvable_private_addr();
@@ -1928,62 +1880,6 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
}
}
-/*******************************************************************************
-**
-** Function btm_ble_connected
-**
-** Description This function is when a LE connection to the peer device is
-** establsihed
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role)
-{
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-
- BTM_TRACE_EVENT0 ("btm_ble_connected");
-
- /* Commenting out trace due to obf/compilation problems.
- */
-#if (BT_USE_TRACES == TRUE)
- if (p_dev_rec)
- {
- BTM_TRACE_EVENT4 ("Security Manager: btm_sec_connected : handle:%d enc_mode:%d bda:%x RName:%s",
- handle, enc_mode,
- (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5],
- p_dev_rec->sec_bd_name);
-
- BTM_TRACE_DEBUG1 ("btm_ble_connected sec_flags=0x%x",p_dev_rec->sec_flags);
- }
- else
- {
- BTM_TRACE_EVENT3 ("Security Manager: btm_sec_connected: handle:%d enc_mode:%d bda:%x ",
- handle, enc_mode,
- (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5]);
- }
-#endif
-
- if (!p_dev_rec)
- {
- /* There is no device record for new connection. Allocate one */
- p_dev_rec = btm_sec_alloc_dev (bda);
- }
- else /* Update the timestamp for this device */
- {
- p_dev_rec->timestamp = btm_cb.dev_rec_count++;
- }
-
- p_dev_rec->device_type = BT_DEVICE_TYPE_BLE;
- p_dev_rec->hci_handle = handle;
- if (role == HCI_ROLE_MASTER)
- p_dev_rec->role_master = TRUE;
-
- p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
-
- return;
-}
/*******************************************************************************
**
@@ -2049,7 +1945,81 @@ void btm_ble_write_adv_enable_complete(UINT8 * p)
/* toggle back the adv mode */
p_cb->adv_mode = !p_cb->adv_mode;
}
+
+
}
+
+/*******************************************************************************
+**
+** Function btm_ble_dir_adv_tout
+**
+** Description when directed adv time out
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_dir_adv_tout(void)
+{
+ btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+
+ /* make device fall back into undirected adv mode by default */
+ btm_cb.ble_ctr_cb.inq_var.directed_conn = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_update_mode_operation
+**
+** Description This function update the GAP role operation when a link status
+** is updated.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, BOOLEAN conn_cancel)
+{
+ tACL_CONN *pa = &btm_cb.acl_db[0];
+ UINT16 xx;
+ UINT8 dev_role = link_role;
+
+ BTM_TRACE_DEBUG1("btm_ble_update_mode_operation adv_mode = %d", btm_cb.ble_ctr_cb.inq_var.adv_mode );
+
+ /* update periphera role operation */
+ /* If we are LE connectable, check if we need to start advertising again */
+ if (link_role == HCI_ROLE_UNKNOWN)
+ /* && btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE) */
+ {
+ for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
+ {
+ /* If any other LE link is up, we are still not connectable */
+ if (pa->in_use && pa->is_le_link)
+ {
+ dev_role = pa->link_role;
+ break;
+ }
+ }
+ }
+
+ if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE &&
+ (dev_role == HCI_ROLE_UNKNOWN )) /* when device has no connection, update adv here */
+ /* if already in connection, no connectable adv is allowed unless scatternet is enabled */
+ {
+ btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
+ }
+
+ /* if connection complete */
+ if (conn_cancel || link_role != HCI_ROLE_UNKNOWN)
+ btm_ble_set_conn_st(BLE_CONN_IDLE);
+
+ if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
+ {
+ if (!btm_send_pending_direct_conn())
+ {
+ btm_ble_resume_bg_conn();
+ }
+ }
+}
+
/*******************************************************************************
**
** Function btm_ble_init
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 449de8f68..878037b64 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -36,15 +36,6 @@
#include "smp_api.h"
#endif
-#define BTM_BLE_CONNECT_EVT 0x00
-#define BTM_BLE_CONNECT_DIR_EVT 0x01
-#define BTM_BLE_DISCOVER_EVT 0x02
-#define BTM_BLE_NON_CONNECT_EVT 0x03
-#define BTM_BLE_SCAN_RSP_EVT 0x04
-#define BTM_BLE_SCAN_REQ_EVT 0x06
-#define BTM_BLE_UNKNOWN_EVT 0xff
-
-#define BTM_BLE_UNKNOWN_EVT 0xff
/* scanning enable status */
#define BTM_BLE_SCAN_ENABLE 0x01
@@ -79,7 +70,10 @@
#define BTM_BLE_SEC_REQ_ACT_DISCARD 3 /* discard the sec request while encryption is started but not completed */
typedef UINT8 tBTM_BLE_SEC_REQ_ACT;
-
+#define BLE_STATIC_PRIVATE_MSB_MASK 0x3f
+#define BLE_RESOLVE_ADDR_MSB 0x40 /* most significant bit, bit7, bit6 is 01 to be resolvable random */
+#define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */
+#define BTM_BLE_IS_RESOLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
typedef struct
{
@@ -119,13 +113,14 @@ typedef struct
UINT8 scan_type; /* current scan type: active or passive */
UINT16 adv_interval_min;
UINT16 adv_interval_max;
- tBLE_ADDR_TYPE own_addr_type;
tBTM_BLE_AFP afp; /* advertising filter policy */
tBTM_BLE_SFP sfp; /* scanning filter policy */
+ tBLE_ADDR_TYPE adv_addr_type;
UINT8 evt_type;
UINT8 adv_mode;
tBLE_BD_ADDR direct_bda;
+ BOOLEAN directed_conn;
UINT8 adv_len;
UINT8 adv_data_cache[BTM_BLE_CACHE_ADV_DATA_MAX];
@@ -134,7 +129,6 @@ typedef struct
UINT8 num_bd_entries;
UINT8 max_bd_entries;
- tBLE_BD_ADDR local_bda;
tBTM_BLE_LOCAL_ADV_DATA adv_data;
tBTM_BLE_ADV_CHNL_MAP adv_chnl_map;
@@ -142,21 +136,25 @@ typedef struct
TIMER_LIST_ENT inq_timer_ent;
BOOLEAN scan_rsp;
UINT8 state; /* Current state that the inquiry process is in */
- UINT8 tx_power;
+ INT8 tx_power;
} tBTM_BLE_INQ_CB;
/* random address resolving complete callback */
typedef void (tBTM_BLE_RESOLVE_CBACK) (void * match_rec, void *p);
+typedef void (tBTM_BLE_ADDR_CBACK) (BD_ADDR_PTR static_random, void *p);
+
/* random address management control block */
typedef struct
{
+ tBLE_ADDR_TYPE own_addr_type; /* local device LE address type */
BD_ADDR private_addr;
BD_ADDR random_bda;
BOOLEAN busy;
UINT16 index;
tBTM_BLE_RESOLVE_CBACK *p_resolve_cback;
+ tBTM_BLE_ADDR_CBACK *p_generate_cback;
void *p;
TIMER_LIST_ENT raddr_timer_ent;
} tBTM_LE_RANDOM_CB;
@@ -172,6 +170,32 @@ typedef struct
}tBTM_LE_CONN_PRAMS;
+
+typedef struct
+{
+ BD_ADDR bd_addr;
+ UINT8 attr;
+ BOOLEAN is_connected;
+ BOOLEAN in_use;
+}tBTM_LE_BG_CONN_DEV;
+
+ /* white list using state as a bit mask */
+#define BTM_BLE_WL_IDLE 0
+#define BTM_BLE_WL_INIT 1
+#define BTM_BLE_WL_SCAN 2
+#define BTM_BLE_WL_ADV 4
+typedef UINT8 tBTM_BLE_WL_STATE;
+
+/* BLE connection state */
+#define BLE_CONN_IDLE 0
+#define BLE_DIR_CONN 1
+#define BLE_BG_CONN 2
+typedef UINT8 tBTM_BLE_CONN_ST;
+
+typedef struct
+{
+ void *p_param;
+}tBTM_BLE_CONN_REQ;
/* Define BLE Device Management control structure
*/
typedef struct
@@ -188,28 +212,26 @@ typedef struct
tBTM_BLE_SEL_CBACK *p_select_cback;
TIMER_LIST_ENT scan_param_idle_timer;
- UINT8 bg_conn_dev_num;
- BD_ADDR bg_conn_dev_list[BTM_BLE_MAX_BG_CONN_DEV_NUM];
-
-#define BLE_BG_CONN_IDLE 0
-#define BLE_BG_CONN_ACTIVE 1
-#define BLE_BG_CONN_SUSPEND 2
+ /* white list information */
+ UINT8 num_empty_filter; /* Number of entries in white list */
+ UINT8 max_filter_entries; /* Maximum number of entries that can be stored */
+ tBTM_BLE_WL_STATE wl_state;
+ UINT8 bg_dev_num;
+ tBTM_LE_BG_CONN_DEV bg_dev_list[BTM_BLE_MAX_BG_CONN_DEV_NUM];
- UINT8 bg_conn_state;
+ BUFFER_Q conn_pending_q;
+ tBTM_BLE_CONN_ST conn_state;
/* random address management control block */
tBTM_LE_RANDOM_CB addr_mgnt_cb;
- /* white list information */
- UINT8 num_empty_filter; /* Number of entries in white list */
- UINT8 max_filter_entries; /* Maximum number of entries that can be stored */
BOOLEAN enabled;
- BOOLEAN privacy; /* privacy enabled or disabled */
#ifdef BTM_BLE_PC_ADV_TEST_MODE
tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback;
#endif
+ BOOLEAN scatternet_enable;
} tBTM_BLE_CB;
#ifdef __cplusplus
@@ -225,17 +247,21 @@ extern BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda);
extern tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode);
extern tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode);
extern tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration);
+extern void btm_ble_dir_adv_tout(void);
extern void btm_ble_stop_scan(void);
extern void btm_ble_att_db_init(void);
extern void btm_ble_init (void);
-extern void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role);
+extern void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched);
extern void btm_ble_read_remote_features_complete(UINT8 *p);
-extern void btm_ble_stop_adv(void);
extern void btm_ble_write_adv_enable_complete(UINT8 * p);
+extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len);
+extern tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
+extern void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
+
/* LE security function from btm_sec.c */
-#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+#if SMP_INCLUDED == TRUE
extern void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE_SEC_REQ_ACT *p_sec_req_act);
extern void btm_ble_ltk_request_reply(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk);
extern UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data);
@@ -260,35 +286,38 @@ extern void btm_ble_update_sec_key_size(BD_ADDR bd_addr, UINT8 enc_key_size);
extern UINT8 btm_ble_read_sec_key_size(BD_ADDR bd_addr);
/* white list function */
-extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr,tBLE_ADDR_TYPE addr_type);
-extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr);
+extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr,UINT8 wl_type);
+extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag);
extern void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
extern void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
extern void btm_ble_clear_white_list (void);
-extern void btm_write_bg_conn_wl(void);
/* background connection function */
extern void btm_ble_suspend_bg_conn(void);
-extern BOOLEAN btm_ble_resume_bg_conn(tBTM_BLE_SEL_CBACK *p_sele_callback, BOOLEAN def_param);
-extern void btm_ble_update_bg_state(void);
+extern BOOLEAN btm_ble_resume_bg_conn(void);
extern void btm_ble_initiate_select_conn(BD_ADDR bda);
extern BOOLEAN btm_ble_start_auto_conn(BOOLEAN start);
extern BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_cback);
-extern BOOLEAN btm_ble_find_dev_in_whitelist(BD_ADDR bd_addr);
extern BOOLEAN btm_ble_renew_bg_conn_params(BOOLEAN add, BD_ADDR bd_addr);
-extern void btm_ble_scan_param_idle(void);
extern UINT8 btm_ble_count_unconn_dev_in_whitelist(void);
+extern void btm_write_dir_conn_wl(BD_ADDR target_addr);
+extern void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bda, BOOLEAN conn_ccancel);
+
+/* direct connection utility */
+extern BOOLEAN btm_send_pending_direct_conn(void);
+extern void btm_ble_enqueue_direct_conn_req(void *p_param);
/* BLE address management */
-extern tBLE_ADDR_TYPE btm_ble_map_bda_to_conn_bda(BD_ADDR bda);
extern void btm_gen_resolvable_private_addr (void);
-extern void btm_gen_non_resolvable_private_addr (void);
+extern void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p);
extern void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p);
+extern void btm_ble_update_reconnect_address(BD_ADDR bd_addr);
#if BTM_BLE_CONFORMANCE_TESTING == TRUE
BT_API extern void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
BT_API extern void btm_ble_set_test_mac_value (BOOLEAN enable, UINT8 *p_test_mac_val);
BT_API extern void btm_ble_set_test_local_sign_cntr_value(BOOLEAN enable, UINT32 test_local_sign_cntr);
+BT_API extern void btm_set_random_address(BD_ADDR random_bda);
#endif
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index 04994d1eb..40919fada 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -125,7 +125,10 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
}
#if defined(BTIF_MIXED_MODE_INCLUDED) && (BTIF_MIXED_MODE_INCLUDED == TRUE)
- p_dev_rec->sm4 = BTM_SM4_KNOWN;
+ if (key_type < BTM_MAX_PRE_SM4_LKEY_TYPE)
+ p_dev_rec->sm4 = BTM_SM4_KNOWN;
+ else
+ p_dev_rec->sm4 = BTM_SM4_TRUE;
#endif
p_dev_rec->rmt_io_caps = io_cap;
@@ -245,7 +248,6 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
else
{
#if BLE_INCLUDED == TRUE
- p_dev_rec->device_type = BT_DEVICE_TYPE_BREDR; /* initialize it as BR/EDR device */
/* update conn params, use default value for background connection params */
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
#endif
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index f0fc43710..5a88a7741 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -37,11 +37,6 @@
#if BLE_INCLUDED == TRUE
#include "gatt_int.h"
-#if GAP_INCLUDED == TRUE
-#include "gap_api.h"
-#include "gattdefs.h"
-#endif
-
#endif /* BLE_INCLUDED */
/* BTM_APP_DEV_INIT should be defined if additional controller initialization is
@@ -112,10 +107,6 @@ response message */
#define BTM_SCO_HOST_BUF_SIZE 0xff
#endif
-#ifndef BTM_GPS_UIPC_CH_NB
-#define BTM_GPS_UIPC_CH_NB UIPC_CH_ID_1
-#endif
-
/********************************************************************************/
/* L O C A L F U N C T I O N P R O T O T Y P E S */
/********************************************************************************/
@@ -551,11 +542,6 @@ void btm_reset_complete (void)
BTM_TRACE_EVENT0 ("btm_reset_complete");
-#ifdef BRCM_VS
- btm_vs_reset_complete();
-#endif
-
-
/* Handle if btm initiated the reset */
if (btm_cb.devcb.state == BTM_DEV_STATE_WAIT_RESET_CMPLT)
{
@@ -587,11 +573,11 @@ void btm_reset_complete (void)
#endif
#if (BLE_INCLUDED == TRUE)
- btm_cb.ble_ctr_cb.bg_conn_state = BLE_BG_CONN_IDLE;
- btm_cb.ble_ctr_cb.bg_conn_dev_num = 0;
+ btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE;
+ btm_cb.ble_ctr_cb.bg_dev_num = 0;
btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE;
btm_cb.ble_ctr_cb.p_select_cback = NULL;
- memset(&btm_cb.ble_ctr_cb.bg_conn_dev_list, 0, (sizeof(BD_ADDR)*BTM_BLE_MAX_BG_CONN_DEV_NUM));
+ memset(&btm_cb.ble_ctr_cb.bg_dev_list, 0, (sizeof(tBTM_LE_BG_CONN_DEV)*BTM_BLE_MAX_BG_CONN_DEV_NUM));
gatt_reset_bgdev_list();
#endif
}
@@ -753,13 +739,9 @@ void btm_read_ble_buf_size_complete (UINT8 *p, UINT16 evt_len)
btm_read_local_features_complete( buf, 9 );
}
#else
-#ifdef BRCM_VS
- btm_brcm_feat_init();
-#else
/* get local feature if BRCM specific feature is not included */
btm_get_local_features ();
#endif
-#endif
}
@@ -781,6 +763,8 @@ void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len)
STREAM_TO_UINT8(btm_cb.ble_ctr_cb.max_filter_entries, p);
btm_cb.ble_ctr_cb.num_empty_filter = btm_cb.ble_ctr_cb.max_filter_entries;
}
+ /* write LE host support and simultaneous LE supported */
+ btsnd_hcic_ble_write_host_supported(BTM_BLE_HOST_SUPPORT, BTM_BLE_SIMULTANEOUS_HOST);
btm_get_ble_buffer_size();
}
@@ -827,32 +811,43 @@ void btm_read_local_version_complete (UINT8 *p, UINT16 evt_len)
btm_read_local_features_complete( buf, 9 );
}
#else
-#ifdef BRCM_VS
- btm_brcm_feat_init();
-#else
/* get local feature if BRCM specific feature is not included */
btm_get_local_features ();
#endif
-#endif
}
+/*******************************************************************************
+**
+** Function btm_read_local_extended_feature
+**
+** Description Local function called to send a read local extended feature to controller
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_read_local_extended_feature (void)
+{
+ btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
+
+ /* Send a Read Local extended feature message to the Controller. */
+ btsnd_hcic_read_local_ext_features (1);
+}
/*******************************************************************************
**
-** Function btm_read_local_features_complete
+** Function btm_read_local_ext_features_complete
**
+
** Description This function is called when local features read is complete.
** This is the last step of the startup sequence.
**
** Returns void
**
*******************************************************************************/
-void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
+void btm_read_local_ext_features_complete(UINT8 *p, UINT16 evt_len)
{
tBTM_DEVCB *p_devcb = &btm_cb.devcb;
tBTM_CMPL_CB *p_cb = p_devcb->p_reset_cmpl_cb;
- UINT8 status;
- UINT16 xx;
UINT8 last;
UINT8 first;
@@ -860,6 +855,46 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
/* If there was a callback address for reset complete, call it */
p_devcb->p_reset_cmpl_cb = NULL;
+ btm_sec_dev_reset ();
+
+ /* If 802.11 present might have to disable some channels */
+ if (btm_cb.last_disabled_channel != 0xff)
+ {
+ last = btm_cb.last_disabled_channel;
+ first = btm_cb.first_disabled_channel;
+ btm_cb.last_disabled_channel = 0xff;
+ btm_cb.first_disabled_channel = 0xff;
+ BTM_SetAfhChannels(first, last);
+ }
+
+ BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
+ BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
+
+ /* If anyone wants device status notifications, give him one */
+ btm_report_device_status (BTM_DEV_STATUS_UP);
+
+ /* Reset sequence is complete. If this was an application originated */
+ /* reset, tell him its done. */
+ if (p_cb)
+ (*p_cb)((void *) NULL);
+}
+/*******************************************************************************
+**
+** Function btm_read_local_features_complete
+**
+
+** Description This function is called when local features read is complete.
+** This is the last step of the startup sequence.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
+{
+ tBTM_DEVCB *p_devcb = &btm_cb.devcb;
+ UINT8 status;
+ UINT16 xx;
+
STREAM_TO_UINT8 (status, p);
if (status == HCI_SUCCESS)
{
@@ -1003,18 +1038,6 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
else
btm_cb.btm_def_link_policy &= ~HCI_ENABLE_PARK_MODE;
- btm_sec_dev_reset ();
-
- /* If 802.11 present might have to disable some channels */
- if (btm_cb.last_disabled_channel != 0xff)
- {
- last = btm_cb.last_disabled_channel;
- first = btm_cb.first_disabled_channel;
- btm_cb.last_disabled_channel = 0xff;
- btm_cb.first_disabled_channel = 0xff;
- BTM_SetAfhChannels(first, last);
- }
-
#if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
if (HCI_LMP_INQ_RSSI_SUPPORTED(p_devcb->local_features))
{
@@ -1033,21 +1056,8 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
else
l2cu_set_non_flushable_pbf(FALSE);
#endif
- BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
- BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
-
- /* If anyone wants device status notifications, give him one */
- btm_report_device_status (BTM_DEV_STATUS_UP);
-
-#ifdef BRCM_VS
- btm_brcm_arc_init();
-#endif
-
- /* Reset sequence is complete. If this was an application originated */
- /* reset, tell him its done. */
- if (p_cb)
- (*p_cb)((void *) NULL);
}
+ btm_read_local_extended_feature ();
}
/*******************************************************************************
@@ -1086,9 +1096,6 @@ UINT8 btm_get_voice_coding_support( void )
tBTM_STATUS BTM_SetLocalDeviceName (char *p_name)
{
UINT8 *p;
-#if BLE_INCLUDED == TRUE && GAP_INCLUDED == TRUE
- tGAP_BLE_ATTR_VALUE attr_value;
-#endif
if (!p_name || !p_name[0] || (strlen ((char *)p_name) > BD_NAME_LEN))
return (BTM_ILLEGAL_VALUE);
@@ -1109,11 +1116,6 @@ tBTM_STATUS BTM_SetLocalDeviceName (char *p_name)
p = (UINT8 *)p_name;
#endif
-#if BLE_INCLUDED == TRUE && GAP_INCLUDED == TRUE
- attr_value.p_dev_name = (UINT8 *)p_name;
- GAP_BleAttrDBUpdate(GATT_UUID_GAP_DEVICE_NAME, &attr_value);
-#endif
-
if (btsnd_hcic_change_name(p))
return (BTM_CMD_STARTED);
else
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index 55985625c..a9feed72d 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -502,8 +502,9 @@ tBTM_STATUS BTM_SetPeriodicInquiryMode (tBTM_INQ_PARMS *p_inqparms, UINT16 max_d
min_delay < BTM_PER_INQ_MIN_MIN_PERIOD ||
min_delay > BTM_PER_INQ_MAX_MIN_PERIOD ||
max_delay <= min_delay ||
- max_delay < BTM_PER_INQ_MIN_MAX_PERIOD ||
- max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)
+ max_delay < BTM_PER_INQ_MIN_MAX_PERIOD)
+ /* max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)*/
+ /* BTM_PER_INQ_MAX_MAX_PERIOD set to 1's in all bits. Condition resulting in false always*/
{
return (BTM_ILLEGAL_VALUE);
}
@@ -618,13 +619,13 @@ tBTM_STATUS BTM_SetConnectability (UINT16 page_mode, UINT16 window, UINT16 inter
BTM_TRACE_API0 ("BTM_SetConnectability");
#if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
- if (btm_ble_set_connectability(page_mode) == BTM_SUCCESS)
+ if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS)
{
- p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
- p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
+ return BTM_NO_RESOURCES;
}
+ p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
+ p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
-
#endif
/*** Check mode parameter ***/
@@ -757,7 +758,7 @@ tBTM_STATUS BTM_CancelInquiry(void)
return (BTM_WRONG_MODE);
/* Only cancel if not in periodic mode, otherwise the caller should call BTM_CancelPeriodicMode */
- if (p_inq->inq_active &&
+ if ((p_inq->inq_active &BTM_INQUIRY_ACTIVE_MASK) != 0 &&
(!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)))
{
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
@@ -775,8 +776,11 @@ tBTM_STATUS BTM_CancelInquiry(void)
/* Initiate the cancel inquiry */
else
{
- if (!btsnd_hcic_inq_cancel())
- status = BTM_NO_RESOURCES;
+ if ((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
+ {
+ if (!btsnd_hcic_inq_cancel())
+ status = BTM_NO_RESOURCES;
+ }
#if BLE_INCLUDED == TRUE
if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
btm_ble_stop_scan();
@@ -805,7 +809,7 @@ tBTM_STATUS BTM_CancelInquiry(void)
** Description This function is called to start an inquiry.
**
** Parameters: p_inqparms - pointer to the inquiry information
-** mode - GENERAL or LIMITED inquiry
+** mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
** max_resps - maximum amount of devices to search for before ending the inquiry
** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
@@ -830,7 +834,7 @@ tBTM_STATUS BTM_CancelInquiry(void)
tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
tBTM_CMPL_CB *p_cmpl_cb)
{
- tBTM_STATUS status;
+ tBTM_STATUS status = BTM_CMD_STARTED;
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
BTM_TRACE_API4 ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
@@ -847,23 +851,23 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p
return (BTM_WRONG_MODE);
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_GENERAL_INQUIRY &&
- (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY)
+ (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY
+#if (BLE_INCLUDED == TRUE)
+ && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_GENERAL_INQUIRY
+ && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_LIMITED_INQUIRY
+#endif
+ )
return (BTM_ILLEGAL_VALUE);
/* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
p_inq->inqparms = *p_inqparms;
-#if (BLE_INCLUDED == TRUE)
- p_inq->inqparms.mode = (UINT8)(p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) | (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
-#else
- p_inq->inqparms.mode = (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
-#endif
/* Initialize the inquiry variables */
p_inq->state = BTM_INQ_ACTIVE_STATE;
p_inq->p_inq_cmpl_cb = p_cmpl_cb;
p_inq->p_inq_results_cb = p_results_cb;
p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
- p_inq->inq_active = (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
+ p_inq->inq_active = p_inqparms->mode;
BTM_TRACE_DEBUG1("BTM_StartInquiry: p_inq->inq_active = 0x%02x", p_inq->inq_active);
@@ -872,8 +876,8 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p
if (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
{
/* BLE for now does not support filter condition for inquiry */
- if (btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
- p_inq->inqparms.duration) != BTM_SUCCESS)
+ if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
+ p_inq->inqparms.duration)) != BTM_CMD_STARTED)
{
BTM_TRACE_ERROR0("Err Starting LE Inquiry.");
p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
@@ -885,6 +889,10 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p
}
#endif /* end of BLE_INCLUDED */
+ /* we're done with this routine if BR/EDR inquiry is not desired. */
+ if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
+ return status;
+
#if (defined(BTM_BYPASS_EVENT_FILTERING) && BTM_BYPASS_EVENT_FILTERING == TRUE)
BTM_TRACE_WARNING0("BTM: Bypassing event filtering...");
p_inq->inqfilt_active = FALSE;
@@ -1954,7 +1962,7 @@ void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
UINT8 num_resp, xx;
BD_ADDR bda;
tINQ_DB_ENT *p_i;
- tBTM_INQ_RESULTS *p_cur;
+ tBTM_INQ_RESULTS *p_cur=NULL;
BOOLEAN is_new = TRUE;
BOOLEAN update = FALSE;
INT8 i_rssi;
@@ -1977,8 +1985,8 @@ void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode)
BTM_TRACE_DEBUG3 ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
#endif
- /* Only process the results if the inquiry is still active */
- if (!p_inq->inq_active)
+ /* Only process the results if the BR inquiry is still active */
+ if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK))
return;
STREAM_TO_UINT8 (num_resp, p);
@@ -2499,7 +2507,7 @@ tBTM_STATUS btm_initiate_rem_name (BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur,
*******************************************************************************/
void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
{
- tBTM_REMOTE_DEV_NAME rem_name = {0};
+ tBTM_REMOTE_DEV_NAME rem_name;
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
tBTM_CMPL_CB *p_cb = p_inq->p_remname_cmpl_cb;
UINT8 *p_n1;
@@ -2559,6 +2567,7 @@ void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hc
/* temporary buffer. */
p_n1 = (UINT8 *)rem_name.remote_bd_name;
rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
+ rem_name.remote_bd_name[rem_name.length] = 0;
rem_name.status = BTM_SUCCESS;
temp_evt_len = rem_name.length;
@@ -2567,6 +2576,7 @@ void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hc
*p_n1++ = *bdn++;
temp_evt_len--;
}
+ rem_name.remote_bd_name[rem_name.length] = 0;
}
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index e5f4c1506..0b8305111 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -117,6 +117,11 @@ typedef struct
#endif /* BTM_PWR_MGR_INCLUDED */
#if BLE_INCLUDED == TRUE
UINT8 is_le_link;
+ BD_ADDR conn_addr; /* local device address used for this connection */
+ UINT8 conn_addr_type; /* local device address type for this connection */
+ BD_ADDR active_remote_addr; /* remote address used on this connection */
+ UINT8 active_remote_addr_type; /* local device address type for this connection */
+
#endif
} tACL_CONN;
@@ -171,6 +176,10 @@ typedef struct
TIMER_LIST_ENT tx_power_timer;
tBTM_CMPL_CB *p_tx_power_cmpl_cb; /* Callback function to be called */
+#if BLE_INCLUDED == TRUE
+ tBTM_CMPL_CB *p_le_test_cmd_cmpl_cb; /* Callback function to be called when
+ LE test mode command has been sent successfully */
+#endif
BD_ADDR local_addr; /* BD_ADDR of the local device */
tBTM_VERSION_INFO local_version; /* Local Version Information */
BD_FEATURES local_features; /* Local features bit mask */
@@ -464,8 +473,7 @@ typedef struct
typedef struct
{
tBLE_ADDR_TYPE ble_addr_type; /* LE device type: public or random address */
- BD_ADDR reconn_addr; /* reconnect address */
- BD_ADDR cur_rand_addr; /* current random address */
+ tBLE_ADDR_TYPE static_addr_type; /* static address type */
BD_ADDR static_addr; /* static address */
#if SMP_INCLUDED == TRUE
@@ -491,17 +499,18 @@ typedef struct
DEV_CLASS dev_class; /* DEV_CLASS of the device */
LINK_KEY link_key; /* Device link key */
-#define BTM_SEC_AUTHORIZED BTM_SEC_FLAG_AUTHORIZED
-#define BTM_SEC_AUTHENTICATED BTM_SEC_FLAG_AUTHENTICATED
-#define BTM_SEC_ENCRYPTED BTM_SEC_FLAG_ENCRYPTED
+#define BTM_SEC_AUTHORIZED BTM_SEC_FLAG_AUTHORIZED /* 0x01 */
+#define BTM_SEC_AUTHENTICATED BTM_SEC_FLAG_AUTHENTICATED /* 0x02 */
+#define BTM_SEC_ENCRYPTED BTM_SEC_FLAG_ENCRYPTED /* 0x04 */
#define BTM_SEC_NAME_KNOWN 0x08
-#define BTM_SEC_LINK_KEY_KNOWN BTM_SEC_FLAG_LKEY_KNOWN
+#define BTM_SEC_LINK_KEY_KNOWN BTM_SEC_FLAG_LKEY_KNOWN /* 0x10 */
#define BTM_SEC_LINK_KEY_AUTHED 0x20
#define BTM_SEC_ROLE_SWITCHED 0x40
#define BTM_SEC_IN_USE 0x80
- tBTM_BD_NAME sec_bd_name; /* User friendly name of the device. (may be truncated to save space in dev_rec table) */
UINT8 sec_flags; /* Current device security state */
+
+ tBTM_BD_NAME sec_bd_name; /* User friendly name of the device. (may be truncated to save space in dev_rec table) */
BD_FEATURES features; /* Features suported by the device */
#define BTM_SEC_STATE_IDLE 0
@@ -525,6 +534,8 @@ typedef struct
UINT8 link_key_type; /* Type of key used in pairing */
BOOLEAN link_key_changed; /* Changed link key during current connection */
+#define BTM_MAX_PRE_SM4_LKEY_TYPE BTM_LKEY_TYPE_REMOTE_UNIT /* the link key type used by legacy pairing */
+
#define BTM_SM4_UNKNOWN 0x00
#define BTM_SM4_KNOWN 0x10
#define BTM_SM4_TRUE 0x11
@@ -552,6 +563,9 @@ typedef struct
UINT8 rs_disc_pending;
#endif
// btla-specific --
+#define BTM_SEC_NO_LAST_SERVICE_ID 0
+ UINT8 last_author_service_id; /* ID of last serviced authorized: Reset after each l2cap connection */
+
} tBTM_SEC_DEV_REC;
#define BTM_SEC_IS_SM4(sm) ((BOOLEAN)(BTM_SM4_TRUE == ((sm)&BTM_SM4_TRUE)))
@@ -676,6 +690,7 @@ typedef UINT8 tBTM_PAIRING_STATE;
#define BTM_PAIR_FLAGS_PIN_REQD 0x08 /* set this bit when pin_callback is called */
#define BTM_PAIR_FLAGS_PRE_FETCH_PIN 0x10 /* set this bit when pre-fetch pin */
#define BTM_PAIR_FLAGS_REJECTED_CONNECT 0x20 /* set this bit when rejected incoming connection */
+#define BTM_PAIR_FLAGS_WE_CANCEL_DD 0x40 /* set this bit when cancelling a bonding procedure */
typedef struct
{
@@ -1003,6 +1018,7 @@ extern void btm_reset_complete (void);
extern void btm_read_local_version_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_hci_buf_size_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len);
+extern void btm_read_local_ext_features_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_local_name_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_local_addr_complete (UINT8 *p, UINT16 evt_len);
extern void btm_get_local_features (void);
@@ -1010,7 +1026,7 @@ extern void btm_get_local_features (void);
#if (BLE_INCLUDED == TRUE)
extern void btm_read_ble_buf_size_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len);
-extern void btm_ble_add_2_white_list_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_add_2_white_list_complete(UINT8 status);
extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
extern void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
#endif /* BLE_INCLUDED */
@@ -1081,6 +1097,7 @@ extern void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res
extern void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec);
extern BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC *p_rec);
extern BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda);
+extern BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda);
#endif /* BLE_INCLUDED */
extern tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda);
@@ -1098,13 +1115,7 @@ extern void btm_acl_reset_paging (void);
extern void btm_acl_paging (BT_HDR *p, BD_ADDR dest);
extern void btm_acl_set_discing (BOOLEAN discing);
extern UINT8 btm_sec_clr_service_by_psm (UINT16 psm);
-
-#ifdef BRCM_VS
-extern void btm_brcm_feat_init(void);
-extern void btm_vs_reset_complete (void);
-extern void btm_brcm_arc_init (void);
-
-#endif
+extern void btm_sec_clr_temp_auth_service (BD_ADDR bda);
#ifdef __cplusplus
}
diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c
index 5a11404fa..f58023253 100644
--- a/stack/btm/btm_sco.c
+++ b/stack/btm/btm_sco.c
@@ -308,8 +308,6 @@ void btm_route_sco_data(BT_HDR *p_msg)
#endif
}
-
-
/*******************************************************************************
**
** Function BTM_WriteScoData
@@ -619,10 +617,7 @@ tBTM_STATUS BTM_CreateSco (BD_ADDR remote_bda, BOOLEAN is_orig, UINT16 pkt_types
{
if (md == BTM_PM_MD_PARK || md == BTM_PM_MD_SNIFF)
{
-/* Coverity: FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-*/
+ memset( (void*)&pm, 0, sizeof(pm));
pm.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &pm);
p->state = SCO_ST_PEND_UNPARK;
@@ -1447,6 +1442,8 @@ tBTM_STATUS BTM_RegForEScoEvts (UINT16 sco_inx, tBTM_ESCO_CBACK *p_esco_cback)
tBTM_STATUS BTM_ReadEScoLinkParms (UINT16 sco_inx, tBTM_ESCO_DATA *p_parms)
{
#if (BTM_MAX_SCO_LINKS>0)
+ UINT8 index;
+
BTM_TRACE_API1("BTM_ReadEScoLinkParms -> sco_inx 0x%04x", sco_inx);
if (sco_inx < BTM_MAX_SCO_LINKS &&
@@ -1455,8 +1452,23 @@ tBTM_STATUS BTM_ReadEScoLinkParms (UINT16 sco_inx, tBTM_ESCO_DATA *p_parms)
*p_parms = btm_cb.sco_cb.sco_db[sco_inx].esco.data;
return (BTM_SUCCESS);
}
+
+ if (sco_inx == BTM_FIRST_ACTIVE_SCO_INDEX)
+ {
+ for (index = 0; index < BTM_MAX_SCO_LINKS; index++)
+ {
+ if (btm_cb.sco_cb.sco_db[index].state >= SCO_ST_CONNECTED)
+ {
+ BTM_TRACE_API1("BTM_ReadEScoLinkParms the first active SCO index is %d",index);
+ *p_parms = btm_cb.sco_cb.sco_db[index].esco.data;
+ return (BTM_SUCCESS);
+ }
+ }
+ }
+
#endif
+ BTM_TRACE_API0("BTM_ReadEScoLinkParms cannot find the SCO index!");
memset(p_parms, 0, sizeof(tBTM_ESCO_DATA));
return (BTM_WRONG_MODE);
}
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index 956364e5d..212b11871 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -288,7 +288,7 @@ void BTM_SetSecurityMode (UINT8 security_mode)
{
UINT8 old_mode = btm_cb.security_mode;
- UINT8 sp_mode = HCI_SPD_MODE_ENABLED;
+ UINT8 sp_mode = HCI_SP_MODE_ENABLED;
UINT8 sp_debug_mode = HCI_SPD_MODE_DISABLED;
switch (security_mode)
@@ -777,6 +777,39 @@ UINT8 btm_sec_clr_service_by_psm (UINT16 psm)
/*******************************************************************************
**
+** Function btm_sec_clr_temp_auth_service
+**
+** Description Removes specified device record's temporary authorization
+** flag from the security database.
+**
+** Parameters Device address to be cleared
+**
+** Returns void.
+**
+*******************************************************************************/
+void btm_sec_clr_temp_auth_service (BD_ADDR bda)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec;
+
+ if ((p_dev_rec = btm_find_dev (bda)) == NULL)
+ {
+ BTM_TRACE_WARNING0 ("btm_sec_clr_temp_auth_service() - no dev CB");
+ return;
+ }
+
+ /* Reset the temporary authorized flag so that next time (untrusted) service is accessed autorization will take place */
+ if (p_dev_rec->last_author_service_id != BTM_SEC_NO_LAST_SERVICE_ID && p_dev_rec->p_cur_service)
+ {
+ BTM_TRACE_DEBUG6 ("btm_sec_clr_auth_service_by_psm [clearing device: %02x:%02x:%02x:%02x:%02x:%02x]",
+ bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+
+ p_dev_rec->last_author_service_id = BTM_SEC_NO_LAST_SERVICE_ID;
+ }
+}
+
+/*******************************************************************************
+**
+**
** Function BTM_SecClrUCDService
**
** Description
@@ -964,7 +997,18 @@ void BTM_DeviceAuthorized (BD_ADDR bd_addr, UINT8 res, UINT32 trusted_mask[])
{
p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED;
if (trusted_mask)
+ {
BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
+ }
+
+ /* Save the currently authorized service in case we are asked again
+ by another multiplexer layer */
+ if (!p_dev_rec->is_originator)
+ {
+ BTM_TRACE_DEBUG1("BTM_DeviceAuthorized: Setting last_author_service_id to %d",
+ p_dev_rec->p_cur_service->service_id);
+ p_dev_rec->last_author_service_id = p_dev_rec->p_cur_service->service_id;
+ }
}
if (p_dev_rec->sec_state != BTM_SEC_STATE_AUTHORIZING)
@@ -1008,6 +1052,8 @@ tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr
#if SMP_INCLUDED == TRUE
tACL_CONN *p=NULL;
BOOLEAN is_le_slave_role=FALSE;
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type;
#endif
BTM_TRACE_API6 ("BTM_SecBond BDA: %02x:%02x:%02x:%02x:%02x:%02x",
bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
@@ -1100,10 +1146,11 @@ tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr
}
+ BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
/* LE device, do SMP pairing */
- if (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+ if (dev_type == BT_DEVICE_TYPE_BLE)
{
- if (SMP_Pair(p_dev_rec->bd_addr) == SMP_STARTED)
+ if (SMP_Pair(bd_addr) == SMP_STARTED)
{
p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
return BTM_CMD_STARTED;
@@ -1275,7 +1322,12 @@ tBTM_STATUS BTM_SecBondCancel (BD_ADDR bd_addr)
return BTM_NO_RESOURCES;
}
-
+ if (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME)
+ {
+ BTM_CancelRemoteDeviceName();
+ btm_cb.pairing_flags |= BTM_PAIR_FLAGS_WE_CANCEL_DD;
+ return BTM_CMD_STARTED;
+ }
return BTM_NOT_AUTHORIZED;
}
}
@@ -1450,7 +1502,8 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBTM_SEC_CBACK *p_callback,
*******************************************************************************/
static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason)
{
- UINT8 old_state = p_dev_rec->sec_state;
+ UINT8 old_state = p_dev_rec->sec_state;
+ tBTM_STATUS status = BTM_CMD_STARTED;
BTM_TRACE_EVENT2 ("btm_sec_send_hci_disconnect: handle:0x%x, reason=0x%x",
p_dev_rec->hci_handle, reason);
@@ -1466,18 +1519,19 @@ static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UIN
{
BTM_TRACE_ERROR0("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect");
p_dev_rec->rs_disc_pending = BTM_SEC_DISC_PENDING;
- return BTM_SUCCESS;
+ status = BTM_SUCCESS;
}
+ else
#endif
/* Tear down the HCI link */
if (!btsnd_hcic_disconnect (p_dev_rec->hci_handle, reason))
{
/* could not send disconnect. restore old state */
p_dev_rec->sec_state = old_state;
- return(BTM_NO_RESOURCES);
+ status = BTM_NO_RESOURCES;
}
}
- return(BTM_CMD_STARTED);
+ return (status);
}
/*******************************************************************************
@@ -1916,23 +1970,23 @@ void BTM_SetOutService(BD_ADDR bd_addr, UINT8 service_id, UINT32 mx_chan_id)
*************************************************************************/
/*******************************************************************************
**
-** Function btm_sec_check_upgrade
+** Function btm_sec_is_upgrade_possible
**
-** Description This function is called to check if the existing link key
-** needs to be upgraded.
+** Description This function returns TRUE if the existing link key
+** can be upgraded or if the link key does not exist.
**
-** Returns void
+** Returns BOOLEAN
**
*******************************************************************************/
-static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
+static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
{
- tBTM_SP_UPGRADE evt_data;
UINT16 mtm_check = is_originator ? BTM_SEC_OUT_MITM : BTM_SEC_IN_MITM;
+ BOOLEAN is_possible = TRUE;
if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)
{
-
- BTM_TRACE_DEBUG5 ("btm_sec_check_upgrade id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x",
+ is_possible = FALSE;
+ BTM_TRACE_DEBUG5 ("btm_sec_is_upgrade_possible id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x",
p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps,
mtm_check, p_dev_rec->p_cur_service->security_flags);
/* Already have a link key to the connected peer. Is the link key secure enough?
@@ -1943,26 +1997,56 @@ static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_origi
&& (p_dev_rec->rmt_io_caps < BTM_IO_CAP_MAX) /* a valid peer IO cap */
&& (btm_sec_io_map[p_dev_rec->rmt_io_caps][btm_cb.devcb.loc_io_caps])) /* authenticated link key is possible */
{
- BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
/* upgrade is possible: check if the application wants the upgrade.
* If the application is configured to use a global MITM flag,
* it probably would not want to upgrade the link key based on the security level database */
- memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- evt_data.upgrade = TRUE;
- if (btm_cb.api.p_sp_callback)
- (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
+ is_possible = TRUE;
+ }
+ }
+ BTM_TRACE_DEBUG2 ("btm_sec_is_upgrade_possible is_possible:%d sec_flags:0x%x", is_possible, p_dev_rec->sec_flags);
+ return is_possible;
+}
- BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade);
- if (evt_data.upgrade)
- {
- /* if the application confirms the upgrade, set the upgrade bit */
- p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
+/*******************************************************************************
+**
+** Function btm_sec_check_upgrade
+**
+** Description This function is called to check if the existing link key
+** needs to be upgraded.
+**
+** Returns void
+**
+*******************************************************************************/
+static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
+{
+ tBTM_SP_UPGRADE evt_data;
- /* Clear the link key known to go through authentication/pairing again */
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
- p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED;
- BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags);
- }
+ BTM_TRACE_DEBUG0 ("btm_sec_check_upgrade...");
+
+ /* Only check if link key already exists */
+ if (!(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN))
+ return;
+ if (btm_sec_is_upgrade_possible (p_dev_rec, is_originator) == TRUE)
+ {
+ BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
+ /* upgrade is possible: check if the application wants the upgrade.
+ * If the application is configured to use a global MITM flag,
+ * it probably would not want to upgrade the link key based on the security level database */
+ memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+ evt_data.upgrade = TRUE;
+ if (btm_cb.api.p_sp_callback)
+ (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
+
+ BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade);
+ if (evt_data.upgrade)
+ {
+ /* if the application confirms the upgrade, set the upgrade bit */
+ p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
+
+ /* Clear the link key known to go through authentication/pairing again */
+ p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
+ p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED;
+ BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags);
}
}
}
@@ -2085,15 +2169,17 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
/* we will process one after another */
if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) )
{
- BTM_TRACE_EVENT2 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed state: %s",
- psm, btm_pair_state_descr(btm_cb.pairing_state));
+ BTM_TRACE_EVENT4 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed state: %s mode:%d, sm4:0x%x",
+ psm, btm_pair_state_descr(btm_cb.pairing_state), btm_cb.security_mode, p_dev_rec->sm4);
+ BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags);
rc = BTM_CMD_STARTED;
if ((BTM_SEC_MODE_SP != btm_cb.security_mode)
|| ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4))
+ || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))
)
{
- BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags);
- /* legacy mode - local is legacy or local is lisbon/peer is legacy */
+ /* legacy mode - local is legacy or local is lisbon/peer is legacy
+ * or SM4 with no possibility of link key upgrade */
if (is_originator)
{
if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
@@ -2256,11 +2342,16 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
p_dev_rec->p_callback = p_callback;
- /* Although authentication and encryption are per connection */
- /* authorization is per access request. For example when serial connection */
- /* is up and authorized and client requests to read file (access to other */
- /* scn, we need to request user's permission again. */
- p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED;
+ if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
+ || p_dev_rec->last_author_service_id != p_dev_rec->p_cur_service->service_id)
+ {
+ /* Although authentication and encryption are per connection
+ ** authorization is per access request. For example when serial connection
+ ** is up and authorized and client requests to read file (access to other
+ ** scn), we need to request user's permission again.
+ */
+ p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED;
+ }
if (BTM_SEC_IS_SM4(p_dev_rec->sm4))
{
@@ -2311,6 +2402,7 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_SEC_SERV_REC *p_serv_rec;
tBTM_STATUS rc;
+ UINT16 security_required;
BTM_TRACE_DEBUG1 ("btm_sec_mx_access_request is_originator:%d", is_originator);
/* Find or get oldest record */
@@ -2337,8 +2429,41 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o
BTM_TRACE_EVENT4 ("btm_sec_mx_access_request service PSM:%d Proto:%d SCN:%d delayed state: %s",
psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state));
- btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data);
- return BTM_CMD_STARTED;
+ rc = BTM_CMD_STARTED;
+ security_required = p_serv_rec->security_flags;
+ if ((BTM_SEC_MODE_SP != btm_cb.security_mode)
+ || ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4))
+ || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))
+ )
+ {
+ /* legacy mode - local is legacy or local is lisbon/peer is legacy
+ * or SM4 with no possibility of link key upgrade */
+ if (is_originator)
+ {
+ if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
+ ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
+ ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)))
+ )
+ {
+ rc = BTM_SUCCESS;
+ }
+ }
+ else
+ {
+ if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
+ ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
+ ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)))
+ )
+ {
+ rc = BTM_SUCCESS;
+ }
+ }
+ }
+ if (rc == BTM_CMD_STARTED)
+ {
+ btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data);
+ return rc;
+ }
}
p_dev_rec->p_cur_service = p_serv_rec;
@@ -2487,7 +2612,9 @@ static void btm_sec_bond_cancel_complete (void)
if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) ||
(BTM_PAIR_STATE_WAIT_LOCAL_PIN == btm_cb.pairing_state &&
- BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags))
+ BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags) ||
+ (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME &&
+ BTM_PAIR_FLAGS_WE_CANCEL_DD & btm_cb.pairing_flags))
{
/* for dedicated bonding in legacy mode, authentication happens at "link level"
* btm_sec_connected is called with failed status.
@@ -2894,6 +3021,12 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT
if (p_bd_addr && memcmp (btm_cb.pairing_bda, p_bd_addr, BD_ADDR_LEN) == 0)
{
BTM_TRACE_EVENT2 ("btm_sec_rmt_name_request_complete() continue bonding sm4: 0x%04x, status:0x%x", p_dev_rec->sm4, status);
+ if(btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_CANCEL_DD)
+ {
+ btm_sec_bond_cancel_complete();
+ return;
+ }
+
if (status != HCI_SUCCESS)
{
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
@@ -3531,6 +3664,7 @@ void btm_rem_oob_req (UINT8 *p)
memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
memcpy (evt_data.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);
BCM_STRNCPY_S((char *)evt_data.bd_name, sizeof(evt_data.bd_name), (char *)p_dev_rec->sec_bd_name, BTM_MAX_REM_BD_NAME_LEN+1);
+ evt_data.bd_name[BTM_MAX_REM_BD_NAME_LEN] = 0;
btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP);
if ((*btm_cb.api.p_sp_callback) (BTM_SP_RMT_OOB_EVT, (tBTM_SP_EVT_DATA *)&evt_data) == BTM_NOT_AUTHORIZED)
@@ -3834,10 +3968,12 @@ void btm_sec_mkey_comp_event (UINT16 handle, UINT8 status, UINT8 key_flg)
void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
-
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ tACL_CONN *p_acl;
+#endif
BTM_TRACE_EVENT3 ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d",
status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable);
- BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
+ BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", (p_dev_rec) ? p_dev_rec->sec_flags : 0 );
/* For transaction collision we need to wait and repeat. There is no need */
/* for random timeout because only slave should receive the result */
@@ -3860,8 +3996,11 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED;
BTM_TRACE_DEBUG1 ("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
+
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+ p_acl = btm_bda_to_acl(p_dev_rec->bd_addr);
+
+ if (p_acl && p_acl->is_le_link)
{
btm_ble_link_encrypted(p_dev_rec->bd_addr, encr_enable);
return;
@@ -4004,6 +4143,9 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
if (status == HCI_SUCCESS)
{
p_dev_rec = btm_sec_alloc_dev (bda);
+#if BLE_INCLUDED == TRUE
+ p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
+#endif
}
else
{
@@ -4061,6 +4203,8 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
#endif
+ p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
+
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
&& (memcmp (btm_cb.pairing_bda, bda, BD_ADDR_LEN) == 0) )
{
@@ -4208,8 +4352,6 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
if (btm_cb.btm_def_link_policy)
BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
#endif
-
- BTM_SetLinkSuperTout (p_acl_cb->remote_addr, btm_cb.btm_def_link_super_tout);
}
btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, FALSE);
@@ -4338,6 +4480,8 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
if (!p_dev_rec)
return;
+ p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
+
#if BTM_DISC_DURING_RS == TRUE
BTM_TRACE_ERROR0("btm_sec_disconnected - Clearing Pending flag");
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
@@ -4382,7 +4526,7 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
p_dev_rec->enc_key_size = 0;
- btm_ble_resume_bg_conn(NULL, TRUE);
+ btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, FALSE);
/* see sec_flags processing in btm_acl_removed */
#endif
p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
@@ -4421,7 +4565,10 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t
p_dev_rec->link_key_type = key_type;
p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
-
+#if (BLE_INCLUDED == TRUE)
+ /* BR/EDR connection, update the encryption key size to be 16 as always */
+ p_dev_rec->enc_key_size = 16;
+#endif
memcpy (p_dev_rec->link_key, p_link_key, LINK_KEY_LEN);
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
@@ -5059,16 +5206,33 @@ static UINT8 btm_sec_start_authorization (tBTM_SEC_DEV_REC *p_dev_rec)
else
service_id = 0;
- p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING;
- result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr,
+ /* Send authorization request if not already sent during this service connection */
+ if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
+ || p_dev_rec->last_author_service_id != service_id)
+ {
+ p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING;
+ result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr,
p_dev_rec->dev_class,
p_dev_rec->sec_bd_name,
p_service_name,
service_id,
p_dev_rec->is_originator);
+ }
+
+ else /* Already authorized once for this L2CAP bringup */
+ {
+ BTM_TRACE_DEBUG1 ("btm_sec_start_authorization: (Ignoring extra Authorization prompt for service %d)", service_id);
+ return (BTM_SUCCESS);
+ }
+
if (result == BTM_SUCCESS)
{
p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED;
+
+ /* Save the currently authorized service in case we are asked again by another multiplexer layer */
+ if (!p_dev_rec->is_originator)
+ p_dev_rec->last_author_service_id = service_id;
+
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
}
return(result);
@@ -5088,7 +5252,7 @@ static UINT8 btm_sec_start_authorization (tBTM_SEC_DEV_REC *p_dev_rec)
*******************************************************************************/
BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[])
{
- int trusted_inx;
+ UINT32 trusted_inx;
for (trusted_inx = 0; trusted_inx < BTM_SEC_SERVICE_ARRAY_SIZE; trusted_inx++)
{
if (p_mask[trusted_inx] != BTM_SEC_TRUST_ALL)
@@ -5611,6 +5775,30 @@ BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda)
/*******************************************************************************
**
+** Function btm_sec_is_le_capable_dev
+**
+** Description Is the specified device is dual mode or LE only device
+**
+** Returns TRUE - dev is a dual mode
+**
+*******************************************************************************/
+BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec= btm_find_dev (bda);
+ BOOLEAN le_capable = FALSE;
+
+#if (BLE_INCLUDED== TRUE)
+ if (p_dev_rec && ((p_dev_rec->device_type == BT_DEVICE_TYPE_DUMO) ||
+ (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) ) )
+ {
+ le_capable = TRUE;
+ }
+#endif
+ return le_capable;
+}
+
+/*******************************************************************************
+**
** Function btm_sec_find_bonded_dev
**
** Description Find a bonded device starting from the specified index
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index 63803bdc7..4aa82ef7e 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -150,10 +150,17 @@ static void btu_hcif_encyption_key_refresh_cmpl_evt (UINT8 *p, UINT16 evt_len);
*******************************************************************************/
static void btu_hcif_store_cmd (UINT8 controller_id, BT_HDR *p_buf)
{
- tHCI_CMD_CB * p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
+ tHCI_CMD_CB *p_hci_cmd_cb;
UINT16 opcode;
BT_HDR *p_cmd;
- UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+ UINT8 *p;
+
+ /* Validate controller ID */
+ if (controller_id >= BTU_MAX_LOCAL_CTRLS)
+ return;
+
+ p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
+ p = (UINT8 *)(p_buf + 1) + p_buf->offset;
/* get command opcode */
STREAM_TO_UINT16 (opcode, p);
@@ -1033,6 +1040,10 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
btm_read_local_features_complete (p, evt_len);
break;
+ case HCI_READ_LOCAL_EXT_FEATURES:
+ btm_read_local_ext_features_complete (p, evt_len);
+ break;
+
case HCI_READ_LOCAL_NAME:
btm_read_local_name_complete (p, evt_len);
break;
@@ -1075,7 +1086,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
break;
case HCI_BLE_ADD_WHITE_LIST:
- btm_ble_add_2_white_list_complete(p, evt_len);
+ btm_ble_add_2_white_list_complete(*p);
break;
case HCI_BLE_CLEAR_WHITE_LIST:
@@ -1103,6 +1114,11 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
btm_ble_write_adv_enable_complete(p);
break;
+ case HCI_BLE_TRANSMITTER_TEST:
+ case HCI_BLE_RECEIVER_TEST:
+ case HCI_BLE_TEST_END:
+ btm_ble_test_command_complete(p);
+ break;
#endif /* (BLE_INCLUDED == TRUE) */
default:
@@ -1470,9 +1486,7 @@ void btu_hcif_cmd_timeout (UINT8 controller_id)
UINT8 *p;
void *p_cplt_cback = NULL;
UINT16 opcode;
-// btla-specific ++
UINT16 event;
-// btla-specific --
#if (defined(BTU_CMD_CMPL_TOUT_DOUBLE_CHECK) && BTU_CMD_CMPL_TOUT_DOUBLE_CHECK == TRUE)
if (!(p_hci_cmd_cb->checked_hcisu))
@@ -1586,10 +1600,8 @@ void btu_hcif_cmd_timeout (UINT8 controller_id)
}
/* fake a command complete; first create a fake event */
-// btla-specific ++
event = HCI_ERR_UNSPECIFIED;
btu_hcif_hdl_command_complete (opcode, (UINT8 *)&event, 1, p_cplt_cback, controller_id);
-// btla-specific --
break;
}
@@ -2202,51 +2214,9 @@ static void btu_ble_process_adv_pkt (UINT8 *p, UINT16 evt_len)
btm_ble_process_adv_pkt(p);
}
-
static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
{
- UINT8 role, status, bda_type;
- UINT16 handle;
- BD_ADDR bda;
- UINT16 conn_interval, conn_latency, conn_timeout;
- UINT16 combined_mode;
-
- STREAM_TO_UINT8 (status, p);
- STREAM_TO_UINT16 (handle, p);
- STREAM_TO_UINT8 (role, p);
- STREAM_TO_UINT8 (bda_type, p);
- STREAM_TO_BDADDR (bda, p);
- STREAM_TO_UINT16 (conn_interval, p);
- STREAM_TO_UINT16 (conn_latency, p);
- STREAM_TO_UINT16 (conn_timeout, p);
-
- handle = HCID_GET_HANDLE (handle);
-
- if (status == 0)
- {
- btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role);
-
- l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
- conn_latency, conn_timeout);
- }
- else
- {
- /* If we are LE connectable, check if we need to start advertising again */
- if (btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE)
- {
- tACL_CONN *pa = &btm_cb.acl_db[0];
- UINT16 xx;
-
- for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
- {
- /* If any other LE link is up, we are still not connectable */
- if (pa->in_use && pa->is_le_link)
- return;
- }
- combined_mode = (btm_cb.ble_ctr_cb.inq_var.connectable_mode | btm_cb.btm_inq_vars.connectable_mode);
- btm_ble_set_connectability ( combined_mode );
- }
- }
+ btm_ble_conn_complete(p, evt_len);
}
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len)
@@ -2267,7 +2237,7 @@ static void btu_ble_proc_ltk_req (UINT8 *p, UINT16 evt_len)
STREAM_TO_UINT16(handle, p);
pp = p + 8;
STREAM_TO_UINT16(ediv, pp);
-#if SMP_INCLUDED == TRUE
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
btm_ble_ltk_request(handle, p, ediv);
#endif
/* This is empty until an upper layer cares about returning event */
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index 48ce48991..514751804 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -169,7 +169,10 @@ BTU_API UINT32 btu_task (UINT32 param)
#if (defined(HCISU_H4_INCLUDED) && HCISU_H4_INCLUDED == TRUE)
/* wait an event that HCISU is ready */
- GKI_wait(0xFFFF, 0);
+ event = GKI_wait (0xFFFF, 0);
+ if (event & EVENT_MASK(GKI_SHUTDOWN_EVT))
+ /* indicates BT ENABLE abort */
+ return (0);
#endif
/* Initialize the mandatory core stack control blocks
(BTU, BTM, L2CAP, and SDP)
@@ -302,6 +305,14 @@ BTU_API UINT32 btu_task (UINT32 param)
GKI_freebuf (p_msg);
break;
+ case BT_EVT_TO_STOP_TIMER:
+ if (btu_cb.timer_queue.p_first == NULL)
+ {
+ GKI_stop_timer(TIMER_0);
+ }
+ GKI_freebuf (p_msg);
+ break;
+
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
case BT_EVT_TO_START_QUICK_TIMER :
GKI_start_timer (TIMER_2, QUICK_TIMER_TICKS, TRUE);
@@ -440,10 +451,6 @@ BTU_API UINT32 btu_task (UINT32 param)
btm_ble_timeout(p_tle);
break;
- case BTU_TTYPE_BLE_SCAN_PARAM_IDLE:
- btm_ble_scan_param_idle();
- break;
-
case BTU_TTYPE_ATT_WAIT_FOR_RSP:
gatt_rsp_timeout(p_tle);
break;
@@ -602,14 +609,27 @@ UINT32 btu_remaining_time (TIMER_LIST_ENT *p_tle)
*******************************************************************************/
void btu_stop_timer (TIMER_LIST_ENT *p_tle)
{
+ BT_HDR *p_msg;
GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle);
- /* if timer list is empty stop periodic GKI timer */
- if (btu_cb.timer_queue.p_first == NULL)
+ /* if timer is stopped on other than BTU task */
+ if (GKI_get_taskid() != BTU_TASK)
{
- GKI_stop_timer(TIMER_0);
+ /* post event to stop timer in BTU task */
+ if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
+ {
+ p_msg->event = BT_EVT_TO_STOP_TIMER;
+ GKI_send_msg (BTU_TASK, TASK_MBOX_0, p_msg);
+ }
+ }
+ else
+ {
+ /* if timer list is empty stop periodic GKI timer */
+ if (btu_cb.timer_queue.p_first == NULL)
+ {
+ GKI_stop_timer(TIMER_0);
+ }
}
-
}
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
diff --git a/stack/gap/gap_api.c b/stack/gap/gap_api.c
new file mode 100644
index 000000000..d17895d3a
--- /dev/null
+++ b/stack/gap/gap_api.c
@@ -0,0 +1,903 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#include "gap_int.h"
+#include "btm_int.h"
+#include "gki.h"
+#include "btu.h"
+
+/*******************************************************************************
+**
+** Function GAP_SetDiscoverableMode
+**
+** Description This function is called to allow or disallow a service to
+** discovered (Inquiry Scans).
+**
+** Parameters: mode - GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE,
+** or GAP_GENERAL_DISCOVERABLE
+**
+** duration - Amount of time for the duration of an inquiry scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** If a value of '0' is entered the default of
+** 0x0012 (11.25 msecs) will be used.
+** Note: The duration must be less than or equal to
+** the interval.
+**
+** interval - Amount of time between the start of two inquiry scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+** If a value of '0' is entered the default of
+** 0x800 (1.28 secs) will be used.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+UINT16 GAP_SetDiscoverableMode (UINT16 mode, UINT16 duration, UINT16 interval)
+{
+ tBTM_STATUS status;
+
+ status = BTM_SetDiscoverability(mode, duration, interval);
+
+ return (gap_convert_btm_status (status));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ReadDiscoverableMode
+**
+** Description This function is called to retrieve the current discoverable mode
+** for the local device.
+**
+** Parameters: duration - pointer to the amount of time of an inquiry scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** interval - pointer to the amount of time between the start of
+** two inquiry scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**
+** Returns GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE, or
+** GAP_GENERAL_DISCOVERABLE
+**
+*******************************************************************************/
+UINT16 GAP_ReadDiscoverableMode (UINT16 *duration, UINT16 *interval)
+{
+ return (BTM_ReadDiscoverability(duration, interval));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SetConnectableMode
+**
+** Description This function is called to allow or disallow a
+** connections on the local device.
+**
+** Parameters: mode - GAP_NON_CONNECTABLE, GAP_CONNECTABLE,
+**
+** duration - Amount of time for the duration of a page scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** If a value of '0' is entered the default of
+** 0x0012 (11.25 msecs) will be used.
+** Note: The duration must be less than or equal to
+** the interval.
+**
+** interval - Amount of time between the start of two page scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+** If a value of '0' is entered the default of
+** 0x800 (1.28 secs) will be used.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+UINT16 GAP_SetConnectableMode (UINT16 mode, UINT16 duration, UINT16 interval)
+{
+ tBTM_STATUS status;
+
+ status = BTM_SetConnectability(mode, duration, interval);
+
+ return (gap_convert_btm_status (status));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_FindAddrByName
+**
+** Description This function is called to retrieve a device address given
+** a device name. It first looks in the current local inquiry
+** database for the device with the specified name. If not found
+** it initiates a general inquiry. Upon completion, it retrieves
+** the name for each device until a match is found or all devices
+** have been checked. Note: This process can take a while to
+** complete.
+**
+** Parameters: devname -
+**
+** inqparms - pointer to the inquiry information
+** mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+** duration - length in 1.28 sec intervals
+** max_resps - maximum amount of devices to search for before ending the inquiry
+** filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+** GAP_FILTER_COND_BD_ADDR
+** filter_cond - value for the filter (based on filter_cond_type)
+**
+**
+** Returns BT_PASS if the name was immediately available. (BD_ADDR is returned)
+** GAP_CMD_INITIATED if an inquiry has been initiated
+**
+*******************************************************************************/
+UINT16 GAP_FindAddrByName (BD_NAME devname, tGAP_INQ_PARMS *p_inq_parms, tGAP_CALLBACK *p_addr_cb,
+ BD_ADDR bd_addr)
+{
+ UINT16 status;
+ tBTM_STATUS btm_status;
+
+
+ /* If the remote name is retrieved automatically during an inquiry search the local db first */
+ if ((status = gap_find_local_addr_by_name (devname, bd_addr)) != BT_PASS)
+ {
+ /* If this code is used, the name wasn't in the current inquiry database */
+ /* A general inquiry must now be initiated */
+ if (gap_cb.findaddr_cb.in_use == FALSE)
+ {
+ gap_cb.findaddr_cb.p_cback = p_addr_cb;
+ gap_cb.findaddr_cb.p_cur_inq = (tBTM_INQ_INFO *) NULL; /* Reset to the beginning of the database */
+ BCM_STRNCPY_S ((char *)gap_cb.findaddr_cb.results.devname, sizeof(gap_cb.findaddr_cb.results.devname), (char *)devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ /* make sure we have an end of string char */
+ gap_cb.findaddr_cb.results.devname[BTM_MAX_REM_BD_NAME_LEN] = 0;
+
+ btm_status = BTM_StartInquiry (p_inq_parms, (tBTM_INQ_RESULTS_CB *) NULL,
+ (tBTM_CMPL_CB *) gap_find_addr_inq_cb);
+ gap_cb.findaddr_cb.in_use = TRUE;
+
+ /* convert the error code into a GAP code and check the results for any errors */
+ if ((status = gap_convert_btm_status (btm_status)) == GAP_CMD_INITIATED)
+ gap_cb.findaddr_cb.in_use = TRUE;
+ }
+ else
+ status = GAP_ERR_BUSY;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ReadConnectableMode
+**
+** Description This function is called to retrieve the current connectability
+** mode for the local device.
+**
+** Parameters: duration - pointer to the amount of time of an page scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** interval - pointer to the amount of time between the start of
+** two page scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**
+** Returns GAP_NON_CONNECTABLE, GAP_CONNECTABLE
+**
+*******************************************************************************/
+
+UINT16 GAP_ReadConnectableMode (UINT16 *duration, UINT16 *interval)
+{
+ return (BTM_ReadConnectability(duration, interval));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SetSecurityMode
+**
+** Description Set security mode for the device
+**
+** Returns void
+**
+*******************************************************************************/
+void GAP_SetSecurityMode (UINT8 sec_mode)
+{
+ BTM_SetSecurityMode (sec_mode);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_Bond
+**
+** Description This function is called to perform bonding with peer device
+**
+** Parameters: bd_addr - Address of the device to bond
+** pin_len - length in bytes of the PIN Code
+** p_pin - pointer to array with the PIN Code
+** trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+UINT8 GAP_Bond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+ return ((UINT8) BTM_SecBond (bd_addr, pin_len, p_pin, trusted_mask));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SecRegister
+**
+** Description Application manager calls this function to register for
+** security services. There can be one and only one application
+** saving link keys. BTM allows only first registration.
+**
+** Returns TRUE if registered OK, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GAP_SecRegister (tBTM_APPL_INFO *p_cb_info)
+{
+ return (BTM_SecRegister (p_cb_info));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_PinRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** PIN code request.
+**
+** Parameters: bd_addr - Address of the device for which PIN was requested
+** res - result of the operation BTM_SUCCESS if success
+** pin_len - length in bytes of the PIN Code
+** p_pin - pointer to array with the PIN Code
+** trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+void GAP_PinRsp (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+ BTM_PINCodeReply (bd_addr, res, pin_len, p_pin, trusted_mask);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_AuthorizeRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** authorization request
+**
+** Parameters: bd_addr - Address of the device for which PIN was requested
+** res - result of the operation BTM_SUCCESS if success
+** trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+void GAP_AuthorizeRsp (BD_ADDR bd_addr, UINT8 res, UINT32 trusted_mask[])
+{
+ BTM_DeviceAuthorized (bd_addr, res, trusted_mask);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SetPairableMode
+**
+** Description This function is called to allow or disallow pairing
+** on the local device.
+**
+** Parameters: mode - GAP_ALLOW_PAIRING, GAP_DISALLOW_PAIRING
+** connect_only_pairable - TRUE or FALSE connect only to paired devices
+**
+** callback - The callback is called when a pin number is requested.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+
+UINT16 GAP_SetPairableMode (UINT16 mode, BOOLEAN connect_only_paired)
+{
+ tBTM_STATUS btm_status;
+ UINT16 status = BT_PASS;
+
+ if (mode == GAP_ALLOW_PAIRING)
+ {
+ btm_status = BTM_SetConnectability(BTM_CONNECTABLE, 0, 0);
+
+ if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+ BTM_SetPairableMode (TRUE, connect_only_paired);
+ }
+ else if (mode == GAP_DISALLOW_PAIRING)
+ {
+ BTM_SetPairableMode (FALSE, connect_only_paired);
+ }
+ else
+ {
+ GAP_TRACE_ERROR1 ("GAP_SetPairableMode: illegal mode %d", mode);
+ status = GAP_ERR_ILL_MODE;
+ }
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_StartInquiry
+**
+** Description This function initiates a single inquiry.
+**
+** Parameters: p_inqparms - pointer to the inquiry information
+** mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+** duration - length in 1.28 sec intervals
+** max_resps - maximum amount of devices to search for before ending the inquiry
+** filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+** GAP_FILTER_COND_BD_ADDR
+** filter_cond - value for the filter (based on filter_cond_type)
+**
+** p_results_cb - Pointer to the callback routine which gets called
+** upon receipt of an inquiry result. If this field is
+** NULL, the application is not notified.
+**
+** p_cmpl_cb - Pointer to the callback routine which gets called
+** upon completion. If this field is NULL, the
+** application is not notified when completed.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+UINT16 GAP_StartInquiry (tGAP_INQ_PARMS *p_inq_parms, tGAP_CALLBACK *p_results_cb, tGAP_CALLBACK *p_cmpl_cb)
+{
+ tGAP_INFO *p_cb;
+ tBTM_STATUS btm_status;
+ UINT16 retval;
+
+ /*** Make sure the parameters are valid before continuing ***/
+ if (p_inq_parms->mode != GAP_GENERAL_INQUIRY && p_inq_parms->mode != GAP_LIMITED_INQUIRY)
+ return (GAP_ERR_ILL_MODE);
+
+ if (p_inq_parms->duration < GAP_MIN_INQUIRY_LEN ||
+ p_inq_parms->duration > GAP_MAX_INQUIRY_LENGTH)
+ return (GAP_ERR_ILL_INQ_TIME);
+
+ /*** get a control block for this operation ***/
+ if ((p_cb = gap_allocate_cb()) != NULL)
+ {
+ p_cb->gap_cback = p_cmpl_cb;
+ p_cb->gap_inq_rslt_cback = p_results_cb;
+ p_cb->event = GAP_EVT_INQUIRY_COMPLETE; /* Return event expected */
+
+ btm_status = BTM_StartInquiry(p_inq_parms, gap_inq_results_cb,
+ (tBTM_CMPL_CB *) gap_cb.btm_cback[p_cb->index]);
+
+ /* convert the error code into a GAP code and check the results for any errors */
+ if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+ gap_free_cb(p_cb); /* Error starting the inquiry */
+ }
+ else
+ retval = GAP_ERR_NO_CTRL_BLK;
+
+ return (retval);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_StartPeriodicInquiry
+**
+** Description This function initiates a periodic inquiry.
+**
+** Parameters: p_inqparms - pointer to the inquiry information
+** mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+** duration - length in 1.28 sec intervals
+** max_resps - maximum amount of devices to search for before ending the inquiry
+** filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+** GAP_FILTER_COND_BD_ADDR
+** filter_cond - value for the filter (based on filter_cond_type)
+**
+** min_time - Minimum amount of time between consecutive inquiries.
+** The value is in 1.28 second intervals.
+** Range: 0x0002 - 0xFFFE (2.56 - 83883.52 seconds)
+**
+** max_time - Maximum amount of time between consecutive inquiries.
+** The value is in 1.28 sec intervals.
+** Range: 0x0003 - 0xFFFF (3.84 - 83884.8 seconds)
+**
+** p_results_cb - Pointer to the callback routine which gets called
+** upon receipt of an inquiry result. If this field is
+** NULL, the application is not notified.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+
+UINT16 GAP_StartPeriodicInquiry (tGAP_INQ_PARMS *p_inq_parms, UINT16 min_time,
+ UINT16 max_time, tGAP_CALLBACK *p_results_cb)
+{
+ tGAP_INFO *p_cb;
+ tBTM_STATUS btm_status;
+ UINT16 retval = BT_PASS;
+
+ /*** Make sure the parameters are valid before continuing ***/
+ if (p_inq_parms->mode != GAP_GENERAL_INQUIRY && p_inq_parms->mode != GAP_LIMITED_INQUIRY)
+ return (GAP_ERR_ILL_MODE);
+
+ if (p_inq_parms->duration < GAP_MIN_INQUIRY_LEN ||
+ p_inq_parms->duration > GAP_MAX_INQUIRY_LENGTH ||
+ min_time <= p_inq_parms->duration ||
+ min_time < GAP_PER_INQ_MIN_MIN_PERIOD ||
+ min_time > GAP_PER_INQ_MAX_MIN_PERIOD ||
+ max_time <= min_time ||
+ max_time < GAP_PER_INQ_MIN_MAX_PERIOD)
+ {
+ return (GAP_ERR_ILL_INQ_TIME);
+ }
+
+ /*** get a control block for this operation ***/
+ if ((p_cb = gap_allocate_cb()) != NULL)
+ {
+ p_cb->gap_inq_rslt_cback = p_results_cb;
+ p_cb->event = GAP_EVT_INQUIRY_COMPLETE; /* mark the inquiry event active */
+
+ btm_status = BTM_SetPeriodicInquiryMode(p_inq_parms, max_time, min_time,
+ gap_inq_results_cb);
+
+ /* convert the error code into a GAP code and check the results for any errors */
+ if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+ gap_free_cb(p_cb); /* Error starting the inquiry */
+ }
+ else
+ retval = GAP_ERR_NO_CTRL_BLK;
+
+ return (retval);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_CancelInquiry
+**
+** Description This function cancels a single inquiry (if in progress)
+**
+** Parameters: None
+**
+** Returns BOOLEAN (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+UINT16 GAP_CancelInquiry(void)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+ tBTM_STATUS btm_status;
+ UINT16 status;
+
+ btm_status = BTM_CancelInquiry();
+ if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+ {
+ /* Free the control block that is waiting for the inquiry complete event */
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (p_cb->in_use && p_cb->event == GAP_EVT_INQUIRY_COMPLETE)
+ {
+ gap_free_cb(p_cb);
+ return (BT_PASS);
+ }
+ }
+
+ /* If here the control block was not found */
+ status = GAP_ERR_NO_CTRL_BLK;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_CancelPeriodicInquiry
+**
+** Description This function cancels a periodic inquiry (if in progress)
+**
+** Parameters: None
+**
+** Returns BOOLEAN: (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+UINT16 GAP_CancelPeriodicInquiry(void)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+ tBTM_STATUS btm_status;
+ UINT16 status;
+
+ btm_status = BTM_CancelPeriodicInquiry();
+ if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+ {
+ /* Free the control block that is waiting for the inquiry complete event */
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (p_cb->in_use && p_cb->event == GAP_EVT_INQUIRY_COMPLETE)
+ {
+ gap_free_cb(p_cb);
+ return (BT_PASS);
+ }
+ }
+
+ /* If here the control block was not found */
+ status = GAP_ERR_NO_CTRL_BLK;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_GetFirstInquiryResult
+**
+** Description This function retrieves the first valid inquiry result.
+**
+** Parameters: p_results - pointer to the inquiry results
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+UINT16 GAP_GetFirstInquiryResult(tGAP_INQ_RESULTS *p_results)
+{
+ UINT8 *ptr;
+
+ gap_cb.cur_inqptr = BTM_InqFirstResult();
+
+ if (gap_cb.cur_inqptr != NULL)
+ {
+ memcpy(p_results, &gap_cb.cur_inqptr->results, sizeof(tBTM_INQ_RESULTS));
+
+ ptr = (UINT8 *)gap_cb.cur_inqptr->results.remote_bd_addr;
+ GAP_TRACE_EVENT6("GAP_GetFirstInqResult %02x%02x%02x%02x%02x%02x",
+ ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5]);
+ return(BT_PASS);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0("GAP_FirstInqResults: No BD_ADDRs Found");
+ memset(p_results, 0, sizeof(tBTM_INQ_RESULTS));
+ return(GAP_EOINQDB);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_GetNextInquiryResult
+**
+** Description This function retrieves the next valid inquiry result.
+**
+** Parameters: p_results - pointer to the inquiry results
+**
+** Returns BT_PASS (0) if successful, or a non-zero status code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+UINT16 GAP_GetNextInquiryResult(tGAP_INQ_RESULTS *p_results)
+{
+ UINT8 *ptr;
+
+ /*** if the current inquiry db pointer is NULL then call the first entry ***/
+ if (gap_cb.cur_inqptr)
+ {
+ gap_cb.cur_inqptr = BTM_InqNextResult(gap_cb.cur_inqptr);
+ if (gap_cb.cur_inqptr != NULL)
+ {
+ memcpy(p_results, &gap_cb.cur_inqptr->results,
+ sizeof(tGAP_INQ_RESULTS));
+
+ ptr = (UINT8 *)gap_cb.cur_inqptr->results.remote_bd_addr;
+ GAP_TRACE_EVENT6("GAP_GetNextInqResult %02x%02x%02x%02x%02x%02x",
+ ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5]);
+
+ return(BT_PASS);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0("GAP_NextInqResults: No BD_ADDRs Found");
+ memset(p_results, 0, sizeof(tBTM_INQ_RESULTS));
+ return(GAP_EOINQDB);
+ }
+ }
+ else
+ return (GAP_GetFirstInquiryResult(p_results));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ReadLocalDeviceInfo
+**
+** Description This function retrieves local device information to the caller.
+**
+** Parameters: name - (output) pointer to the UTF-8 encoded string representing
+** the device name.
+**
+** addr - (output) pointer to the Bluetooth device address (BD_ADDR).
+**
+** verinfo - (output) pointer to the LMP version information.
+**
+** features - (output) pointer to the LMP features for the device.
+**
+** NOTE: Return parameters that are set to NULL are not retrieved.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+
+UINT16 GAP_ReadLocalDeviceInfo(UINT8 *name, BD_ADDR *addr, tGAP_LMP_VERSION *verinfo,
+ tGAP_LMP_FEATURES *features)
+{
+ return (GAP_UNSUPPORTED);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_GetRemoteDeviceName
+**
+** Description The remote name is retrieved from the specified remote device. If
+** GAP_CMD_INITIATED is returned by the function, the command was
+** successfully sent to the controller. The GAP_EVT_NAME_RESP event
+** is passed in the callback when the remote device name has been retrieved.
+**
+** Parameters: addr - The Bluetooth device address (BD_ADDR) of the remote
+** device.
+**
+** callback - pointer to the callback which is called after the
+** remote device has been retrieved.
+** p_data in the callback points to the structure containing the
+** status, device name length, and the UTF-8 encoded
+** device name. (type tBTM_REMOTE_DEV_NAME)
+** The event field in the callback is set to GAP_EVT_REM_NAME_COMPLETE.
+** The callback is not called unless (GAP_CMD_INITIATED) is returned.
+**
+**
+** Returns
+** GAP_CMD_INITIATED if remote search successfully initiated
+** GAP_ERR_BUSY if a remote name request is already in progress,
+** GAP_ERR_NO_CTRL_BLK if out of control blocks (too many commands pending)
+** GAP_BAD_BD_ADDR if the device address is bad,
+** GAP_DEVICE_NOT_UP if the device has not been initialized yet
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+UINT16 GAP_GetRemoteDeviceName (BD_ADDR addr, tGAP_CALLBACK *callback)
+{
+ tGAP_INFO *p_cb;
+ UINT16 retval;
+ tBTM_STATUS btm_status;
+
+ if ((p_cb = gap_allocate_cb()) != NULL)
+ {
+ p_cb->gap_cback = callback;
+ p_cb->event = GAP_EVT_REM_NAME_COMPLETE; /* Return event expected */
+
+ btm_status = BTM_ReadRemoteDeviceName (addr, gap_cb.btm_cback[p_cb->index]);
+
+ /* If the name was not returned immediately, or if an error occurred, release the control block */
+ if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+ gap_free_cb (p_cb);
+ }
+ else
+ retval = GAP_ERR_NO_CTRL_BLK;
+
+ return (retval);
+}
+
+/*******************************************************************************
+**
+** Function GAP_SetDeviceClass
+**
+** Description This function updates the local Device Class.
+**
+** Parameters:
+** p_cod - Pointer to the device class to set to
+**
+** cmd - the fields of the device class to update.
+** GAP_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+** GAP_SET_COD_SERVICE_CLASS - set the bits in the input
+** GAP_CLR_COD_SERVICE_CLASS - clear the bits in the input
+** GAP_SET_COD_ALL - overwrite major, minor, set the bits in service class
+** GAP_INIT_COD - overwrite major, minor, and service class
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_BUSY if a discovery is already in progress
+** GAP_ERR_ILL_PARM if an illegal parameter was detected
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+UINT16 GAP_SetDeviceClass(tGAP_COD *p_cod, UINT8 cmd)
+{
+ tBTM_STATUS btm_status;
+ UINT8 *dev;
+ UINT16 service;
+ UINT8 minor, major;
+ DEV_CLASS dev_class;
+
+ dev = BTM_ReadDeviceClass();
+ BTM_COD_SERVICE_CLASS( service, dev );
+ BTM_COD_MINOR_CLASS(minor, dev );
+ BTM_COD_MAJOR_CLASS(major, dev );
+
+ switch(cmd)
+ {
+ case GAP_SET_COD_MAJOR_MINOR:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ break;
+
+ case GAP_SET_COD_SERVICE_CLASS:
+ /* clear out the bits that is not SERVICE_CLASS bits */
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service | p_cod->service;
+ break;
+
+ case GAP_CLR_COD_SERVICE_CLASS:
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service & (~p_cod->service);
+ break;
+
+ case GAP_SET_COD_ALL:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service | p_cod->service;
+ break;
+
+ case GAP_INIT_COD:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ service = p_cod->service & BTM_COD_SERVICE_CLASS_MASK;
+ break;
+
+ default:
+ return GAP_ERR_ILL_PARM;
+ }
+
+ /* convert the fields into the device class type */
+ FIELDS_TO_COD(dev_class, minor, major, service);
+
+ btm_status = BTM_SetDeviceClass(dev_class);
+ return (gap_convert_btm_status (btm_status));
+}
+
+/*******************************************************************************
+**
+** Function GAP_ReadDeviceClass
+**
+** Description This function reads the local Device Class.
+**
+** Parameters:
+**
+** Returns PASS
+**
+*******************************************************************************/
+UINT16 GAP_ReadDeviceClass(tGAP_COD *p_cod)
+{
+ UINT8 *dev;
+
+ dev = BTM_ReadDeviceClass();
+
+ BTM_COD_SERVICE_CLASS( p_cod->service, dev );
+ BTM_COD_MINOR_CLASS( p_cod->minor, dev );
+ BTM_COD_MAJOR_CLASS( p_cod->major, dev );
+
+ return (BT_PASS);
+}
+
+/*******************************************************************************
+**
+** Function GAP_SetTraceLevel
+**
+** Description This function sets the trace level for GAP. If called with
+** a value of 0xFF, it simply returns the current trace level.
+**
+** Returns The new or current trace level
+**
+*******************************************************************************/
+UINT8 GAP_SetTraceLevel (UINT8 new_level)
+{
+ if (new_level != 0xFF)
+ gap_cb.trace_level = new_level;
+
+ return (gap_cb.trace_level);
+}
+
+/*******************************************************************************
+**
+** Function GAP_Init
+**
+** Description Initializes the control blocks used by GAP.
+**
+** This routine should not be called except once per
+** stack invocation.
+**
+** Returns Nothing
+**
+*******************************************************************************/
+void GAP_Init(void)
+{
+ memset (&gap_cb, 0, sizeof (tGAP_CB));
+
+ /*** Initialize the callbacks for BTM; Needs to be one per GAP_MAX_BLOCKS ***/
+ gap_cb.btm_cback[0] = gap_btm_cback0;
+#if GAP_MAX_BLOCKS > 1
+ gap_cb.btm_cback[1] = gap_btm_cback1;
+#endif
+#if GAP_MAX_BLOCKS > 2
+ gap_cb.btm_cback[2] = gap_btm_cback2;
+#endif
+
+#if defined(GAP_INITIAL_TRACE_LEVEL)
+ gap_cb.trace_level = GAP_INITIAL_TRACE_LEVEL;
+#else
+ gap_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
+#endif
+
+ /* Initialize the connection control block if included in build */
+#if GAP_CONN_INCLUDED == TRUE
+ gap_conn_init();
+#endif /* GAP_CONN_INCLUDED */
+
+#if BLE_INCLUDED == TRUE
+ gap_attr_db_init();
+#endif
+}
+
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
new file mode 100644
index 000000000..19e24a9da
--- /dev/null
+++ b/stack/gap/gap_ble.c
@@ -0,0 +1,967 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gap_int.h"
+#include "gap_api.h"
+#include "gattdefs.h"
+#include "gatt_api.h"
+#include "gatt_int.h"
+#include "btm_int.h"
+#include "hcimsgs.h"
+
+#define GAP_CHAR_ICON_SIZE 2
+#define GAP_CHAR_DEV_NAME_SIZE 248
+#define GAP_BLE_PRIVACY_FLAG_SIZE 1
+
+#define GAP_MAX_NUM_INC_SVR 0
+#define GAP_MAX_ATTR_NUM (2 * GAP_MAX_CHAR_NUM + GAP_MAX_NUM_INC_SVR + 1)
+#define GAP_MAX_CHAR_VALUE_SIZE (30 + GAP_CHAR_DEV_NAME_SIZE)
+
+
+#ifndef GAP_ATTR_DB_SIZE
+#define GAP_ATTR_DB_SIZE GATT_DB_MEM_SIZE(GAP_MAX_NUM_INC_SVR, GAP_MAX_CHAR_NUM, GAP_MAX_CHAR_VALUE_SIZE)
+#endif
+
+/* privacy flag readable and writable with encryption on */
+#ifndef GAP_BLE_PRIVACY_FLAG_PERM
+#define GAP_BLE_PRIVACY_FLAG_PERM (GATT_PERM_READ|GATT_PERM_WRITE)
+#endif
+
+#define GATT_READ_GAP_PRIVACY_FLAG 1
+#define GATT_SET_GAP_PRIVACY_FLAG 2
+#define GATT_READ_GAP_REMOTE_NAME 3
+#define GATT_UPDATE_RECONN_ADDR 4
+
+#define GAP_BLE_PRIVACY_UNKNOWN 0xff
+
+static void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE op_code, tGATTS_DATA *p_data);
+
+/* client connection callback */
+static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
+
+static tGATT_CBACK gap_cback =
+{
+ gap_ble_c_connect_cback,
+ gap_ble_c_cmpl_cback,
+ NULL,
+ NULL,
+ gap_ble_s_attr_request_cback
+};
+
+
+
+/*******************************************************************************
+**
+** Function gap_find_clcb_by_bd_addr
+**
+** Description The function searches all LCB with macthing bd address
+**
+** Returns total number of clcb found.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_find_clcb_by_bd_addr(BD_ADDR bda)
+{
+ UINT8 i_clcb;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
+ {
+ return p_clcb;
+ }
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_find_clcb_by_conn_id
+**
+** Description The function searches all LCB with macthing connection ID
+**
+** Returns total number of clcb found.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_ble_find_clcb_by_conn_id(UINT16 conn_id)
+{
+ UINT8 i_clcb;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && p_clcb->conn_id == conn_id)
+ {
+ return p_clcb;
+ }
+ }
+
+ return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function gap_clcb_alloc
+**
+** Description The function allocates a GAP connection link control block
+**
+** Returns NULL if not found. Otherwise pointer to the connection link block.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
+{
+ UINT8 i_clcb = 0;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (!p_clcb->in_use)
+ {
+ p_clcb->in_use = TRUE;
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+ memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
+ break;
+ }
+ }
+ return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function gap_find_alloc_clcb
+**
+** Description The function find or allocates a GAP connection link control block
+**
+** Returns NULL if not found. Otherwise pointer to the connection link block.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_find_alloc_clcb (UINT16 conn_id, BD_ADDR bda)
+{
+ UINT8 i_clcb = 0;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (!p_clcb->in_use)
+ {
+ p_clcb->in_use = TRUE;
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+ memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
+ break;
+ }
+ }
+ return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function gap_get_conn_id_if_connected
+**
+** Description This function returns a connecttion handle to a ATT server
+** if the server is already connected
+**
+** Parameters client_if: client interface.
+** bd_addr: peer device address.
+**
+** Returns Connection handle or invalid handle value
+**
+*******************************************************************************/
+UINT16 gap_get_conn_id_if_connected (BD_ADDR bd_addr)
+{
+ tGAP_CLCB *p_clcb;
+ UINT16 i;
+
+ GAP_TRACE_EVENT2 ("gap_get_conn_id_if_connected() - BDA: %08x%04x ",
+ (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
+ (bd_addr[4]<<8)+bd_addr[5]);
+
+ for (i = 0, p_clcb = gap_cb.clcb; i < GAP_MAX_CL; i++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bd_addr, BD_ADDR_LEN) )
+ {
+ return(p_clcb->conn_id);
+ }
+ }
+
+ /* If here, failed to allocate a client control block */
+ GATT_TRACE_DEBUG0 ("gap_get_conn_id_if_connected: not connected");
+ return(GATT_INVALID_CONN_ID);
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_enqueue_op
+**
+** Description enqueue a GAP operation when GAP client is busy
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_ble_enqueue_op( tGAP_CLCB * p_clcb, UINT8 op, BD_ADDR reconn_addr, UINT8 privacy_flag, void *p_cback)
+{
+ tGAP_BLE_PENDING_OP *p_op = (tGAP_BLE_PENDING_OP *)GKI_getbuf(sizeof(tGAP_BLE_PENDING_OP));
+
+ if (p_op != NULL)
+ {
+ p_op->op = op;
+ p_op->p_pending_cback = p_cback;
+
+ if (op == GATT_SET_GAP_PRIVACY_FLAG)
+ p_op->pending_data.privacy_flag = privacy_flag;
+ else if (op == GATT_UPDATE_RECONN_ADDR)
+ memcpy(p_op->pending_data.reconn_addr, reconn_addr, BD_ADDR_LEN);
+
+ GKI_enqueue(&p_clcb->pending_op_q, p_op);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_process_pending_op
+**
+** Description get next pending operation and process it
+**
+** Returns void
+**
+*******************************************************************************/
+static BOOLEAN gap_ble_process_pending_op(tGAP_CLCB *p_clcb)
+{
+ tGAP_BLE_PENDING_OP *p_pending_op = (tGAP_BLE_PENDING_OP *)GKI_dequeue(&p_clcb->pending_op_q);
+ BOOLEAN started = FALSE;
+
+ if (p_pending_op != NULL)
+ {
+ if (p_pending_op->op == GATT_UPDATE_RECONN_ADDR)
+ {
+ GAP_BleUpdateReconnectAddr( p_clcb->bda,
+ p_pending_op->pending_data.reconn_addr,
+ (tGAP_BLE_RECONN_ADDR_CBACK *)p_pending_op->p_pending_cback);
+ started = TRUE;
+ }
+ GKI_freebuf(p_pending_op);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0("No pending operation");
+ }
+
+ return started;
+}
+
+/*******************************************************************************
+** GAP Attributes Database Request callback
+*******************************************************************************/
+tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN is_long)
+{
+ tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
+ UINT8 *p = p_value->value, i;
+ UINT16 offset = p_value->offset;
+ UINT8 *p_dev_name = NULL;
+
+ for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+ {
+ if (handle == p_db_attr->handle)
+ {
+ if (p_db_attr->uuid != GATT_UUID_GAP_DEVICE_NAME &&
+ is_long == TRUE)
+ return GATT_NOT_LONG;
+
+ switch (p_db_attr->uuid)
+ {
+ case GATT_UUID_GAP_DEVICE_NAME:
+ BTM_ReadLocalDeviceName((char **)&p_dev_name);
+ if (strlen ((char *)p_dev_name) > GATT_MAX_ATTR_LEN)
+ p_value->len = GATT_MAX_ATTR_LEN;
+ else
+ p_value->len = (UINT16)strlen ((char *)p_dev_name);
+
+ if (offset > p_value->len)
+ return GATT_INVALID_OFFSET;
+ else
+ {
+ p_value->len -= offset;
+ p_dev_name += offset;
+ ARRAY_TO_STREAM(p, p_dev_name, p_value->len);
+ GAP_TRACE_EVENT1("GATT_UUID_GAP_DEVICE_NAME len=0x%04x", p_value->len);
+ }
+ break;
+
+ case GATT_UUID_GAP_ICON:
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.icon);
+ p_value->len = 2;
+ break;
+
+ case GATT_UUID_GAP_PRIVACY_FLAG:
+ UINT8_TO_STREAM(p, p_db_attr->attr_value.privacy);
+ p_value->len = 1;
+ break;
+
+ case GATT_UUID_GAP_RECONN_ADDR:
+ p_value->len = BD_ADDR_LEN;
+ BDADDR_TO_STREAM(p, p_db_attr->attr_value.reconn_bda);
+ break;
+
+ case GATT_UUID_GAP_PREF_CONN_PARAM:
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_min); /* int_min */
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_max); /* int_max */
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.latency); /* latency */
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.sp_tout); /* sp_tout */
+ p_value->len =8;
+ break;
+ }
+ return GATT_SUCCESS;
+ }
+ }
+ return GATT_NOT_FOUND;
+}
+
+/*******************************************************************************
+** GAP Attributes Database Read/Read Blob Request process
+*******************************************************************************/
+tGATT_STATUS gap_proc_read (tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp)
+{
+ tGATT_STATUS status = GATT_NO_RESOURCES;
+
+ if (p_data->is_long)
+ p_rsp->attr_value.offset = p_data->offset;
+
+ p_rsp->attr_value.handle = p_data->handle;
+
+ status = gap_read_attr_value(p_data->handle, &p_rsp->attr_value, p_data->is_long);
+
+ return status;
+}
+BOOLEAN gap_read_local_reconn_addr(BD_ADDR_PTR reconn_bda)
+{
+ BD_ADDR dummy_bda = {0};
+
+ if (memcmp(gap_cb.reconn_bda, dummy_bda, BD_ADDR_LEN) != 0)
+ {
+ memcpy(reconn_bda, gap_cb.reconn_bda, BD_ADDR_LEN);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/******************************************************************************
+**
+** Function gap_proc_write_req
+**
+** Description GAP ATT server process a write request.
+**
+** Returns void.
+**
+*******************************************************************************/
+UINT8 gap_proc_write_req( tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
+{
+ tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
+ UINT8 i;
+
+ for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+ {
+ if (p_data-> handle == p_db_attr->handle)
+ {
+ if (p_data->offset != 0) return GATT_NOT_LONG;
+ if (p_data->is_prep) return GATT_REQ_NOT_SUPPORTED;
+
+/* DO NOT SUPPORT RECONNECTION ADDRESS FOR NOW
+
+ if (p_db_attr->uuid == GATT_UUID_GAP_RECONN_ADDR)
+ {
+ if (!btm_cb.ble_ctr_cb.privacy)
+ return GATT_WRITE_NOT_PERMIT;
+ if (p_data->len != BD_ADDR_LEN) return GATT_INVALID_ATTR_LEN;
+
+ STREAM_TO_BDADDR(p_db_attr->attr_value.reconn_bda, p);
+ // write direct connection address
+ memcpy(&gap_cb.reconn_bda, p_db_attr->attr_value.reconn_bda, BD_ADDR_LEN);
+
+ return GATT_SUCCESS;
+ }
+ else
+*/
+ return GATT_WRITE_NOT_PERMIT;
+ }
+ }
+ return GATT_NOT_FOUND;
+
+}
+
+/******************************************************************************
+**
+** Function gap_ble_s_attr_request_cback
+**
+** Description GAP ATT server attribute access request callback.
+**
+** Returns void.
+**
+*******************************************************************************/
+void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id,
+ tGATTS_REQ_TYPE type, tGATTS_DATA *p_data)
+{
+ UINT8 status = GATT_INVALID_PDU;
+ tGATTS_RSP rsp_msg;
+ BOOLEAN ignore = FALSE;
+
+ GAP_TRACE_EVENT1("gap_ble_s_attr_request_cback : recv type (0x%02x)", type);
+
+ memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
+
+ switch (type)
+ {
+ case GATTS_REQ_TYPE_READ:
+ status = gap_proc_read(type, &p_data->read_req, &rsp_msg);
+ break;
+
+ case GATTS_REQ_TYPE_WRITE:
+ if (!p_data->write_req.need_rsp)
+ ignore = TRUE;
+
+ status = gap_proc_write_req(type, &p_data->write_req);
+ break;
+
+ case GATTS_REQ_TYPE_WRITE_EXEC:
+ ignore = TRUE;
+ GAP_TRACE_EVENT0("Ignore GATTS_REQ_TYPE_WRITE_EXEC" );
+ break;
+
+ case GATTS_REQ_TYPE_MTU:
+ GAP_TRACE_EVENT1("Get MTU exchange new mtu size: %d", p_data->mtu);
+ ignore = TRUE;
+ break;
+
+ default:
+ GAP_TRACE_EVENT1("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
+ break;
+ }
+
+ if (!ignore)
+ GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_att_db_init
+**
+** Description GAP ATT database initalization.
+**
+** Returns void.
+**
+*******************************************************************************/
+void gap_attr_db_init(void)
+{
+ tBT_UUID app_uuid = {LEN_UUID_128,{0}};
+ tBT_UUID uuid = {LEN_UUID_16,{UUID_SERVCLASS_GAP_SERVER}};
+ UINT16 service_handle;
+ tGAP_ATTR *p_db_attr = &gap_cb.gatt_attr[0];
+ tGATT_STATUS status;
+
+ /* Fill our internal UUID with a fixed pattern 0x82 */
+ memset (&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
+ memset(gap_cb.gatt_attr, 0, sizeof(tGAP_ATTR) *GAP_MAX_CHAR_NUM);
+
+ gap_cb.gatt_if = GATT_Register(&app_uuid, &gap_cback);
+
+ GATT_StartIf(gap_cb.gatt_if);
+
+ /* Create a GAP service */
+ service_handle = GATTS_CreateService (gap_cb.gatt_if, &uuid, 0, GAP_MAX_ATTR_NUM, TRUE);
+
+ GAP_TRACE_EVENT1 ("gap_attr_db_init service_handle = %d", service_handle);
+
+ /* add Device Name Characteristic
+ */
+ uuid.len = LEN_UUID_16;
+ uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
+ p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
+ p_db_attr ++;
+
+ /* add Icon characteristic
+ */
+ uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_ICON;
+ p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
+ &uuid,
+ GATT_PERM_READ,
+ GATT_CHAR_PROP_BIT_READ);
+ p_db_attr ++;
+
+ /* start service now */
+ memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
+
+ status = GATTS_StartService(gap_cb.gatt_if, service_handle, GAP_TRANSPORT_SUPPORTED );
+
+ GAP_TRACE_EVENT3 ("GAP App gatt_if: %d s_hdl = %d start_status=%d",
+ gap_cb.gatt_if, service_handle, status);
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleAttrDBUpdate
+**
+** Description GAP ATT database update.
+**
+** Returns void.
+**
+*******************************************************************************/
+void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
+{
+ tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
+ UINT8 i = 0;
+
+ GAP_TRACE_EVENT1("GAP_BleAttrDBUpdate attr_uuid=0x%04x", attr_uuid);
+
+ for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+ {
+ if (p_db_attr->uuid == attr_uuid)
+ {
+ GAP_TRACE_EVENT1("Found attr_uuid=0x%04x", attr_uuid);
+
+ switch (attr_uuid)
+ {
+ case GATT_UUID_GAP_ICON:
+ p_db_attr->attr_value.icon = p_value->icon;
+ break;
+
+ case GATT_UUID_GAP_PREF_CONN_PARAM:
+ memcpy((void *)&p_db_attr->attr_value.conn_param, (const void *)&p_value->conn_param, sizeof(tGAP_BLE_PREF_PARAM));
+ break;
+
+ case GATT_UUID_GAP_DEVICE_NAME:
+ BTM_SetLocalDeviceName((char *)p_value->p_dev_name);
+ break;
+
+ }
+ break;
+ }
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_cl_op_cmpl
+**
+** Description GAP client operation complete callback
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_ble_cl_op_cmpl(tGAP_CLCB *p_clcb, BOOLEAN status, UINT16 len, UINT8 *p_name)
+{
+ tGAP_BLE_DEV_NAME_CBACK *p_dev_name_cback = (tGAP_BLE_DEV_NAME_CBACK *)(p_clcb->p_cback);
+ UINT16 op = p_clcb->cl_op_uuid;
+
+ GAP_TRACE_EVENT1("gap_ble_cl_op_cmpl status: %d", status);
+
+ p_clcb->cl_op_uuid = 0;
+ p_clcb->p_cback=NULL;
+
+ if (!gap_ble_process_pending_op(p_clcb) && op != 0)
+ GATT_Disconnect(p_clcb->conn_id);
+
+ if (p_dev_name_cback)
+ {
+ GAP_TRACE_EVENT0("calling gap_ble_cl_op_cmpl");
+
+ if (op == GATT_UUID_GAP_DEVICE_NAME)
+ (* p_dev_name_cback)(status, p_clcb->bda, len, (char *)p_name);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_c_connect_cback
+**
+** Description Client connection callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+ tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (bda);
+ UINT16 cl_op_uuid;
+
+ GAP_TRACE_EVENT5 ("gap_ble_c_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
+ (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
+ (bda[4]<<8)+bda[5], connected, conn_id, reason);
+
+
+ if (connected)
+ {
+ if (p_clcb == NULL)
+ {
+ if ((p_clcb = gap_clcb_alloc(conn_id, bda))== NULL)
+ {
+ GAP_TRACE_ERROR0 ("gap_ble_c_connect_cback: no_resource");
+ return;
+ }
+ }
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+
+ /* Do not use reconnection address for now -->
+ check privacy enabled? set reconnect address
+ btm_ble_update_reconnect_address(bda);*/
+ }
+ else
+ {
+ if (p_clcb != NULL)
+ p_clcb->connected = FALSE;
+ }
+
+ if (p_clcb)
+ {
+ cl_op_uuid = p_clcb->cl_op_uuid;
+
+ GAP_TRACE_EVENT1 ("cl_op_uuid=0x%04x", cl_op_uuid );
+
+ if (p_clcb->connected)
+ {
+ p_clcb->cl_op_uuid = 0;
+ if (cl_op_uuid == GATT_UUID_GAP_DEVICE_NAME)
+ {
+ GAP_BleReadPeerDevName (bda, (tGAP_BLE_DEV_NAME_CBACK *)p_clcb->p_cback);
+ }
+ }
+ /* current link disconnect */
+ else
+ {
+ gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+ memset(p_clcb, 0, sizeof(tGAP_CLCB));
+ }
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_c_cmpl_cback
+**
+** Description Client operation complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+
+{
+ tGAP_CLCB *p_clcb = gap_ble_find_clcb_by_conn_id(conn_id);
+ UINT16 op_type;
+ UINT16 min, max, latency, tout;
+ UINT16 len;
+ UINT8 *pp;
+
+ if (p_clcb == NULL)
+ return;
+
+ op_type = p_clcb->cl_op_uuid;
+
+ GAP_TRACE_EVENT3 ("gap_ble_c_cmpl_cback() - op_code: 0x%02x status: 0x%02x read_type: 0x%04x", op, status, op_type);
+ /* Currently we only issue read commands */
+ if (op != GATTC_OPTYPE_READ && op != GATTC_OPTYPE_WRITE)
+ return;
+
+ if (status != GATT_SUCCESS)
+ {
+ gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+ return;
+ }
+
+ pp = p_data->att_value.value;
+
+ switch (op_type)
+ {
+ case GATT_UUID_GAP_PREF_CONN_PARAM:
+ GAP_TRACE_EVENT0 ("GATT_UUID_GAP_PREF_CONN_PARAM");
+ /* Extract the peripheral preferred connection parameters and save them */
+
+ STREAM_TO_UINT16 (min, pp);
+ STREAM_TO_UINT16 (max, pp);
+ STREAM_TO_UINT16 (latency, pp);
+ STREAM_TO_UINT16 (tout, pp);
+
+ BTM_BleSetPrefConnParams (p_clcb->bda, min, max, latency, tout);
+ /* release the connection here */
+ gap_ble_cl_op_cmpl(p_clcb, TRUE, 0, NULL);
+ break;
+
+ case GATT_UUID_GAP_DEVICE_NAME:
+ GAP_TRACE_EVENT0 ("GATT_UUID_GAP_DEVICE_NAME");
+ len = (UINT16)strlen((char *)pp);
+ if (len > GAP_CHAR_DEV_NAME_SIZE)
+ len = GAP_CHAR_DEV_NAME_SIZE;
+ gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp);
+ break;
+ case GATT_UUID_GAP_ICON:
+ break;
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_cl_read_request
+**
+** Description utility function to start a read request for a GAP charactersitic
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback)
+{
+ tGATT_READ_PARAM param;
+
+ memset(&param, 0, sizeof(tGATT_READ_PARAM));
+
+ param.service.uuid.len = LEN_UUID_16;
+ param.service.uuid.uu.uuid16 = uuid;
+ param.service.s_handle = 1;
+ param.service.e_handle = 0xFFFF;
+ param.service.auth_req = 0;
+
+ if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, &param) != GATT_SUCCESS)
+ {
+ GAP_TRACE_ERROR0 ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
+ /* release the link here */
+ GATT_Disconnect(p_clcb->conn_id);
+ return(FALSE);
+ }
+ else
+ {
+ p_clcb->p_cback = p_cback;
+ p_clcb->cl_op_uuid = uuid;
+ return TRUE;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerPrefConnParams
+**
+** Description Start a process to read a connected peripheral's preferred
+** connection parameters
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
+{
+ tGAP_CLCB *p_clcb;
+
+
+ /* This function should only be called if there is a connection to */
+ /* the peer. Get a client handle for that connection. */
+ if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL ||
+ !p_clcb->connected)
+ {
+ GAP_TRACE_ERROR0("No connection, can not update reconnect address");
+ return(FALSE);
+ }
+
+ GAP_TRACE_API3 ("GAP_BleReadPeerPrefConnParams() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+ /* For now we only handle one at a time */
+ if (p_clcb->cl_op_uuid != 0)
+ return(FALSE);
+
+ return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
+
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerDevName
+**
+** Description Start a process to read a connected peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback)
+{
+ tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
+
+ if (p_cback == NULL)
+ return(FALSE);
+
+ if (p_clcb == NULL)
+ {
+ p_clcb = gap_clcb_alloc(0, peer_bda);
+ p_clcb->connected = FALSE;
+ }
+
+ if (p_clcb == NULL)
+ {
+ GAP_TRACE_ERROR0("GAP_BleReadPeerDevName max connection reached");
+ }
+
+
+ GAP_TRACE_EVENT3 ("GAP_BleReadPeerDevName() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+ /* For now we only handle one at a time */
+ if (p_clcb->cl_op_uuid != 0)
+ return(FALSE);
+
+ /* hold the link here */
+ GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
+
+ if (p_clcb->connected)
+ {
+ return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_DEVICE_NAME, (void *)p_cback);
+ }
+
+ p_clcb->p_cback = (void *)p_cback;
+ /* Mark currently active operation */
+ p_clcb->cl_op_uuid = GATT_UUID_GAP_DEVICE_NAME;
+
+
+ return(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleCancelReadPeerDevName
+**
+** Description Cancel reading a peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda)
+{
+ tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
+
+ GAP_TRACE_EVENT3 ("GAP_BleCancelReadPeerDevName() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], (p_clcb == NULL)? 0 : p_clcb->cl_op_uuid);
+
+ if (p_clcb == NULL || p_clcb->cl_op_uuid != GATT_UUID_GAP_DEVICE_NAME)
+ {
+ GAP_TRACE_ERROR0 ("Cannot cancel current op is not get dev name");
+ return FALSE;
+ }
+
+ if (!p_clcb->connected)
+ {
+ if (!GATT_CancelConnect(gap_cb.gatt_if, peer_bda, TRUE))
+ {
+ GAP_TRACE_ERROR0 ("Cannot cancel where No connection id");
+ return FALSE;
+ }
+ }
+
+ gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+
+ return(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleUpdateReconnectAddr
+**
+** Description Start a process to udpate the reconnect address if remote devive
+** has privacy enabled.
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda, BD_ADDR reconn_addr,
+ tGAP_BLE_RECONN_ADDR_CBACK *p_cback)
+{
+ tGAP_CLCB *p_clcb;
+ tGATT_DISC_PARAM param;
+
+ if (p_cback == NULL)
+ return(FALSE);
+
+ /* This function should only be called if there is a connection to */
+ /* the peer. Get a client handle for that connection. */
+ if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL ||
+ !p_clcb->connected)
+ {
+ GAP_TRACE_ERROR0("No connection, can not update reconnect address");
+ return(FALSE);
+ }
+
+ GAP_TRACE_API3 ("GAP_BleUpdateReconnectAddr() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+ /* For now we only handle one at a time */
+ if (p_clcb->cl_op_uuid != 0)
+ {
+ gap_ble_enqueue_op(p_clcb, GATT_UPDATE_RECONN_ADDR, reconn_addr, 0, (void *)p_cback);
+ return(FALSE);
+ }
+
+ /* hold the link here */
+ GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
+
+ memset(&param, 0, sizeof(tGATT_DISC_PARAM));
+
+ param.service.len = LEN_UUID_16;
+ param.service.uu.uuid16 = GATT_UUID_GAP_RECONN_ADDR;
+ param.s_handle = 1;
+ param.e_handle = 0xFFFF;
+
+ if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR, &param) != GATT_SUCCESS)
+ {
+ GAP_TRACE_ERROR0 ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
+ /* release the link here */
+ GATT_Disconnect(p_clcb->conn_id);
+ return(FALSE);
+ }
+ else
+ {
+ p_clcb->p_cback = (void *)p_cback;
+ memcpy(p_clcb->reconn_addr, reconn_addr, BD_ADDR_LEN);
+ p_clcb->cl_op_uuid = GATT_UUID_GAP_RECONN_ADDR;
+ }
+
+ return TRUE;
+
+}
+
+#endif /* BLE_INCLUDED */
+
+
+
+
+
diff --git a/stack/gap/gap_conn.c b/stack/gap/gap_conn.c
new file mode 100644
index 000000000..43765b767
--- /dev/null
+++ b/stack/gap/gap_conn.c
@@ -0,0 +1,1270 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#include "bt_target.h"
+#include "btu.h"
+#include "gap_int.h"
+#include "l2cdefs.h"
+#include "l2c_int.h"
+#include <string.h>
+#if GAP_CONN_INCLUDED == TRUE
+#include "btm_int.h"
+
+/********************************************************************************/
+/* L O C A L F U N C T I O N P R O T O T Y P E S */
+/********************************************************************************/
+static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
+static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result);
+static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
+static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
+static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
+static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
+static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested);
+
+static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid);
+static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle);
+static tGAP_CCB *gap_allocate_ccb (void);
+static void gap_release_ccb (tGAP_CCB *p_ccb);
+
+/*******************************************************************************
+**
+** Function gap_conn_init
+**
+** Description This function is called to initialize GAP connection management
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_conn_init (void)
+{
+#if AMP_INCLUDED == TRUE
+ gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
+ gap_cb.conn.reg_info.pAMP_ConnectCfm_Cb = gap_connect_cfm;
+ gap_cb.conn.reg_info.pAMP_ConnectPnd_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_ConfigInd_Cb = gap_config_ind;
+ gap_cb.conn.reg_info.pAMP_ConfigCfm_Cb = gap_config_cfm;
+ gap_cb.conn.reg_info.pAMP_DisconnectInd_Cb = gap_disconnect_ind;
+ gap_cb.conn.reg_info.pAMP_DisconnectCfm_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_QoSViolationInd_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_DataInd_Cb = gap_data_ind;
+ gap_cb.conn.reg_info.pAMP_CongestionStatus_Cb = gap_congestion_ind;
+ gap_cb.conn.reg_info.pAMP_TxComplete_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_MoveInd_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_MoveRsp_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_MoveCfm_Cb = NULL; //gap_move_cfm
+ gap_cb.conn.reg_info.pAMP_MoveCfmRsp_Cb = NULL; //gap_move_cfm_rsp
+
+#else
+ gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
+ gap_cb.conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
+ gap_cb.conn.reg_info.pL2CA_ConnectPnd_Cb = NULL;
+ gap_cb.conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;
+ gap_cb.conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;
+ gap_cb.conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;
+ gap_cb.conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL;
+ gap_cb.conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
+ gap_cb.conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
+ gap_cb.conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
+ gap_cb.conn.reg_info.pL2CA_TxComplete_Cb = NULL;
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnOpen
+**
+** Description This function is called to open an L2CAP connection.
+**
+** Parameters: is_server - If TRUE, the connection is not created
+** but put into a "listen" mode waiting for
+** the remote side to connect.
+**
+** service_id - Unique service ID from
+** BTM_SEC_SERVICE_FIRST_EMPTY (6)
+** to BTM_SEC_MAX_SERVICE_RECORDS (32)
+**
+** p_rem_bda - Pointer to remote BD Address.
+** If a server, and we don't care about the
+** remote BD Address, then NULL should be passed.
+**
+** psm - the PSM used for the connection
+**
+** p_config - Optional pointer to configuration structure.
+** If NULL, the default GAP configuration will
+** be used.
+**
+** security - security flags
+** chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM, GAP_FCR_CHAN_OPT_STREAM)
+**
+** p_cb - Pointer to callback function for events.
+**
+** Returns handle of the connection if successful, else GAP_INVALID_HANDLE
+**
+*******************************************************************************/
+UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
+ BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
+ UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb)
+{
+ tGAP_CCB *p_ccb;
+ UINT16 cid;
+ tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
+
+ GAP_TRACE_EVENT0 ("GAP_CONN - Open Request");
+
+ /* Allocate a new CCB. Return if none available. */
+ if ((p_ccb = gap_allocate_ccb()) == NULL)
+ return (GAP_INVALID_HANDLE);
+
+ /* If caller specified a BD address, save it */
+ if (p_rem_bda)
+ {
+ /* the bd addr is not BT_BD_ANY, then a bd address was specified */
+ if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN))
+ p_ccb->rem_addr_specified = TRUE;
+
+ memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN);
+ }
+ else if (!is_server)
+ {
+ /* remore addr is not specified and is not a server -> bad */
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* A client MUST have specified a bd addr to connect with */
+ if (!p_ccb->rem_addr_specified && !is_server)
+ {
+ gap_release_ccb (p_ccb);
+ GAP_TRACE_ERROR0 ("GAP ERROR: Client must specify a remote BD ADDR to connect to!");
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* Check if configuration was specified */
+ if (p_cfg)
+ p_ccb->cfg = *p_cfg;
+
+ p_ccb->p_callback = p_cb;
+
+ /* If originator, use a dynamic PSM */
+#if AMP_INCLUDED == TRUE
+ if (!is_server)
+ gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = NULL;
+ else
+ gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
+#else
+ if (!is_server)
+ gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
+ else
+ gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
+#endif
+
+ /* Register the PSM with L2CAP */
+ if ((p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info, AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE)) == 0)
+ {
+ GAP_TRACE_ERROR1 ("GAP_ConnOpen: Failure registering PSM 0x%04x", psm);
+ gap_release_ccb (p_ccb);
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* Register with Security Manager for the specific security level */
+ p_ccb->service_id = service_id;
+ if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name, p_ccb->service_id, security, p_ccb->psm, 0, 0))
+ {
+ GAP_TRACE_ERROR0 ("GAP_CONN - Security Error");
+ gap_release_ccb (p_ccb);
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* Fill in eL2CAP parameter data */
+ if( p_ccb->cfg.fcr_present )
+ {
+ p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
+ p_ccb->ertm_info.user_rx_pool_id = GAP_DATA_POOL_ID;
+ p_ccb->ertm_info.user_tx_pool_id = GAP_DATA_POOL_ID;
+ p_ccb->ertm_info.fcr_rx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+ p_ccb->ertm_info.fcr_tx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+ }
+
+ /* optional FCR channel modes */
+ p_ccb->ertm_info.allowed_modes = (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC;
+
+ if (is_server)
+ {
+ p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
+ p_ccb->con_state = GAP_CCB_STATE_LISTENING;
+ return (p_ccb->gap_handle);
+ }
+ else
+ {
+ /* We are the originator of this connection */
+ p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
+
+ /* Transition to the next appropriate state, waiting for connection confirm. */
+ p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
+
+ /* mark security done flag, when security is not required */
+ if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0)
+ p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
+
+ /* Check if L2CAP started the connection process */
+ if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info, &bt_uuid)) != 0))
+ {
+ p_ccb->connection_id = cid;
+ return (p_ccb->gap_handle);
+ }
+ else
+ {
+ gap_release_ccb (p_ccb);
+ return (GAP_INVALID_HANDLE);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnClose
+**
+** Description This function is called to close a connection.
+**
+** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnClose (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ GAP_TRACE_EVENT1 ("GAP_CONN - close handle: 0x%x", gap_handle);
+
+ if (p_ccb)
+ {
+ /* Check if we have a connection ID */
+ if (p_ccb->con_state != GAP_CCB_STATE_LISTENING)
+ L2CA_DISCONNECT_REQ (p_ccb->connection_id);
+
+ gap_release_ccb (p_ccb);
+
+ return (BT_PASS);
+ }
+
+ return (GAP_ERR_BAD_HANDLE);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnReadData
+**
+** Description Normally not GKI aware application will call this function
+** after receiving GAP_EVT_RXDATA event.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** p_data - Data area
+** max_len - Byte count requested
+** p_len - Byte count received
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+ BT_HDR *p_buf;
+ UINT16 copy_len;
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ *p_len = 0;
+
+ p_buf = (BT_HDR *)GKI_getfirst (&p_ccb->rx_queue);
+ if (!p_buf)
+ return (GAP_NO_DATA_AVAIL);
+
+ GKI_disable();
+
+ while (max_len && p_buf)
+ {
+ copy_len = (p_buf->len > max_len)?max_len:p_buf->len;
+ max_len -= copy_len;
+ *p_len += copy_len;
+ if (p_data)
+ {
+ memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len);
+ p_data += copy_len;
+ }
+
+ if (p_buf->len > copy_len)
+ {
+ p_buf->offset += copy_len;
+ p_buf->len -= copy_len;
+ break;
+ }
+ else
+ {
+ if (max_len)
+ {
+ p_buf = (BT_HDR *)GKI_getnext (p_buf);
+ }
+ GKI_freebuf (GKI_dequeue (&p_ccb->rx_queue));
+ }
+ }
+
+ p_ccb->rx_queue_size -= *p_len;
+
+ GKI_enable();
+
+ GAP_TRACE_EVENT2 ("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
+ p_ccb->rx_queue_size, *p_len);
+
+ return (BT_PASS);
+}
+
+/*******************************************************************************
+**
+** Function GAP_GetRxQueueCnt
+**
+** Description This function return number of bytes on the rx queue.
+**
+** Parameters: handle - Handle returned in the GAP_ConnOpen
+** p_rx_queue_count - Pointer to return queue count in.
+**
+**
+*******************************************************************************/
+int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count)
+{
+ tGAP_CCB *p_ccb;
+ int rc = BT_PASS;
+
+ /* Check that handle is valid */
+ if (handle < GAP_MAX_CONNECTIONS)
+ {
+ p_ccb = &gap_cb.conn.ccb_pool[handle];
+
+ if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+ {
+ *p_rx_queue_count = p_ccb->rx_queue_size;
+ }
+ else
+ rc = GAP_INVALID_HANDLE;
+ }
+ else
+ rc = GAP_INVALID_HANDLE;
+
+ GAP_TRACE_EVENT2 ("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
+ rc , *p_rx_queue_count);
+
+ return (rc);
+}
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTRead
+**
+** Description Bluetooth aware applications will call this function after receiving
+** GAP_EVT_RXDATA event.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** pp_buf - pointer to address of buffer with data,
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+ BT_HDR *p_buf;
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->rx_queue);
+
+ if (p_buf)
+ {
+ *pp_buf = p_buf;
+
+ p_ccb->rx_queue_size -= p_buf->len;
+ return (BT_PASS);
+ }
+ else
+ {
+ *pp_buf = NULL;
+ return (GAP_NO_DATA_AVAIL);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTWrite
+**
+** Description Bluetooth Aware applications can call this function to write data.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** p_buf - pointer to address of buffer with data,
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_INVALID_BUF_OFFSET - buffer offset is invalid
+*******************************************************************************/
+UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ if (!p_ccb)
+ {
+ GKI_freebuf (p_buf);
+ return (GAP_ERR_BAD_HANDLE);
+ }
+
+ if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+ {
+ GKI_freebuf (p_buf);
+ return (GAP_ERR_BAD_STATE);
+ }
+
+ if (p_buf->offset < L2CAP_MIN_OFFSET)
+ {
+ GKI_freebuf (p_buf);
+ return (GAP_ERR_BUF_OFFSET);
+ }
+
+ GKI_enqueue (&p_ccb->tx_queue, p_buf);
+
+ if (p_ccb->is_congested)
+ {
+ return (BT_PASS);
+ }
+
+ /* Send the buffer through L2CAP */
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+ gap_send_event (gap_handle);
+#else
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ return (GAP_ERR_BAD_STATE);
+ }
+#endif
+ return (BT_PASS);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnWriteData
+**
+** Description Normally not GKI aware application will call this function
+** to send data to the connection.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** p_data - Data area
+** max_len - Byte count requested
+** p_len - Byte count received
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_CONGESTION - system is congested
+**
+*******************************************************************************/
+UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+ BT_HDR *p_buf;
+
+ *p_len = 0;
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+ return (GAP_ERR_BAD_STATE);
+
+ while (max_len)
+ {
+ if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
+ {
+ if ((p_buf = (BT_HDR *)GKI_getpoolbuf (p_ccb->ertm_info.user_tx_pool_id)) == NULL)
+ return (GAP_ERR_CONGESTED);
+ }
+ else
+ {
+ if ((p_buf = (BT_HDR *)GKI_getpoolbuf (GAP_DATA_POOL_ID)) == NULL)
+ return (GAP_ERR_CONGESTED);
+ }
+
+ p_buf->offset = L2CAP_MIN_OFFSET;
+ p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len;
+ p_buf->event = BT_EVT_TO_BTU_SP_DATA;
+
+ memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
+
+ *p_len += p_buf->len;
+ max_len -= p_buf->len;
+ p_data += p_buf->len;
+
+ GAP_TRACE_EVENT1 ("GAP_WriteData %d bytes", p_buf->len);
+
+ GKI_enqueue (&p_ccb->tx_queue, p_buf);
+ }
+
+ if (p_ccb->is_congested)
+ {
+ return (BT_PASS);
+ }
+
+ /* Send the buffer through L2CAP */
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+ gap_send_event (gap_handle);
+#else
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ return (GAP_ERR_BAD_STATE);
+ }
+#endif
+ return (BT_PASS);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnReconfig
+**
+** Description Applications can call this function to reconfigure the connection.
+**
+** Parameters: handle - Handle of the connection
+** p_cfg - Pointer to new configuration
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ p_ccb->cfg = *p_cfg;
+
+ if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+ L2CA_CONFIG_REQ (p_ccb->connection_id, p_cfg);
+
+ return (BT_PASS);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnSetIdleTimeout
+**
+** Description Higher layers call this function to set the idle timeout for
+** a connection, or for all future connections. The "idle timeout"
+** is the amount of time that a connection can remain up with
+** no L2CAP channels on it. A timeout of zero means that the
+** connection will be torn down immediately when the last channel
+** is removed. A timeout of 0xFFFF means no timeout. Values are
+** in seconds.
+**
+** Parameters: handle - Handle of the connection
+** timeout - in secs
+** 0 = immediate disconnect when last channel is removed
+** 0xFFFF = no idle timeout
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout)
+{
+ tGAP_CCB *p_ccb;
+
+ if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+ return (GAP_ERR_BAD_HANDLE);
+
+ if (L2CA_SetIdleTimeout (p_ccb->connection_id, timeout, FALSE))
+ return (BT_PASS);
+ else
+ return (GAP_ERR_BAD_HANDLE);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemoteAddr
+**
+** Description This function is called to get the remote BD address
+** of a connection.
+**
+** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ GAP_TRACE_EVENT1 ("GAP_ConnGetRemoteAddr gap_handle = %d", gap_handle);
+
+ if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING))
+ {
+ GAP_TRACE_EVENT6("GAP_ConnGetRemoteAddr bda :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
+ p_ccb->rem_dev_address[0],p_ccb->rem_dev_address[1],p_ccb->rem_dev_address[2],
+ p_ccb->rem_dev_address[3],p_ccb->rem_dev_address[4],p_ccb->rem_dev_address[5]);
+ return (p_ccb->rem_dev_address);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0 ("GAP_ConnGetRemoteAddr return Error ");
+ return (NULL);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemMtuSize
+**
+** Description Returns the remote device's MTU size
+**
+** Parameters: handle - Handle of the connection
+**
+** Returns UINT16 - maximum size buffer that can be transmitted to the peer
+**
+*******************************************************************************/
+UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb;
+
+ if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+ return (0);
+
+ return (p_ccb->rem_mtu_size);
+}
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetL2CAPCid
+**
+** Description Returns the L2CAP channel id
+**
+** Parameters: handle - Handle of the connection
+**
+** Returns UINT16 - The L2CAP channel id
+** 0, if error
+**
+*******************************************************************************/
+UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb;
+
+ if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+ return (0);
+
+ return (p_ccb->connection_id);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_connect_ind
+**
+** Description This function handles an inbound connection indication
+** from L2CAP. This is the case where we are acting as a
+** server.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
+{
+ UINT16 xx;
+ tGAP_CCB *p_ccb;
+ tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
+
+ /* See if we have a CCB listening for the connection */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING)
+ && (p_ccb->psm == psm)
+ && ((p_ccb->rem_addr_specified == FALSE)
+ || (!memcmp (bd_addr, p_ccb->rem_dev_address, BD_ADDR_LEN))))
+ break;
+ }
+
+ if (xx == GAP_MAX_CONNECTIONS)
+ {
+ GAP_TRACE_WARNING0("*******");
+ GAP_TRACE_WARNING0("WARNING: GAP Conn Indication for Unexpected Bd Addr...Disconnecting");
+ GAP_TRACE_WARNING0("*******");
+
+ /* Disconnect because it is an unexpected connection */
+ L2CA_DISCONNECT_REQ (l2cap_cid);
+ return;
+ }
+
+ /* Transition to the next appropriate state, waiting for config setup. */
+ p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
+
+ /* Save the BD Address and Channel ID. */
+ memcpy (&p_ccb->rem_dev_address[0], bd_addr, BD_ADDR_LEN);
+ p_ccb->connection_id = l2cap_cid;
+
+ /* Send response to the L2CAP layer. */
+ L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info, &bt_uuid);
+
+ GAP_TRACE_EVENT1("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
+
+ /* Send a Configuration Request. */
+ L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
+}
+
+/*******************************************************************************
+**
+** Function gap_checks_con_flags
+**
+** Description This function processes the L2CAP configuration indication
+** event.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_checks_con_flags (tGAP_CCB *p_ccb)
+{
+ GAP_TRACE_EVENT1 ("gap_checks_con_flags conn_flags:0x%x, ", p_ccb->con_flags);
+ /* if all the required con_flags are set, report the OPEN event now */
+ if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE)
+ {
+ p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
+
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_OPENED);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_sec_check_complete
+**
+** Description The function called when Security Manager finishes
+** verification of the service side connection
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+{
+ tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data;
+
+ GAP_TRACE_EVENT3 ("gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
+ p_ccb->con_state, p_ccb->con_flags, res);
+ if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
+ return;
+
+ if (res == BTM_SUCCESS)
+ {
+ p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
+ gap_checks_con_flags (p_ccb);
+ }
+ else
+ {
+ /* security failed - disconnect the channel */
+ L2CA_DISCONNECT_REQ (p_ccb->connection_id);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_connect_cfm
+**
+** Description This function handles the connect confirm events
+** from L2CAP. This is the case when we are acting as a
+** client and have sent a connect request.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ /* initiate security process, if needed */
+ if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0)
+ {
+ btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE,
+ 0, 0, &gap_sec_check_complete, p_ccb);
+ }
+
+ /* If the connection response contains success status, then */
+ /* Transition to the next state and startup the timer. */
+ if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP))
+ {
+ p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
+
+ /* Send a Configuration Request. */
+ L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
+ }
+ else
+ {
+ /* Tell the user if he has a callback */
+ if (p_ccb->p_callback)
+ (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+
+ gap_release_ccb (p_ccb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_config_ind
+**
+** Description This function processes the L2CAP configuration indication
+** event.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
+{
+ tGAP_CCB *p_ccb;
+ UINT16 local_mtu_size;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ /* Remember the remote MTU size */
+
+ if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
+ {
+ local_mtu_size = GKI_get_pool_bufsize (p_ccb->ertm_info.user_tx_pool_id)
+ - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
+ }
+ else
+ local_mtu_size = L2CAP_MTU_SIZE;
+
+ if ((!p_cfg->mtu_present)||(p_cfg->mtu > local_mtu_size))
+ {
+ p_ccb->rem_mtu_size = local_mtu_size;
+ }
+ else
+ p_ccb->rem_mtu_size = p_cfg->mtu;
+
+ /* For now, always accept configuration from the other side */
+ p_cfg->flush_to_present = FALSE;
+ p_cfg->mtu_present = FALSE;
+ p_cfg->result = L2CAP_CFG_OK;
+ p_cfg->fcs_present = FALSE;
+
+ L2CA_CONFIG_RSP (l2cap_cid, p_cfg);
+
+ p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
+
+ gap_checks_con_flags (p_ccb);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_config_cfm
+**
+** Description This function processes the L2CAP configuration confirmation
+** event.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ if (p_cfg->result == L2CAP_CFG_OK)
+ {
+ p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
+
+
+ if (p_ccb->cfg.fcr_present)
+ p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
+ else
+ p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
+
+ gap_checks_con_flags (p_ccb);
+ }
+ else
+ {
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+ gap_release_ccb (p_ccb);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_disconnect_ind
+**
+** Description This function handles a disconnect event from L2CAP. If
+** requested to, we ack the disconnect before dropping the CCB
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
+{
+ tGAP_CCB *p_ccb;
+
+ GAP_TRACE_EVENT1 ("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ if (ack_needed)
+ L2CA_DISCONNECT_RSP (l2cap_cid);
+
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+ gap_release_ccb (p_ccb);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_data_ind
+**
+** Description This function is called when data is received from L2CAP.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ {
+ GKI_freebuf (p_msg);
+ return;
+ }
+
+ if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+ {
+ GKI_enqueue (&p_ccb->rx_queue, p_msg);
+
+ p_ccb->rx_queue_size += p_msg->len;
+ /*
+ GAP_TRACE_EVENT2 ("gap_data_ind - rx_queue_size=%d, msg len=%d",
+ p_ccb->rx_queue_size, p_msg->len);
+ */
+
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL);
+ }
+ else
+ {
+ GKI_freebuf (p_msg);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_congestion_ind
+**
+** Description This is a callback function called by L2CAP when
+** data L2CAP congestion status changes
+**
+*******************************************************************************/
+static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested)
+{
+ tGAP_CCB *p_ccb;
+ UINT16 event;
+ BT_HDR *p_buf;
+ UINT8 status;
+
+ GAP_TRACE_EVENT2 ("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
+ is_congested, lcid);
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (lcid)) == NULL)
+ return;
+
+ p_ccb->is_congested = is_congested;
+
+ event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
+ p_ccb->p_callback (p_ccb->gap_handle, event);
+
+ if (!is_congested)
+ {
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_find_ccb_by_cid
+**
+** Description This function searches the CCB table for an entry with the
+** passed CID.
+**
+** Returns the CCB address, or NULL if not found.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid)
+{
+ UINT16 xx;
+ tGAP_CCB *p_ccb;
+
+ /* Look through each connection control block */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->connection_id == cid))
+ return (p_ccb);
+ }
+
+ /* If here, not found */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_find_ccb_by_handle
+**
+** Description This function searches the CCB table for an entry with the
+** passed handle.
+**
+** Returns the CCB address, or NULL if not found.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Check that handle is valid */
+ if (handle < GAP_MAX_CONNECTIONS)
+ {
+ p_ccb = &gap_cb.conn.ccb_pool[handle];
+
+ if (p_ccb->con_state != GAP_CCB_STATE_IDLE)
+ return (p_ccb);
+ }
+
+ /* If here, handle points to invalid connection */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_allocate_ccb
+**
+** Description This function allocates a new CCB.
+**
+** Returns CCB address, or NULL if none available.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_allocate_ccb (void)
+{
+ UINT16 xx;
+ tGAP_CCB *p_ccb;
+
+ /* Look through each connection control block for a free one */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
+ {
+ memset (p_ccb, 0, sizeof (tGAP_CCB));
+
+ p_ccb->gap_handle = xx;
+ p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
+
+ return (p_ccb);
+ }
+ }
+
+ /* If here, no free CCB found */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_release_ccb
+**
+** Description This function releases a CCB.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_release_ccb (tGAP_CCB *p_ccb)
+{
+ UINT16 xx;
+ UINT16 psm = p_ccb->psm;
+ UINT8 service_id = p_ccb->service_id;
+
+ /* Drop any buffers we may be holding */
+ p_ccb->rx_queue_size = 0;
+
+ while (p_ccb->rx_queue.p_first)
+ GKI_freebuf (GKI_dequeue (&p_ccb->rx_queue));
+
+ while (p_ccb->tx_queue.p_first)
+ GKI_freebuf (GKI_dequeue (&p_ccb->tx_queue));
+
+ p_ccb->con_state = GAP_CCB_STATE_IDLE;
+
+ /* If no-one else is using the PSM, deregister from L2CAP */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm))
+ return;
+ }
+
+ /* Free the security record for this PSM */
+ BTM_SecClrService(service_id);
+ L2CA_DEREGISTER (psm);
+}
+
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** Function gap_send_event
+**
+** Description Send BT_EVT_TO_GAP_MSG event to BTU task
+**
+** Returns None
+**
+*******************************************************************************/
+void gap_send_event (UINT16 gap_handle)
+{
+ BT_HDR *p_msg;
+
+ if ((p_msg = (BT_HDR*)GKI_getbuf(BT_HDR_SIZE)) != NULL)
+ {
+ p_msg->event = BT_EVT_TO_GAP_MSG;
+ p_msg->len = 0;
+ p_msg->offset = 0;
+ p_msg->layer_specific = gap_handle;
+
+ GKI_send_msg(BTU_TASK, BTU_HCI_RCV_MBOX, p_msg);
+ }
+ else
+ {
+ GAP_TRACE_ERROR0("Unable to allocate message buffer for event.");
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_proc_btu_event
+**
+** Description Event handler for BT_EVT_TO_GAP_MSG event from BTU task
+**
+** Returns None
+**
+*******************************************************************************/
+void gap_proc_btu_event(BT_HDR *p_msg)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (p_msg->layer_specific);
+ UINT8 status;
+ BT_HDR *p_buf;
+
+ if (!p_ccb)
+ {
+ return;
+ }
+
+ if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+ {
+ return;
+ }
+
+ if (p_ccb->is_congested)
+ {
+ return;
+ }
+
+ /* Send the buffer through L2CAP */
+
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ break;
+ }
+
+}
+#endif /* (GAP_CONN_POST_EVT_INCLUDED == TRUE) */
+#endif /* GAP_CONN_INCLUDED */
diff --git a/stack/gap/gap_int.h b/stack/gap/gap_int.h
new file mode 100644
index 000000000..295ad831e
--- /dev/null
+++ b/stack/gap/gap_int.h
@@ -0,0 +1,231 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#ifndef GAP_INT_H
+#define GAP_INT_H
+
+#include "bt_target.h"
+#include "gap_api.h"
+#include "btm_api.h"
+#include "gki.h"
+#include "gatt_api.h"
+#if AMP_INCLUDED == TRUE
+ #include "amp_api.h"
+#endif
+
+#if defined BLE_INCLUDED && BLE_INCLUDED == TRUE
+ #include "gatt_api.h"
+#endif
+
+#define GAP_MAX_BLOCKS 2 /* Concurrent GAP commands pending at a time*/
+/* There must be a different btm callback for*/
+/* each control block.*/
+
+
+/* Definitions of limits for inquiries */
+#define GAP_PER_INQ_MIN_MAX_PERIOD BTM_PER_INQ_MIN_MAX_PERIOD
+#define GAP_PER_INQ_MAX_MAX_PERIOD BTM_PER_INQ_MAX_MAX_PERIOD
+#define GAP_PER_INQ_MIN_MIN_PERIOD BTM_PER_INQ_MIN_MIN_PERIOD
+#define GAP_PER_INQ_MAX_MIN_PERIOD BTM_PER_INQ_MAX_MIN_PERIOD
+#define GAP_MAX_INQUIRY_LENGTH BTM_MAX_INQUIRY_LENGTH
+#define GAP_MIN_INQUIRY_LEN BTM_MIN_INQUIRY_LEN
+
+/* Define the Generic Access Profile control structure */
+typedef struct
+{
+ void *p_data; /* Pointer to any data returned in callback */
+ tGAP_CALLBACK *gap_cback; /* Pointer to users callback function */
+ tGAP_CALLBACK *gap_inq_rslt_cback; /* Used for inquiry results */
+ UINT16 event; /* Passed back in the callback */
+ UINT8 index; /* Index of this control block and callback */
+ BOOLEAN in_use; /* True when structure is allocated */
+} tGAP_INFO;
+
+/* Define the control block for the FindAddrByName operation (Only 1 active at a time) */
+typedef struct
+{
+ tGAP_CALLBACK *p_cback;
+ tBTM_INQ_INFO *p_cur_inq; /* Pointer to the current inquiry database entry */
+ tGAP_FINDADDR_RESULTS results;
+ BOOLEAN in_use;
+} tGAP_FINDADDR_CB;
+
+
+/* Define the GAP Connection Control Block.
+*/
+typedef struct
+{
+#define GAP_CCB_STATE_IDLE 0
+#define GAP_CCB_STATE_LISTENING 1
+#define GAP_CCB_STATE_CONN_SETUP 2
+#define GAP_CCB_STATE_CFG_SETUP 3
+#define GAP_CCB_STATE_WAIT_SEC 4
+#define GAP_CCB_STATE_CONNECTED 5
+ UINT8 con_state;
+
+#define GAP_CCB_FLAGS_IS_ORIG 0x01
+#define GAP_CCB_FLAGS_HIS_CFG_DONE 0x02
+#define GAP_CCB_FLAGS_MY_CFG_DONE 0x04
+#define GAP_CCB_FLAGS_SEC_DONE 0x08
+#define GAP_CCB_FLAGS_CONN_DONE 0x0E
+ UINT8 con_flags;
+
+ UINT8 service_id; /* Used by BTM */
+ UINT16 gap_handle; /* GAP handle */
+ UINT16 connection_id; /* L2CAP CID */
+ BOOLEAN rem_addr_specified;
+ UINT8 chan_mode_mask; /* Supported channel modes (FCR) */
+ BD_ADDR rem_dev_address;
+ UINT16 psm;
+ UINT16 rem_mtu_size;
+
+ BOOLEAN is_congested;
+ BUFFER_Q tx_queue; /* Queue of buffers waiting to be sent */
+ BUFFER_Q rx_queue; /* Queue of buffers waiting to be read */
+
+ UINT32 rx_queue_size; /* Total data count in rx_queue */
+
+ tGAP_CONN_CALLBACK *p_callback; /* Users callback function */
+
+ tL2CAP_CFG_INFO cfg; /* Configuration */
+ tL2CAP_ERTM_INFO ertm_info; /* Pools and modes for ertm */
+} tGAP_CCB;
+
+typedef struct
+{
+#if AMP_INCLUDED == TRUE
+ tAMP_APPL_INFO reg_info;
+#else
+ tL2CAP_APPL_INFO reg_info; /* L2CAP Registration info */
+#endif
+ tGAP_CCB ccb_pool[GAP_MAX_CONNECTIONS];
+} tGAP_CONN;
+
+
+#if BLE_INCLUDED == TRUE
+ #define GAP_MAX_CHAR_NUM 5
+
+typedef struct
+{
+ UINT16 handle;
+ UINT16 uuid;
+ tGAP_BLE_ATTR_VALUE attr_value;
+}tGAP_ATTR;
+#endif
+/**********************************************************************
+** M A I N C O N T R O L B L O C K
+***********************************************************************/
+
+#define GAP_MAX_CL GATT_CL_MAX_LCB
+
+typedef struct
+{
+ union
+ {
+ BD_ADDR reconn_addr;
+ UINT8 privacy_flag;
+ } pending_data;
+ UINT8 op;
+ void *p_pending_cback;
+}tGAP_BLE_PENDING_OP;
+
+typedef struct
+{
+ BD_ADDR bda;
+ BD_ADDR reconn_addr;
+ void * p_cback;
+ UINT16 conn_id;
+ UINT16 cl_op_uuid;
+ UINT16 disc_handle;
+ BOOLEAN in_use;
+ BOOLEAN connected;
+ UINT8 privacy_flag;
+ BUFFER_Q pending_op_q;
+}tGAP_CLCB;
+
+typedef struct
+{
+ tGAP_INFO blk[GAP_MAX_BLOCKS];
+ tBTM_CMPL_CB *btm_cback[GAP_MAX_BLOCKS];
+ UINT8 trace_level;
+ tGAP_FINDADDR_CB findaddr_cb; /* Contains the control block for finding a device addr */
+ tBTM_INQ_INFO *cur_inqptr;
+
+#if GAP_CONN_INCLUDED == TRUE
+ tGAP_CONN conn;
+#endif
+
+ /* LE GAP attribute database */
+#if BLE_INCLUDED == TRUE
+ tGAP_ATTR gatt_attr[GAP_MAX_CHAR_NUM];
+ BD_ADDR reconn_bda;
+ tGAP_CLCB clcb[GAP_MAX_CL]; /* connection link*/
+
+ tGATT_IF gatt_if;
+#endif
+} tGAP_CB;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if GAP_DYNAMIC_MEMORY == FALSE
+ GAP_API extern tGAP_CB gap_cb;
+#else
+ GAP_API extern tGAP_CB *gap_cb_ptr;
+#define gap_cb (*gap_cb_ptr)
+#endif
+
+ extern tGAP_INFO *gap_allocate_cb(void);
+ extern void gap_free_cb(tGAP_INFO *p_cb);
+
+ /* GAP inquiry functions */
+ extern void gap_inq_results_cb(tGAP_INQ_RESULTS *p_results, UINT8 *p_eir);
+ extern UINT16 gap_find_local_addr_by_name (const BD_NAME devname, BD_ADDR bd_addr);
+ extern void gap_find_addr_inq_cb (tBTM_INQUIRY_CMPL *p);
+
+ extern BOOLEAN gap_is_service_busy (UINT16 request);
+ extern UINT16 gap_convert_btm_status (tBTM_STATUS btm_status);
+
+ extern void gap_btm_cback0(void *p1);
+#if GAP_MAX_BLOCKS > 1
+ extern void gap_btm_cback1(void *p1);
+#endif
+#if GAP_MAX_BLOCKS > 2
+ extern void gap_btm_cback2(void *p1);
+#endif
+
+#if (GAP_CONN_INCLUDED == TRUE)
+ extern void gap_conn_init(void);
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+ void gap_send_event (UINT16 gap_handle);
+ void gap_proc_btu_event(BT_HDR *p_msg);
+#endif
+#endif
+
+#if (BLE_INCLUDED == TRUE)
+ extern void gap_attr_db_init(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/stack/gap/gap_utils.c b/stack/gap/gap_utils.c
new file mode 100644
index 000000000..d253a9937
--- /dev/null
+++ b/stack/gap/gap_utils.c
@@ -0,0 +1,432 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_target.h"
+#include "gap_int.h"
+
+/*****************************************************************************/
+/* G L O B A L GAP D A T A */
+/*****************************************************************************/
+#if GAP_DYNAMIC_MEMORY == FALSE
+tGAP_CB gap_cb;
+#endif
+
+/*****************************************************************************
+** Callbacks passed to BTM -
+** There are different callbacks based on the control block index so that
+** more than one command can be pending at a time.
+** NOTE: There must be 1 callback for each control block defined
+** GAP_MAX_BLOCKS
+**
+** Also, the inquiry results event has its own callback; Not handled here!
+******************************************************************************/
+static void btm_cback(UINT16 index, void *p_data)
+{
+ tGAP_INFO *p_cb;
+ tGAP_INQ_CMPL inq_cmpl;
+
+ /* Make sure that the index is valid AND it is in use */
+ if (index < GAP_MAX_BLOCKS && gap_cb.blk[index].in_use)
+ {
+ p_cb = &gap_cb.blk[index];
+
+ /* If the callback is non-NULL, call it with the specified event */
+ switch (p_cb->event)
+ {
+ case GAP_EVT_INQUIRY_COMPLETE:
+ /* pass the number of results to caller */
+ inq_cmpl.num_results = ((tBTM_INQUIRY_CMPL *)p_data)->num_resp;
+
+ inq_cmpl.status = (((tBTM_INQUIRY_CMPL *)p_data)->status == BTM_SUCCESS) ? BT_PASS : GAP_ERR_PROCESSING;
+
+ p_data = &inq_cmpl;
+
+ GAP_TRACE_EVENT2(" GAP Inquiry Complete Event (Status 0x%04x, Result(s) %d)",
+ inq_cmpl.status, inq_cmpl.num_results);
+ break;
+
+ case GAP_EVT_DISCOVERY_COMPLETE:
+ if (*((UINT16 *) p_data))
+ {
+ GAP_TRACE_EVENT1(" GAP Discovery Complete Event(SDP Result: 0x%04x)", *((UINT16 *) p_data));
+ }
+ else
+ {
+ GAP_TRACE_EVENT0(" GAP Discovery Successfully Completed");
+ }
+
+ break;
+
+ case GAP_EVT_REM_NAME_COMPLETE:
+ /* override the BTM error code with a GAP error code */
+ ((tGAP_REMOTE_DEV_NAME *)p_data)->status =
+ gap_convert_btm_status ((tBTM_STATUS)((tBTM_REMOTE_DEV_NAME *)p_data)->status);
+
+ GAP_TRACE_EVENT1(" GAP Remote Name Complete Event (status 0x%04x)", ((tGAP_REMOTE_DEV_NAME *)p_data)->status);
+
+ break;
+ };
+
+ if (p_cb->gap_cback)
+ p_cb->gap_cback(p_cb->event, p_data);
+
+ /* Deallocate the control block */
+ gap_free_cb(p_cb);
+ }
+}
+
+
+/*** Callback functions for BTM_CMPL_CB ***/
+void gap_btm_cback0(void *p1)
+{
+ btm_cback(0, p1);
+}
+
+#if GAP_MAX_BLOCKS > 1
+void gap_btm_cback1(void *p1)
+{
+ btm_cback(1, p1);
+}
+#endif
+#if GAP_MAX_BLOCKS > 2
+void gap_btm_cback2(void *p1)
+{
+ btm_cback(2, p1);
+}
+#endif
+
+/* There is only one instance of this because only 1 inquiry can be active at a time */
+void gap_inq_results_cb(tBTM_INQ_RESULTS *p_results, UINT8 *p_eir)
+{
+ tGAP_INFO *p_cb;
+ UINT8 index;
+
+ GAP_TRACE_EVENT6 ("GAP Inquiry Results Callback (bdaddr [%02x%02x%02x%02x%02x%02x])",
+ p_results->remote_bd_addr[0], p_results->remote_bd_addr[1],
+ p_results->remote_bd_addr[2], p_results->remote_bd_addr[3],
+ p_results->remote_bd_addr[4], p_results->remote_bd_addr[5]);
+ GAP_TRACE_EVENT4 (" (COD [%02x%02x%02x], clkoff 0x%04x)",
+ p_results->dev_class[0], p_results->dev_class[1], p_results->dev_class[2],
+ p_results->clock_offset);
+
+ /* Find the control block which has an Inquiry Active and call its results callback */
+ for (index = 0, p_cb = &gap_cb.blk[0]; index < GAP_MAX_BLOCKS; index++, p_cb++)
+ {
+ /* Look for the control block that is using inquiry */
+ if (p_cb->in_use && (p_cb->event == GAP_EVT_INQUIRY_COMPLETE))
+ {
+ /* Notify the higher layer if they care */
+ if (p_cb->gap_inq_rslt_cback)
+ p_cb->gap_inq_rslt_cback (GAP_EVT_INQUIRY_RESULTS, (tGAP_INQ_RESULTS *)p_results);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_find_addr_name_cb
+**
+** Description Processes the remote name request event when the Find Addr by Name
+** request is active. The following procedure takes place:
+** 1. Check the resulting name (If return status is ok)
+** 2. If name matches requested name, we're done, call the appl's callback
+** with the BD ADDR.
+** 3. Otherwise get the next BD ADDR out of the inquiry database and intiate
+** another remote name request.
+** 4. If there are no more BD ADDRs, then call the appl's callback with a FAIL
+** status.
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_find_addr_name_cb (tBTM_REMOTE_DEV_NAME *p)
+{
+ tGAP_FINDADDR_CB *p_cb = &gap_cb.findaddr_cb;
+ tGAP_FINDADDR_RESULTS *p_result = &p_cb->results;
+
+ if (p_cb->in_use)
+ {
+ if (p->status == BTM_SUCCESS)
+ {
+ GAP_TRACE_EVENT2(" GAP: FindAddrByName Rem Name Cmpl Evt (Status 0x%04x, Name [%s])",
+ p->status, p->remote_bd_name);
+
+ /* See if the returned name matches the desired name; if not initiate another search */
+ if (!strncmp ((char *)p_result->devname, (char *) p->remote_bd_name, strlen ((char *) p_result->devname)))
+ {
+ /* We found the device! Copy it into the return structure */
+ memcpy (p_result->bd_addr, p_cb->p_cur_inq->results.remote_bd_addr, BD_ADDR_LEN);
+ p_result->status = BT_PASS;
+ }
+ else /* The name doesn't match so initiate another search */
+ {
+ /* Get the device address of the next database entry */
+ if ((p_cb->p_cur_inq = BTM_InqDbNext(p_cb->p_cur_inq)) != NULL)
+ {
+ if ((BTM_ReadRemoteDeviceName (p_cb->p_cur_inq->results.remote_bd_addr,
+ (tBTM_CMPL_CB *) gap_find_addr_name_cb)) == BTM_CMD_STARTED)
+ return; /* This routine will get called again with the next results */
+ else
+ p_result->status = gap_convert_btm_status ((tBTM_STATUS) p->status);
+ }
+ else
+ p_result->status = GAP_EOINQDB; /* No inquiry results; we're done! */
+ }
+ }
+ else
+ {
+ GAP_TRACE_EVENT1(" GAP: FindAddrByName Rem Name Cmpl Evt (Status 0x%04x)", p->status);
+ p_result->status = gap_convert_btm_status ((tBTM_STATUS) p->status);
+ }
+
+ /* If this code is reached, the process has completed so call the appl's callback with results */
+ if (p_cb->p_cback)
+ p_cb->p_cback (GAP_EVT_FIND_ADDR_COMPLETE, (tGAP_FINDADDR_RESULTS *) p_result);
+
+ /* Clear out the control block */
+ p_cb->in_use = FALSE;
+ p_cb->p_cback = (tGAP_CALLBACK *) NULL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_find_addr_inq_cb
+**
+** Description Processes the inquiry complete event when the Find Addr by Name
+** request is active. This callback performs one of the two following
+** steps:
+** 1. If the remote name is retrieved automatically, the DB is searched
+** immediately, and the results are returned in the appls callback.
+**
+** 2. If remote name is not automatic, retrieve the first BTM INQ
+** database entry and initiate a remote name request.
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_find_addr_inq_cb (tBTM_INQUIRY_CMPL *p)
+{
+ tGAP_FINDADDR_CB *p_cb = &gap_cb.findaddr_cb;
+ tGAP_FINDADDR_RESULTS *p_result = &p_cb->results;
+
+ if (p_cb->in_use)
+ {
+
+ GAP_TRACE_EVENT2(" GAP: FindAddrByName Inq Cmpl Evt (Status 0x%04x, Result(s) %d)",
+ p->status, p->num_resp);
+
+ if (p->status == BTM_SUCCESS)
+ {
+ /* Step 1: If automatically retrieving remote names then search the local database */
+ if ((p_result->status = gap_find_local_addr_by_name (p_result->devname, p_result->bd_addr)) == GAP_NO_DATA_AVAIL)
+ {
+ /* Step 2: The name is not stored automatically, so a search of all devices needs to
+ * be initiated.
+ */
+ if ((p_cb->p_cur_inq = BTM_InqDbFirst()) != NULL)
+ {
+ if ((BTM_ReadRemoteDeviceName (p_cb->p_cur_inq->results.remote_bd_addr,
+ (tBTM_CMPL_CB *) gap_find_addr_name_cb)) == BTM_CMD_STARTED)
+ return; /* Wait for the response in gap_find_addr_name_cb() */
+ else
+ p_result->status = gap_convert_btm_status (p->status);
+ }
+ else
+ p_result->status = GAP_EOINQDB; /* No inquiry results; we're done! */
+ }
+ }
+ else
+ p_result->status = gap_convert_btm_status (p->status);
+
+ /* If this code is reached, the process has completed so call the appl's callback with results */
+ if (p_cb->p_cback)
+ p_cb->p_cback (GAP_EVT_FIND_ADDR_COMPLETE, (tGAP_FINDADDR_RESULTS *) p_result);
+
+ /* Clear out the control block */
+ p_cb->in_use = FALSE;
+ p_cb->p_cback = (tGAP_CALLBACK *) NULL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_find_local_addr_by_name
+**
+** Description Searches through the internal inquiry database for a device
+** that has the same name as the one passed in. If found, the
+** device address is filled in.
+**
+** NOTE: It only searches up to the first BTM_MAX_REM_BD_NAME_LEN
+** bytes because the inquiry database uses tBTM_BD_NAME.
+**
+** Returns BT_PASS if the name was found and the device address is filled in
+** GAP_EOINQDB if the name was not found in the database
+** GAP_NO_DATA_AVAIL if the name is not saved with the inquiry
+**
+*******************************************************************************/
+UINT16 gap_find_local_addr_by_name (const tBTM_BD_NAME devname, BD_ADDR bd_addr)
+{
+
+/* If the remote name is retrieved automatically during an inquiry search the local db */
+#if (BTM_INQ_GET_REMOTE_NAME == TRUE)
+ tBTM_INQ_INFO *p_result;
+
+ p_result = BTM_InqDbFirst();
+
+ while (p_result)
+ {
+ /* Check the entry for a device name match */
+ if (!strncmp ((char *)devname, (char *)p_result->remote_name, BTM_MAX_REM_BD_NAME_LEN))
+ {
+ memcpy (bd_addr, p_result->results.remote_bd_addr, BD_ADDR_LEN);
+ return (BT_PASS);
+ }
+ else
+ p_result = BTM_InqDbNext(p_result);
+ };
+
+ return (GAP_EOINQDB);
+#else
+ /* No data available because we are not automatically saving the data */
+ return (GAP_NO_DATA_AVAIL);
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function gap_allocate_cb
+**
+** Description Look through the GAP Control Blocks for a free one.
+**
+** Returns Pointer to the control block or NULL if not found
+**
+*******************************************************************************/
+tGAP_INFO *gap_allocate_cb (void)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (!p_cb->in_use)
+ {
+ memset (p_cb, 0, sizeof (tGAP_INFO));
+
+ p_cb->in_use = TRUE;
+ p_cb->index = x;
+ p_cb->p_data = (void *)NULL;
+ return (p_cb);
+ }
+ }
+
+ /* If here, no free control blocks found */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_free_cb
+**
+** Description Release GAP control block.
+**
+** Returns Pointer to the control block or NULL if not found
+**
+*******************************************************************************/
+void gap_free_cb (tGAP_INFO *p_cb)
+{
+ if (p_cb)
+ {
+ p_cb->gap_cback = NULL;
+ p_cb->in_use = FALSE;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_is_service_busy
+**
+** Description Look through the GAP Control Blocks that are in use
+** and check to see if the event waiting for is the command
+** requested.
+**
+** Returns TRUE if already in use
+** FALSE if not busy
+**
+*******************************************************************************/
+BOOLEAN gap_is_service_busy (UINT16 request)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (p_cb->in_use && p_cb->event == request)
+ return (TRUE);
+ }
+
+ /* If here, service is not busy */
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_convert_btm_status
+**
+** Description Converts a BTM error status into a GAP error status
+**
+**
+** Returns GAP_UNKNOWN_BTM_STATUS is returned if not recognized
+**
+*******************************************************************************/
+UINT16 gap_convert_btm_status (tBTM_STATUS btm_status)
+{
+ switch (btm_status)
+ {
+ case BTM_SUCCESS:
+ return (BT_PASS);
+
+ case BTM_CMD_STARTED:
+ return (GAP_CMD_INITIATED);
+
+ case BTM_BUSY:
+ return (GAP_ERR_BUSY);
+
+ case BTM_MODE_UNSUPPORTED:
+ case BTM_ILLEGAL_VALUE:
+ return (GAP_ERR_ILL_PARM);
+
+ case BTM_WRONG_MODE:
+ return (GAP_DEVICE_NOT_UP);
+
+ case BTM_UNKNOWN_ADDR:
+ return (GAP_BAD_BD_ADDR);
+
+ case BTM_DEVICE_TIMEOUT:
+ return (GAP_ERR_TIMEOUT);
+
+ default:
+ return (GAP_ERR_PROCESSING);
+ }
+}
diff --git a/stack/gatt/att_protocol.c b/stack/gatt/att_protocol.c
index a114a3338..9c715af6a 100644
--- a/stack/gatt/att_protocol.c
+++ b/stack/gatt/att_protocol.c
@@ -390,13 +390,13 @@ BT_HDR *attp_build_sr_msg(tGATT_TCB *p_tcb, UINT8 op_code, tGATT_SR_MSG *p_msg)
switch (op_code)
{
case GATT_RSP_READ_BLOB:
- GATT_TRACE_EVENT2 ("ATT_RSP_READ_BLOB: len = %d offset = %d", p_msg->attr_value.len, p_msg->attr_value.offset);
- offset = p_msg->attr_value.offset;
-
case GATT_RSP_PREPARE_WRITE:
- if (offset == 0)
- offset = p_msg->attr_value.offset;
-
+ GATT_TRACE_EVENT2 ("ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = %d offset = %d",
+ p_msg->attr_value.len, p_msg->attr_value.offset);
+ offset = p_msg->attr_value.offset;
+/* Coverity: [FALSE-POSITIVE error] intended fall through */
+/* Missing break statement between cases in switch statement */
+ /* fall through */
case GATT_RSP_READ_BY_TYPE:
case GATT_RSP_READ:
case GATT_HANDLE_VALUE_NOTIF:
@@ -503,7 +503,10 @@ UINT8 attp_cl_send_cmd(tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 cmd_code, BT_HDR
att_ret = GATT_INTERNAL_ERROR;
}
else
+ {
+ att_ret = GATT_CMD_STARTED;
gatt_cmd_enq(p_tcb, clcb_idx, TRUE, cmd_code, p_cmd);
+ }
}
else
att_ret = GATT_ILLEGAL_PARAMETER;
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 7845f3c2c..ef437e130 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -849,6 +849,7 @@ tGATT_STATUS GATTC_Discover (UINT16 conn_id, tGATT_DISC_TYPE disc_type,
(disc_type == GATT_DISC_SRVC_BY_UUID &&
p_param->service.len == 0))
{
+ gatt_clcb_dealloc(p_clcb);
return GATT_ILLEGAL_PARAMETER;
}
@@ -1313,7 +1314,6 @@ void GATT_StartIf (tGATT_IF gatt_if)
{
tGATT_REG *p_reg;
tGATT_TCB *p_tcb;
- //tGATT_CLCB *p_clcb;
BD_ADDR bda;
UINT8 start_idx, found_idx;
UINT16 conn_id;
@@ -1326,7 +1326,7 @@ void GATT_StartIf (tGATT_IF gatt_if)
while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
{
p_tcb = gatt_find_tcb_by_addr(bda);
- if (p_reg->app_cb.p_conn_cb)
+ if (p_reg->app_cb.p_conn_cb && p_tcb)
{
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
(*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0);
@@ -1341,7 +1341,8 @@ void GATT_StartIf (tGATT_IF gatt_if)
**
** Function GATT_Connect
**
-** Description This function initiate a connecttion to a ATT server.
+** Description This function initiate a connecttion to a remote device on GATT
+** channel.
**
** Parameters gatt_if: applicaiton interface
** bd_addr: peer device address.
@@ -1366,7 +1367,7 @@ BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct){
if (is_direct)
status = gatt_act_connect (p_reg, bd_addr);
else
- status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr);
+ status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr, TRUE);
return status;
@@ -1376,7 +1377,8 @@ BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct){
**
** Function GATT_CancelConnect
**
-** Description This function initiate a connecttion to a ATT server.
+** Description This function terminate the connection initaition to a remote
+** device on GATT channel.
**
** Parameters gatt_if: client interface. If 0 used as unconditionally disconnect,
** typically used for direct connection cancellation.
@@ -1454,7 +1456,8 @@ BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct
**
** Function GATT_Disconnect
**
-** Description This function disconnect a logic channel.
+** Description This function disconnect the GATT channel for this registered
+** application.
**
** Parameters conn_id: connection identifier.
**
@@ -1550,6 +1553,50 @@ BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_c
return status;
}
-#endif
+/*******************************************************************************
+**
+** Function GATT_Listen
+**
+** Description This function start or stop LE advertisement and listen for
+** connection.
+**
+** Parameters gatt_if: applicaiton interface
+** p_bd_addr: listen for specific address connection, or NULL for
+** listen to all device connection.
+** start: is a direct conenection or a background auto connection
+**
+** Returns TRUE if advertisement is started; FALSE if adv start failure.
+**
+*******************************************************************************/
+BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr)
+{
+ tGATT_REG *p_reg;
+ BOOLEAN status = TRUE;
+
+ GATT_TRACE_API1 ("GATT_Listen gatt_if=%d", gatt_if);
+
+ /* Make sure app is registered */
+ if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
+ {
+ GATT_TRACE_ERROR1("GATT_Listen - gatt_if =%d is not registered", gatt_if);
+ return(FALSE);
+ }
+
+ if (bd_addr != NULL)
+ {
+ status = gatt_update_auto_connect_dev(gatt_if,start, bd_addr, FALSE);
+ }
+ else
+ {
+ p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE;
+ }
+
+ gatt_update_listen_mode();
+
+ return status;
+
+}
+
+#endif
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index b7ec2fcbd..459580ed3 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -183,7 +183,7 @@ static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_
break;
case GATTS_REQ_TYPE_WRITE_EXEC:
- //case GATT_CMD_WRITE:
+ case GATT_CMD_WRITE:
ignore = TRUE;
GATT_TRACE_EVENT0("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD" );
break;
@@ -269,7 +269,7 @@ void gatt_profile_db_init (void)
/* start service
*/
- status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATT_TRANSPORT_LE_BR_EDR);
+ status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
GATT_TRACE_DEBUG2 ("gatt_profile_db_init: gatt_if=%d start status%d",
gatt_cb.gatt_if, status);
diff --git a/stack/gatt/gatt_auth.c b/stack/gatt/gatt_auth.c
index de0c14f9b..df42758c2 100644
--- a/stack/gatt/gatt_auth.c
+++ b/stack/gatt/gatt_auth.c
@@ -48,6 +48,9 @@ static BOOLEAN gatt_sign_data (tGATT_CLCB *p_clcb)
BOOLEAN status = FALSE;
UINT8 *p_signature;
+ /* do not need to mark channel securoty activity for data signing */
+ gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_OK);
+
p_data = (UINT8 *)GKI_getbuf((UINT16)(p_attr->len + 3)); /* 3 = 2 byte handle + opcode */
if (p_data != NULL)
@@ -69,7 +72,7 @@ static BOOLEAN gatt_sign_data (tGATT_CLCB *p_clcb)
{
p_attr->len += BTM_BLE_AUTH_SIGN_LEN;
gatt_set_ch_state(p_clcb->p_tcb, GATT_CH_OPEN);
- gatt_act_write(p_clcb);
+ gatt_act_write(p_clcb, GATT_SEC_SIGN_DATA);
}
else
{
@@ -126,10 +129,10 @@ void gatt_verify_signature(tGATT_TCB *p_tcb, BT_HDR *p_buf)
** Returns void.
**
*******************************************************************************/
-void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb)
+void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb, UINT8 sec_act)
{
- p_clcb->p_tcb->p_clcb = NULL;
- gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);
+ if (GKI_queue_is_empty(&p_clcb->p_tcb->pending_enc_clcb))
+ gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);
if (!sec_check_ok)
{
@@ -137,7 +140,7 @@ void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb)
}
else if (p_clcb->operation == GATTC_OPTYPE_WRITE)
{
- gatt_act_write(p_clcb);
+ gatt_act_write(p_clcb, sec_act);
}
else if (p_clcb->operation == GATTC_OPTYPE_READ)
{
@@ -158,28 +161,51 @@ void gatt_enc_cmpl_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
tGATT_TCB *p_tcb;
UINT8 sec_flag;
BOOLEAN status = FALSE;
+ tGATT_PENDING_ENC_CLCB *p_buf;
+ UINT16 count;
GATT_TRACE_DEBUG0("gatt_enc_cmpl_cback");
if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
{
- gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+ if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
+ return;
- if (result == BTM_SUCCESS)
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
{
- if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM )
+ if (result == BTM_SUCCESS)
{
- BTM_GetSecurityFlags(bd_addr, &sec_flag);
- if (sec_flag & sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+ if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM )
+ {
+ BTM_GetSecurityFlags(bd_addr, &sec_flag);
+ if (sec_flag & sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+ {
+ status = TRUE;
+ }
+ }
+ else
{
status = TRUE;
}
}
- else
+ gatt_sec_check_complete(status , p_buf->p_clcb, p_tcb->sec_act);
+ GKI_freebuf(p_buf);
+ /* start all other pending operation in queue */
+ count = p_tcb->pending_enc_clcb.count;
+ for (; count > 0; count --)
{
- status = TRUE;
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
+ {
+ gatt_security_check_start(p_buf->p_clcb);
+ GKI_freebuf(p_buf);
+ }
+ else
+ break;
}
}
- gatt_sec_check_complete(status , (tGATT_CLCB *)p_tcb->p_clcb);
+ else
+ {
+ GATT_TRACE_ERROR0("Unknown operation encryption completed");
+ }
}
else
{
@@ -189,6 +215,48 @@ void gatt_enc_cmpl_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
/*******************************************************************************
**
+** Function gatt_notify_enc_cmpl
+**
+** Description link encryption complete notification for all encryption process
+** initiated outside GATT.
+**
+** Returns
+**
+*******************************************************************************/
+void gatt_notify_enc_cmpl(BD_ADDR bd_addr)
+{
+ tGATT_TCB *p_tcb;
+ tGATT_PENDING_ENC_CLCB *p_buf;
+ UINT16 count;
+
+ if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
+ {
+ if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
+ {
+ gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
+
+ count = p_tcb->pending_enc_clcb.count;
+
+ for (; count > 0; count --)
+ {
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
+ {
+ gatt_security_check_start(p_buf->p_clcb);
+ GKI_freebuf(p_buf);
+ }
+ else
+ break;
+ }
+ }
+ }
+ else
+ {
+ GATT_TRACE_DEBUG0("notify GATT for encryption completion of unknown device");
+ }
+ return;
+}
+/*******************************************************************************
+**
** Function gatt_set_sec_act
**
** Description This function set the sec_act in clcb
@@ -243,18 +311,32 @@ tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB *p_clcb )
BOOLEAN is_link_key_known=FALSE;
BOOLEAN is_key_mitm=FALSE;
UINT8 key_type;
+ tBTM_BLE_SEC_REQ_ACT sec_act = BTM_LE_SEC_NONE;
if (auth_req == GATT_AUTH_REQ_NONE )
return act;
is_le_link = btm_ble_check_link_type(p_tcb->peer_bda);
BTM_GetSecurityFlags(p_tcb->peer_bda, &sec_flag);
+ btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act);
+
+ /* if a encryption is pending, need to wait */
+ if (sec_act == BTM_BLE_SEC_REQ_ACT_DISCARD &&
+ auth_req != GATT_AUTH_REQ_NONE)
+ return GATT_SEC_ENC_PENDING;
if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
{
is_link_encrypted = TRUE;
+ is_link_key_known = TRUE;
+
+ if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+ {
+ is_key_mitm = TRUE;
+ }
+
}
- if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
+ else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
{
is_link_key_known = TRUE;
if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
@@ -397,48 +479,49 @@ BOOLEAN gatt_security_check_start(tGATT_CLCB *p_clcb)
tBTM_BLE_SEC_ACT btm_ble_sec_act;
BOOLEAN status = TRUE;
tBTM_STATUS btm_status;
+ tGATT_SEC_ACTION sec_act_old = gatt_get_sec_act(p_tcb);
- if ( gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
- {
- gatt_sec_act = gatt_determine_sec_act(p_clcb);
+ gatt_sec_act = gatt_determine_sec_act(p_clcb);
+
+ if (sec_act_old == GATT_SEC_NONE)
gatt_set_sec_act(p_tcb, gatt_sec_act);
- switch (gatt_sec_act )
- {
- case GATT_SEC_SIGN_DATA:
- GATT_TRACE_DEBUG0("gatt_security_check_start: Do data signing");
- gatt_set_ch_state(p_tcb, GATT_CH_W4_DATA_SIGN_COMP);
- gatt_sign_data(p_clcb);
- break;
- case GATT_SEC_ENCRYPT:
- case GATT_SEC_ENCRYPT_NO_MITM:
- case GATT_SEC_ENCRYPT_MITM:
+
+ switch (gatt_sec_act )
+ {
+ case GATT_SEC_SIGN_DATA:
+ GATT_TRACE_DEBUG0("gatt_security_check_start: Do data signing");
+ gatt_sign_data(p_clcb);
+ break;
+ case GATT_SEC_ENCRYPT:
+ case GATT_SEC_ENCRYPT_NO_MITM:
+ case GATT_SEC_ENCRYPT_MITM:
+ if (sec_act_old < GATT_SEC_ENCRYPT)
+ {
GATT_TRACE_DEBUG0("gatt_security_check_start: Encrypt now or key upgreade first");
- gatt_convert_sec_action(p_tcb->sec_act, &btm_ble_sec_act);
- gatt_set_ch_state(p_tcb, GATT_CH_W4_SEC_COMP);
- p_tcb->p_clcb = p_clcb; /* keep the clcb pointer in CCB */
+ gatt_convert_sec_action(gatt_sec_act, &btm_ble_sec_act);
btm_status = BTM_SetEncryption(p_tcb->peer_bda, gatt_enc_cmpl_cback, &btm_ble_sec_act);
if ( (btm_status != BTM_SUCCESS) && (btm_status != BTM_CMD_STARTED))
{
GATT_TRACE_ERROR1("gatt_security_check_start BTM_SetEncryption failed btm_status=%d", btm_status);
- p_tcb->p_clcb = NULL;
status = FALSE;
}
- break;
- default:
- gatt_sec_check_complete(TRUE, p_clcb);
- break;
- }
-
- if (status == FALSE)
- {
- gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
- gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
- }
+ }
+ if (status)
+ gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb);
+ break;
+ case GATT_SEC_ENC_PENDING:
+ gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb);
+ /* wait for link encrypotion to finish */
+ break;
+ default:
+ gatt_sec_check_complete(TRUE, p_clcb, gatt_sec_act);
+ break;
}
- else
+
+ if (status == FALSE)
{
- GATT_TRACE_ERROR0("gatt_security_check_start channel not open");
- status = FALSE;
+ gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
+ gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
}
return status;
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index 91fb98516..e9402aaed 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -201,7 +201,7 @@ void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset)
** Returns void.
**
*******************************************************************************/
-void gatt_act_write (tGATT_CLCB *p_clcb)
+void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
{
tGATT_TCB *p_tcb = p_clcb->p_tcb;
UINT8 rt = GATT_SUCCESS, op_code;
@@ -213,7 +213,7 @@ void gatt_act_write (tGATT_CLCB *p_clcb)
{
case GATT_WRITE_NO_RSP:
p_clcb->s_handle = p_attr->handle;
- op_code = (p_tcb->sec_act & GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
+ op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
rt = gatt_send_write_msg(p_tcb,
p_clcb->clcb_idx,
op_code,
@@ -379,59 +379,7 @@ void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb)
}
}
-/*******************************************************************************
-**
-** Function gatt_proc_disc_read_by_type_rsp
-**
-** Description This function process the read by type response and send another
-** request if needed.
-**
-** Returns void.
-**
-*******************************************************************************/
-void gatt_proc_disc_read_by_type_rsp(tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
-{
- /*
- tGATT_TCB *p_tcb = p_clcb->p_tcb;
- tGATT_DISCOVERY_DB *p_db = p_clcb->p_disc_db;
- tGATT_DISC_REC *p_rec;
- tGATT_STATUS status = GATT_INTERNAL_ERROR;
-
-
- if ((p_rec = gatt_add_record(p_clcb->p_disc_db)) != NULL)
- {
- p_rec->handle = handle;
- p_rec->type = p_db->uuid_filter;
- p_rec->attr_len = len;
-
- // copy the attibute value into DB
- p_rec->p_value = p_db->p_free_mem;
- memcpy(p_rec->p_value, p_value, len);
- p_db->p_free_mem += len;
- p_db->mem_free -= len;
-
- if (handle < p_clcb->e_handle)
- {
- // send another request
- if (gatt_act_send_browse(p_tcb, p_clcb->conn_id,
- GATT_REQ_READ_BY_TYPE,
- (UINT16)(handle + 1), // starting handle
- p_clcb->e_handle, // end handle
- p_clcb->p_disc_db->uuid_filter) // uuid filter /
- == GATT_SUCCESS)
- {
- status = GATT_SUCCESS;
- }
- }
- }
- else
- status = GATT_DB_FULL;
-
- if (status != GATT_SUCCESS) // DB full
- {
- gatt_end_operation(p_clcb, status, NULL);
- }*/
-}
+
/*******************************************************************************
**
** Function gatt_process_find_type_value_rsp
@@ -445,7 +393,6 @@ void gatt_proc_disc_read_by_type_rsp(tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_da
void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
{
tGATT_DISC_RES result;
- tGATT_DISC_VALUE record_value;
UINT8 *p = p_data;
GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp ");
@@ -453,7 +400,7 @@ void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UIN
if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
return;
- memset (&record_value, 0, sizeof(tGATT_DISC_VALUE));
+ memset (&result, 0, sizeof(tGATT_DISC_RES));
result.type.len = 2;
result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
@@ -461,17 +408,17 @@ void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UIN
while (len >= 4)
{
STREAM_TO_UINT16 (result.handle, p);
- STREAM_TO_UINT16 (record_value.handle, p);
- len -= 4;
+ STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
+ memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID));
- memcpy (&result.value, &record_value, sizeof (result.value));;
+ len -= 4;
if (p_clcb->p_reg->app_cb.p_disc_res_cb)
(*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
}
/* last handle + 1 */
- p_clcb->s_handle = (record_value.handle == 0) ? 0 : (record_value.handle + 1);
+ p_clcb->s_handle = (result.value.group_value.e_handle == 0) ? 0 : (result.value.group_value.e_handle + 1);
/* initiate another request */
gatt_act_discovery(p_clcb) ;
}
@@ -721,12 +668,12 @@ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
}
+ encrypt_status = gatt_get_link_encrypt_status(p_tcb);
for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
{
if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
{
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
- encrypt_status = gatt_get_link_encrypt_status(p_tcb);
(*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
}
}
@@ -882,7 +829,12 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
return;
}
- gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p);
+ if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
+ {
+ gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+ /* invalid format, and skip the result */
+ return;
+ }
/* UUID not matching */
if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
@@ -1087,6 +1039,8 @@ BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
{
tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
BOOLEAN sent = FALSE;
+ UINT8 rsp_code;
+ tGATT_CLCB *p_clcb = NULL;
while (!sent &&
p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
@@ -1099,7 +1053,21 @@ BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
p_cmd->to_send = FALSE;
p_cmd->p_cmd = NULL;
- gatt_start_rsp_timer (p_tcb);
+ /* dequeue the request if is write command or sign write */
+ if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
+ {
+ gatt_start_rsp_timer (p_tcb);
+ }
+ else
+ {
+ p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
+
+ /* if no ack needed, keep sending */
+ sent = FALSE;
+ p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
+ /* send command complete callback here */
+ gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+ }
}
else
{
@@ -1109,6 +1077,7 @@ BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
p_tcb->pending_cl_req ++;
p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
}
+
}
return sent;
}
diff --git a/stack/gatt/gatt_db.c b/stack/gatt/gatt_db.c
index bd94e5060..fa636fba9 100644
--- a/stack/gatt/gatt_db.c
+++ b/stack/gatt/gatt_db.c
@@ -134,7 +134,8 @@ static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr,
return GATT_READ_NOT_PERMIT;
}
- if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
+ if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
+ !(sec_flag & BTM_SEC_FLAG_ENCRYPTED))
{
GATT_TRACE_ERROR0( "GATT_INSUF_AUTHENTICATION");
return GATT_INSUF_AUTHENTICATION;
@@ -731,14 +732,21 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code,
p_attr->permission,
min_key_size);
- if ((op_code == GATT_CMD_WRITE) && (perm & GATT_WRITE_SIGNED_PERM) )
+ if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE)
+ && (perm & GATT_WRITE_SIGNED_PERM))
{
/* use the rules for the mixed security see section 10.2.3*/
- if (perm & GATT_PERM_WRITE_SIGNED)
+ /* use security mode 1 level 2 when the following condition follows */
+ /* LE security mode 2 level 1 and LE security mode 1 level 2 */
+ if ((perm & GATT_PERM_WRITE_SIGNED) && (perm & GATT_PERM_WRITE_ENCRYPTED))
{
perm = GATT_PERM_WRITE_ENCRYPTED;
}
- else
+ /* use security mode 1 level 3 when the following condition follows */
+ /* LE security mode 2 level 2 and security mode 1 and LE */
+ else if (((perm & GATT_PERM_WRITE_SIGNED_MITM) && (perm & GATT_PERM_WRITE_ENCRYPTED)) ||
+ /* LE security mode 2 and security mode 1 level 3 */
+ ((perm & GATT_WRITE_SIGNED_PERM) && (perm & GATT_PERM_WRITE_ENC_MITM)))
{
perm = GATT_PERM_WRITE_ENC_MITM;
}
@@ -759,6 +767,7 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code,
status = GATT_WRITE_NOT_PERMIT;
GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT");
}
+ /* require authentication, but not been authenticated */
else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
{
status = GATT_INSUF_AUTHENTICATION;
@@ -779,6 +788,12 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code,
status = GATT_INSUF_KEY_SIZE;
GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE");
}
+ /* LE security mode 2 attribute */
+ else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED))
+ {
+ status = GATT_INSUF_AUTHENTICATION;
+ GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required");
+ }
else /* writable: must be char value declaration or char descritpors */
{
if(p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16)
@@ -793,6 +808,9 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code,
break;
case GATT_UUID_CHAR_CLIENT_CONFIG:
+/* coverity[MISSING_BREAK] */
+/* intnended fall through, ignored */
+ /* fall through */
case GATT_UUID_CHAR_SRVR_CONFIG:
max_size = 2;
case GATT_UUID_CHAR_DESCRIPTION:
@@ -828,7 +846,7 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code,
}
else if (len != max_size) /* data does not match the required format */
{
- status = GATT_INVALID_PDU;
+ status = GATT_INVALID_ATTR_LEN;
GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INVALID_PDU");
}
else
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 44a2bc1d9..48278c20e 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -42,10 +42,11 @@
/* security action for GATT write and read request */
#define GATT_SEC_NONE 0
#define GATT_SEC_OK 1
-#define GATT_SEC_ENCRYPT 2 /* encrypt the link with current key */
-#define GATT_SEC_ENCRYPT_NO_MITM 3 /* unauthenticated encryption or better */
-#define GATT_SEC_ENCRYPT_MITM 4 /* authenticated encryption */
-#define GATT_SEC_SIGN_DATA 5 /* compute the signature for the write cmd */
+#define GATT_SEC_SIGN_DATA 2 /* compute the signature for the write cmd */
+#define GATT_SEC_ENCRYPT 3 /* encrypt the link with current key */
+#define GATT_SEC_ENCRYPT_NO_MITM 4 /* unauthenticated encryption or better */
+#define GATT_SEC_ENCRYPT_MITM 5 /* authenticated encryption */
+#define GATT_SEC_ENC_PENDING 6 /* wait for link encryption pending */
typedef UINT8 tGATT_SEC_ACTION;
@@ -214,7 +215,6 @@ typedef struct
typedef struct
{
tGATT_SVC_DB *p_db; /* pointer to the service database */
- //tGATT_SR_CBACK sr_cb; /* server callback functions */
tBT_UUID app_uuid; /* applicatino UUID */
UINT32 sdp_handle; /* primamry service SDP handle */
UINT16 service_instance; /* service instance number */
@@ -225,6 +225,8 @@ typedef struct
BOOLEAN in_use;
} tGATT_SR_REG;
+#define GATT_LISTEN_TO_ALL 0xff
+#define GATT_LISTEN_TO_NONE 0
/* Data Structure used for GATT server */
/* An GATT registration record consists of a handle, and 1 or more attributes */
@@ -237,6 +239,7 @@ typedef struct
tGATT_CBACK app_cb;
tGATT_IF gatt_if; /* one based */
BOOLEAN in_use;
+ UINT8 listening; /* if adv for all has been enabled */
} tGATT_REG;
@@ -332,7 +335,7 @@ typedef struct
typedef struct
{
- void *p_clcb; /* which clcb is doing encryption */
+ BUFFER_Q pending_enc_clcb; /* pending encryption channel q */
tGATT_SEC_ACTION sec_act;
BD_ADDR peer_bda;
UINT32 trans_id;
@@ -366,6 +369,7 @@ typedef struct
UINT8 tcb_idx;
} tGATT_TCB;
+
/* logic channel */
typedef struct
{
@@ -395,6 +399,12 @@ typedef struct
BOOLEAN in_use;
} tGATT_CLCB;
+typedef struct
+{
+ tGATT_CLCB *p_clcb;
+}tGATT_PENDING_ENC_CLCB;
+
+
#define GATT_SIGN_WRITE 1
#define GATT_VERIFY_SIGN_DATA 2
@@ -429,6 +439,7 @@ typedef struct
typedef struct
{
tGATT_IF gatt_if[GATT_MAX_APPS];
+ tGATT_IF listen_gif[GATT_MAX_APPS];
BD_ADDR remote_bda;
BOOLEAN in_use;
}tGATT_BG_CONN_DEV;
@@ -468,6 +479,7 @@ typedef struct
BOOLEAN enable_err_rsp;
UINT8 req_op_code;
UINT8 err_status;
+ UINT16 handle;
#endif
tGATT_PROFILE_CLCB profile_clcb[GATT_MAX_APPS];
@@ -551,6 +563,7 @@ extern void gatt_ind_ack_timeout(TIMER_LIST_ENT *p_tle);
extern void gatt_start_ind_ack_timer(tGATT_TCB *p_tcb);
extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB *p_tcb, UINT8 err_code, UINT8 op_code, UINT16 handle, BOOLEAN deq);
extern void gatt_dbg_display_uuid(tBT_UUID bt_uuid);
+extern tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb );
extern tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
@@ -563,6 +576,7 @@ extern void gatt_delete_dev_from_srv_chg_clt_list(BD_ADDR bd_addr);
extern tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB *p_tcb, tGATT_VALUE *p_ind);
extern tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start( tGATTS_HNDL_RANGE *p_new_srv_start);
extern void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id);
+extern void gatt_update_listen_mode(void);
/* reserved handle list */
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
@@ -578,13 +592,11 @@ extern BOOLEAN gatt_remove_an_item_from_list(tGATT_HDL_LIST_INFO *p_list, tGATT_
extern tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg);
/* for background connection */
-extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr);
-extern BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr);
+extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initiator);
extern BOOLEAN gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV *p_dev, tGATT_IF gatt_if);
extern BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr);
extern UINT8 gatt_get_num_apps_for_bg_dev(BD_ADDR bd_addr);
extern BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if);
-extern BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr);
extern tGATT_BG_CONN_DEV * gatt_find_bg_dev(BD_ADDR remote_bda);
extern void gatt_deregister_bgdev_list(tGATT_IF gatt_if);
extern void gatt_reset_bgdev_list(void);
@@ -634,7 +646,7 @@ extern void gatt_end_operation(tGATT_CLCB *p_clcb, tGATT_STATUS status, void *p_
extern void gatt_act_discovery(tGATT_CLCB *p_clcb);
extern void gatt_act_read(tGATT_CLCB *p_clcb, UINT16 offset);
-extern void gatt_act_write(tGATT_CLCB *p_clcb);
+extern void gatt_act_write(tGATT_CLCB *p_clcb, UINT8 sec_act);
extern UINT8 gatt_act_send_browse(tGATT_TCB *p_tcb, UINT16 index, UINT8 op, UINT16 s_handle, UINT16 e_handle,
tBT_UUID uuid);
extern tGATT_CLCB *gatt_cmd_dequeue(tGATT_TCB *p_tcb, UINT8 *p_opcode);
@@ -666,6 +678,7 @@ extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, BOOLEAN is_lo
extern void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary);
extern tBT_UUID * gatts_get_service_uuid (tGATT_SVC_DB *p_db);
+extern void gatt_reset_bgdev_list(void);
#endif
#endif /* BLE_INCLUDED */
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 06d87bb24..dcd939840 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -49,7 +49,7 @@ static void gatt_l2cif_config_cfm_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cf
static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed);
static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg);
-static void gatt_send_conn_cback (BOOLEAN is_bg_conn, tGATT_TCB *p_tcb);
+static void gatt_send_conn_cback (tGATT_TCB *p_tcb);
static const tL2CAP_APPL_INFO dyn_info =
{
@@ -145,7 +145,8 @@ BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb)
BTM_ReadDevInfo(rem_bda, &dev_type, &addr_type);
- gatt_set_ch_state(p_tcb, GATT_CH_CONN);
+ if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN)
+ gatt_set_ch_state(p_tcb, GATT_CH_CONN);
if (dev_type == BT_DEVICE_TYPE_BLE)
{
@@ -188,8 +189,10 @@ BOOLEAN gatt_disconnect (BD_ADDR rem_bda)
if (p_tcb->att_lcid == L2CAP_ATT_CID)
{
if (ch_state == GATT_CH_OPEN)
+ {
/* only LCB exist between remote device and local */
ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, rem_bda);
+ }
else
{
gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
@@ -315,13 +318,22 @@ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr)
{
BOOLEAN ret = FALSE;
tGATT_TCB *p_tcb;
+ UINT8 st;
GATT_TRACE_DEBUG0("gatt_act_connect");
if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
{
ret = TRUE;
- if(gatt_get_ch_state(p_tcb) == GATT_CH_CLOSING )
+ st = gatt_get_ch_state(p_tcb);
+
+ /* before link down, another app try to open a GATT connection */
+ if(st == GATT_CH_OPEN && gatt_num_apps_hold_link(p_tcb) == 0 )
+ {
+ if (!gatt_connect(bd_addr, p_tcb))
+ ret = FALSE;
+ }
+ else if(st == GATT_CH_CLOSING)
{
/* need to complete the closing first */
ret = FALSE;
@@ -370,8 +382,6 @@ static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 re
BOOLEAN check_srv_chg = FALSE;
tGATTS_SRV_CHG *p_srv_chg_clt=NULL;
- BOOLEAN is_bg_conn = FALSE;
-
GATT_TRACE_DEBUG3 ("GATT ATT protocol channel with BDA: %08x%04x is %s",
(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
@@ -407,7 +417,7 @@ static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 re
gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
- gatt_send_conn_cback(FALSE, p_tcb);
+ gatt_send_conn_cback(p_tcb);
}
else /* there was an exisiting link, ignore the callback */
{
@@ -425,11 +435,8 @@ static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 re
gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
- if (L2CA_GetBleConnRole(p_tcb->peer_bda)== HCI_ROLE_MASTER)
- {
- is_bg_conn = TRUE;
- }
- gatt_send_conn_cback (is_bg_conn, p_tcb);
+
+ gatt_send_conn_cback (p_tcb);
if (check_srv_chg)
{
gatt_chk_srv_chg (p_srv_chg_clt);
@@ -630,12 +637,15 @@ void gatt_l2cif_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
}
else
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
}
/* send callback */
- gatt_send_conn_cback(FALSE, p_tcb);
+ gatt_send_conn_cback(p_tcb);
}
}
/* else failure */
@@ -692,12 +702,15 @@ void gatt_l2cif_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
}
else
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
}
/* send callback */
- gatt_send_conn_cback(FALSE, p_tcb);
+ gatt_send_conn_cback(p_tcb);
}
}
}
@@ -726,8 +739,13 @@ void gatt_l2cif_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
/* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid);
}
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
+
/* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
reason = GATT_CONN_TERMINATE_PEER_USER;
@@ -755,8 +773,12 @@ void gatt_l2cif_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
/* look up clcb for this channel */
if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
+
/* send disconnect callback */
/* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
@@ -801,15 +823,14 @@ void gatt_l2cif_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
** Returns void
**
*******************************************************************************/
-static void gatt_send_conn_cback(BOOLEAN is_bg_conn, tGATT_TCB *p_tcb)
+static void gatt_send_conn_cback(tGATT_TCB *p_tcb)
{
UINT8 i;
tGATT_REG *p_reg;
tGATT_BG_CONN_DEV *p_bg_dev=NULL;
UINT16 conn_id;
- if (is_bg_conn)
- p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
+ p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
/* notifying all applications for the connection up event */
for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++)
@@ -1015,7 +1036,7 @@ void gatt_init_srv_chg (void)
while ((i <= num_clients) && status)
{
req.client_read_index = i;
- if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)))
+ if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)) == TRUE)
{
memcpy(&srv_chg_clt, &rsp.srv_chg ,sizeof(tGATTS_SRV_CHG));
if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL)
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index ddecdb3a8..71ba6a52c 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -332,6 +332,18 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
tGATT_IF gatt_if;
UINT16 conn_id;
+#if GATT_CONFORMANCE_TESTING == TRUE
+ if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
+ {
+ GATT_TRACE_DEBUG2("conf test forced err rsp for %s error status=%d",
+ __FUNCTION__,gatt_cb.err_status);
+
+ gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, 0, FALSE);
+
+ return;
+ }
+#endif
+
STREAM_TO_UINT8(flag, p);
/* mask the flag */
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index bd3aaf62a..5470f4ef8 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -98,6 +98,23 @@ void gatt_free_pending_ind(tGATT_TCB *p_tcb)
/*******************************************************************************
**
+** Function gatt_free_pending_enc_queue
+**
+** Description Free all buffers in pending encyption queue
+**
+** Returns None
+**
+*******************************************************************************/
+void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb)
+{
+ GATT_TRACE_DEBUG0("gatt_free_pending_enc_queue");
+ /* release all queued indications */
+ while (p_tcb->pending_enc_clcb.p_first)
+ GKI_freebuf (GKI_dequeue (&p_tcb->pending_enc_clcb));
+}
+
+/*******************************************************************************
+**
** Function gatt_delete_dev_from_srv_chg_clt_list
**
** Description Delete a device from the service changed client lit
@@ -920,6 +937,8 @@ tGATT_TCB * gatt_allocate_tcb_by_bdaddr(BD_ADDR bda)
if (allocated)
{
memset(p_tcb, 0, sizeof(tGATT_TCB));
+ GKI_init_q (&p_tcb->pending_enc_clcb);
+ GKI_init_q (&p_tcb->pending_ind_q);
p_tcb->in_use = TRUE;
p_tcb->tcb_idx = i;
}
@@ -1258,7 +1277,6 @@ UINT8 gatt_sr_alloc_rcb(tGATT_HDL_LIST_ELEM *p_list )
p_sreg->type = p_list->asgn_range.is_primary ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
p_sreg->s_hdl = p_list->asgn_range.s_handle;
p_sreg->e_hdl = p_list->asgn_range.e_handle;
- //p_sreg->sr_cb = *p_cback;
p_sreg->p_db = &p_list->svc_db;
GATT_TRACE_DEBUG1 ("total GKI buffer in db [%d]",p_sreg->p_db->svc_buffer.count);
@@ -2109,6 +2127,7 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason)
btu_stop_timer (&p_tcb->ind_ack_timer_ent);
btu_stop_timer (&p_tcb->conf_timer_ent);
gatt_free_pending_ind(p_tcb);
+ gatt_free_pending_enc_queue(p_tcb);
for (i = 0; i < GATT_MAX_APPS; i ++)
{
@@ -2272,13 +2291,15 @@ tGATT_BG_CONN_DEV * gatt_alloc_bg_dev(BD_ADDR remote_bda)
**
** Description add/remove device from the back ground connection device list
**
-** Returns pointer to the device record
+** Returns TRUE if device added to the list; FALSE failed
**
*******************************************************************************/
-BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
+BOOLEAN gatt_add_bg_dev_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_initator)
{
+ tGATT_IF gatt_if = p_reg->gatt_if;
tGATT_BG_CONN_DEV *p_dev = NULL;
- UINT8 i;
+ UINT8 i;
+ BOOLEAN ret = FALSE;
if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
{
@@ -2289,26 +2310,51 @@ BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
{
for (i = 0; i < GATT_MAX_APPS; i ++)
{
- if (p_dev->gatt_if[i] == gatt_if)
+ if (is_initator)
{
- GATT_TRACE_ERROR0("device already in list");
- return FALSE;
+ if (p_dev->gatt_if[i] == gatt_if)
+ {
+ GATT_TRACE_ERROR0("device already in iniator white list");
+ break;
+ }
+ else if (p_dev->gatt_if[i] == 0)
+ {
+ p_dev->gatt_if[i] = gatt_if;
+ if (i == 0)
+ ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
+ break;
+ }
}
- else if (p_dev->gatt_if[i] == 0)
+ else
{
- GATT_TRACE_DEBUG0("add device into list");
- p_dev->gatt_if[i] = gatt_if;
- return TRUE;
+ if (p_dev->listen_gif[i] == gatt_if)
+ {
+ GATT_TRACE_ERROR0("device already in adv white list");
+ return FALSE;
+ }
+ else if (p_dev->listen_gif[i] == 0)
+ {
+ if (p_reg->listening == GATT_LISTEN_TO_ALL)
+ p_reg->listening = GATT_LISTEN_TO_NONE;
+
+ p_reg->listening ++;
+ p_dev->listen_gif[i] = gatt_if;
+
+ if (i == 0)
+ ret = BTM_BleUpdateAdvWhitelist(TRUE, bd_addr);
+ break;
+ }
}
}
}
+ else
+ {
+ GATT_TRACE_ERROR0("no device record available");
+ }
- GATT_TRACE_ERROR0("no device record available");
-
- return FALSE;
+ return ret;
}
-
/*******************************************************************************
**
** Function gatt_remove_bg_dev_for_app
@@ -2325,7 +2371,7 @@ BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr)
if (p_tcb)
gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
- status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr);
+ status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr, TRUE);
return status;
}
@@ -2393,13 +2439,15 @@ BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if)
**
** Function gatt_remove_bg_dev_from_list
**
-** Description add/remove device from the back ground connection device list
+** Description add/remove device from the back ground connection device list or
+** listening to advertising list.
**
** Returns pointer to the device record
**
*******************************************************************************/
-BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
+BOOLEAN gatt_remove_bg_dev_from_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_initiator)
{
+ tGATT_IF gatt_if = p_reg->gatt_if;
tGATT_BG_CONN_DEV *p_dev = NULL;
UINT8 i, j;
BOOLEAN ret = FALSE;
@@ -2409,27 +2457,49 @@ BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
return ret;
}
- for (i = 0; i < GATT_MAX_APPS && p_dev->gatt_if[i] > 0; i ++)
+ for (i = 0; i < GATT_MAX_APPS && (p_dev->gatt_if[i] > 0 || p_dev->listen_gif[i]); i ++)
{
- if (p_dev->gatt_if[i] == gatt_if)
+ if (is_initiator)
{
- p_dev->gatt_if[i] = 0;
+ if (p_dev->gatt_if[i] == gatt_if)
+ {
+ p_dev->gatt_if[i] = 0;
+ /* move all element behind one forward */
+ for (j = i + 1; j < GATT_MAX_APPS; j ++)
+ p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
- for (j = i + 1; j < GATT_MAX_APPS; j ++)
- p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
+ if (p_dev->gatt_if[0] == 0)
+ ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
+ else
+ ret = TRUE;
- if (p_dev->gatt_if[0] == 0)
+ break;
+ }
+ }
+ else
+ {
+ if (p_dev->listen_gif[i] == gatt_if)
{
- ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
- memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
+ p_dev->listen_gif[i] = 0;
+ p_reg->listening --;
+ /* move all element behind one forward */
+ for (j = i + 1; j < GATT_MAX_APPS; j ++)
+ p_dev->listen_gif[j - 1] = p_dev->listen_gif[j];
+
+ if (p_dev->listen_gif[0] == 0)
+ ret = BTM_BleUpdateAdvWhitelist(FALSE, p_dev->remote_bda);
+ else
+ ret = TRUE;
+ break;
}
- else
- ret = TRUE;
-
- break;
}
}
+ if (i != GATT_MAX_APPS && p_dev->gatt_if[0] == 0 && p_dev->listen_gif[0] == 0)
+ {
+ memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
+ }
+
return ret;
}
/*******************************************************************************
@@ -2500,9 +2570,9 @@ void gatt_reset_bgdev_list(void)
** Returns TRUE if connection started; FALSE if connection start failure.
**
*******************************************************************************/
-BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr)
+BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initator)
{
- BOOLEAN ret = FALSE, exist_dev = FALSE;
+ BOOLEAN ret = FALSE;
tGATT_REG *p_reg;
tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr);
@@ -2516,27 +2586,17 @@ BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_
if (add)
{
- /* new device */
- if (gatt_find_bg_dev(bd_addr))
- exist_dev = TRUE;
+ ret = gatt_add_bg_dev_list(p_reg, bd_addr, is_initator);
- if (gatt_add_bg_dev_list(gatt_if, bd_addr))
+ if (ret && p_tcb != NULL)
{
- if (!exist_dev)
- {
- ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
- }
- else
- ret = TRUE;
-
/* if a connected device, update the link holding number */
- if (p_tcb != NULL)
- gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
+ gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
}
}
else
{
- ret = gatt_remove_bg_dev_from_list(gatt_if, bd_addr);
+ ret = gatt_remove_bg_dev_from_list(p_reg, bd_addr, is_initator);
}
return ret;
}
@@ -2591,10 +2651,70 @@ UINT16 gatt_get_conn_id (tGATT_IF gatt_if, BD_ADDR bd_addr)
GATT_TRACE_ERROR1 ("gatt_get_conn_id: not connected- gatt_if: %u", gatt_if);
return(GATT_INVALID_CONN_ID);
}
+/*******************************************************************************
+**
+** Function gatt_add_pending_new_srv_start
+**
+** Description Add a pending new srv start to the new service start queue
+**
+** Returns Pointer to the new service start buffer, NULL no buffer available
+**
+*******************************************************************************/
+tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb )
+{
+ tGATT_PENDING_ENC_CLCB *p_buf;
+ GATT_TRACE_DEBUG0 ("gatt_add_pending_new_srv_start");
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_getbuf((UINT16)sizeof(tGATT_PENDING_ENC_CLCB))) != NULL)
+ {
+ GATT_TRACE_DEBUG0 ("enqueue a new pending encryption channel clcb");
+ p_buf->p_clcb = p_clcb;
+ GKI_enqueue (&p_tcb->pending_enc_clcb, p_buf);
+ }
+ return p_buf;
+}
+/*******************************************************************************
+**
+** Function gatt_update_listen_mode
+**
+** Description update peripheral role listening mode
+**
+** Returns Pointer to the new service start buffer, NULL no buffer available
+**
+*******************************************************************************/
+void gatt_update_listen_mode(void)
+{
+ UINT8 ii = 0;
+ tGATT_REG *p_reg = &gatt_cb.cl_rcb[0];
+ UINT8 listening = 0;
+ UINT16 connectability, window, interval;
+ for (; ii < GATT_MAX_APPS; ii ++, p_reg ++)
+ {
+ if ( p_reg->in_use && p_reg->listening > listening)
+ {
+ listening = p_reg->listening;
+ }
+ }
+
+ if (listening == GATT_LISTEN_TO_ALL ||
+ listening == GATT_LISTEN_TO_NONE)
+ BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_ALL);
+ else
+ BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_WL);
+ connectability = BTM_ReadConnectability (&window, &interval);
+ if (listening != GATT_LISTEN_TO_NONE)
+ {
+ connectability |= BTM_BLE_CONNECTABLE;
+ }
+ else
+ connectability &= ~BTM_BLE_CONNECTABLE;
+ /* turning on the adv now */
+ BTM_SetConnectability(connectability, window, interval);
+
+}
#endif
diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c
index 417297b71..a4e55da7e 100644
--- a/stack/hcic/hciblecmds.c
+++ b/stack/hcic/hciblecmds.c
@@ -748,4 +748,112 @@ BOOLEAN btsnd_hcic_ble_read_supported_states (void)
return (TRUE);
}
+BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_PARAM1)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_RECEIVER_TEST);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_WRITE_PARAM1);
+
+ UINT8_TO_STREAM (pp, rx_freq);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len, UINT8 payload)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_PARAM3)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM3;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_TRANSMITTER_TEST);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_WRITE_PARAM3);
+
+ UINT8_TO_STREAM (pp, tx_freq);
+ UINT8_TO_STREAM (pp, test_data_len);
+ UINT8_TO_STREAM (pp, payload);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_test_end(void)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_READ_CMD)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_TEST_END);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_host_supported (void)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_READ_CMD)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_READ_LE_HOST_SUPPORTED);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_write_host_supported (UINT8 le_host_spt, UINT8 simul_le_host_spt)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_WRITE_LE_HOST_SUPPORTED);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED);
+ UINT8_TO_STREAM (pp, le_host_spt);
+ UINT8_TO_STREAM (pp, simul_le_host_spt);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
#endif
diff --git a/stack/hcic/hcicmds.c b/stack/hcic/hcicmds.c
index 71a5dc551..21222bd6b 100644
--- a/stack/hcic/hcicmds.c
+++ b/stack/hcic/hcicmds.c
@@ -1371,6 +1371,9 @@ BOOLEAN btsnd_hcic_change_name (BD_NAME name)
UINT16_TO_STREAM (pp, HCI_CHANGE_LOCAL_NAME);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_CHANGE_NAME);
+ if (len > HCIC_PARAM_SIZE_CHANGE_NAME)
+ len = HCIC_PARAM_SIZE_CHANGE_NAME;
+
ARRAY_TO_STREAM (pp, name, len);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
diff --git a/stack/hid/hidh_api.c b/stack/hid/hidh_api.c
index 36ee5ea98..4f048fcb8 100644
--- a/stack/hid/hidh_api.c
+++ b/stack/hid/hidh_api.c
@@ -88,7 +88,7 @@ void hidh_get_str_attr( tSDP_DISC_REC *p_rec, UINT16 attr_id, UINT16 max_len, ch
else
{
memcpy( str, (char *) p_attr->attr_value.v.array, max_len-1 );
- str[max_len] = '\0';
+ str[max_len-1] = '\0';
}
}
else
@@ -220,7 +220,7 @@ static void hidh_search_callback (UINT16 sdp_result)
p_nvi->ssr_min_tout = p_attr->attr_value.v.u16;
}
else
- p_nvi->ssr_max_latency = HID_SSR_PARAM_INVALID;
+ p_nvi->ssr_min_tout = HID_SSR_PARAM_INVALID;
hh_cb.sdp_rec.p_sdp_layer_rec = p_rec;
hh_cb.sdp_cback(SDP_SUCCESS, attr_mask, &hh_cb.sdp_rec);
@@ -454,7 +454,7 @@ tHID_STATUS HID_HostWriteDev( UINT8 dev_handle, UINT8 t_type,
status = HID_ERR_INVALID_PARAM;
}
- if( hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED )
+ else if( hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED )
{
HIDH_TRACE_ERROR1("HID_ERR_NO_CONNECTION dev_handle %d", dev_handle);
status = HID_ERR_NO_CONNECTION;
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 9ed3a0ee1..2fe1f3da1 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -322,7 +322,7 @@ void hidh_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
#endif
UINT32 reason;
- dhandle = p_dev - &(hh_cb.devices[0]) ;
+ dhandle = ((UINT32)p_dev - (UINT32)&(hh_cb.devices[0]))/ sizeof(tHID_HOST_DEV_CTB);
if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
{
HIDH_TRACE_EVENT0 ("HID - Originator security pass.");
@@ -975,7 +975,6 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq (HID_PSM_CONTROL, p_dev->addr)) == 0)
{
HIDH_TRACE_WARNING0 ("HID - Originate failed");
- dhandle = (p_dev - &(hh_cb.devices[0]))/(sizeof( tHID_HOST_DEV_CTB )) ;
hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL ) ;
}
else
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index 0a9b7f8c7..beaecf61e 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -407,6 +407,13 @@ typedef struct {
UINT16 nsc_mask; /* Nonsupported protocol command messages */
} tAVDT_CS;
+/* AVDT data option mask is used in the write request */
+#define AVDT_DATA_OPT_NONE 0x00 /* No option still add RTP header */
+#define AVDT_DATA_OPT_NO_RTP (0x01 << 0) /* Skip adding RTP header */
+
+typedef UINT8 tAVDT_DATA_OPT_MASK;
+
+
/*****************************************************************************
** External Function Declarations
@@ -758,6 +765,44 @@ AVDT_API extern UINT16 AVDT_SecurityRsp(UINT8 handle, UINT8 label, UINT8 error_c
*******************************************************************************/
AVDT_API extern UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp,
UINT8 m_pt);
+/*******************************************************************************
+**
+** Function AVDT_WriteReqOpt
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteReq(). If the applications calls
+** AVDT_WriteReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+** or AVDT_START_IND_EVT.
+**
+** The application passes the packet using the BT_HDR structure
+** This structure is described in section 2.1. The offset
+** field must be equal to or greater than AVDT_MEDIA_OFFSET
+** (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used)
+** This allows enough space in the buffer for the L2CAP and
+** AVDTP headers.
+**
+** The memory pointed to by p_pkt must be a GKI buffer
+** allocated by the application. This buffer will be freed
+** by the protocol stack; the application must not free
+** this buffer.
+**
+** The opt parameter allows passing specific options like:
+** - NO_RTP : do not add the RTP header to buffer
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+AVDT_API extern UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp,
+ UINT8 m_pt, tAVDT_DATA_OPT_MASK opt);
/*******************************************************************************
**
diff --git a/stack/include/avrc_api.h b/stack/include/avrc_api.h
index 1f4bb7f52..cc6db7f3e 100644
--- a/stack/include/avrc_api.h
+++ b/stack/include/avrc_api.h
@@ -563,7 +563,8 @@ AVRC_API extern void AVRC_Init(void);
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
-AVRC_API extern tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len);
+AVRC_API extern tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result,
+ UINT8 *p_buf, UINT16 buf_len);
/*******************************************************************************
**
@@ -575,7 +576,8 @@ AVRC_API extern tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_r
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
-AVRC_API extern tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result, UINT8 *p_buf, UINT16 buf_len);
+AVRC_API extern tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result,
+ UINT8 *p_buf, UINT16 buf_len);
/*******************************************************************************
**
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index 580996848..020a2810d 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -97,33 +97,34 @@
#define BT_EVT_TO_OBX_SR_L2C_MSG 0x3500
/* ftp events */
-#define BT_EVT_TO_FTP_SRVR_CMDS 0x3800
-#define BT_EVT_TO_FTP_CLNT_CMDS 0x3900
+#define BT_EVT_TO_FTP_SRVR_CMDS 0x3600
+#define BT_EVT_TO_FTP_CLNT_CMDS 0x3700
-#define BT_EVT_TO_BTU_SAP 0x3a00 /* SIM Access Profile events */
+#define BT_EVT_TO_BTU_SAP 0x3800 /* SIM Access Profile events */
/* opp events */
-#define BT_EVT_TO_OPP_SRVR_CMDS 0x3b00
-#define BT_EVT_TO_OPP_CLNT_CMDS 0x3c00
+#define BT_EVT_TO_OPP_SRVR_CMDS 0x3900
+#define BT_EVT_TO_OPP_CLNT_CMDS 0x3a00
/* gap events */
-#define BT_EVT_TO_GAP_MSG 0x3d00
+#define BT_EVT_TO_GAP_MSG 0x3b00
/* start timer */
-#define BT_EVT_TO_START_TIMER 0x3e00
+#define BT_EVT_TO_START_TIMER 0x3c00
+
+/* stop timer */
+#define BT_EVT_TO_STOP_TIMER 0x3d00
/* start quick timer */
-#define BT_EVT_TO_START_QUICK_TIMER 0x3f00
+#define BT_EVT_TO_START_QUICK_TIMER 0x3e00
/* for NFC */
/************************************/
#define BT_EVT_TO_NFC_NCI 0x4000 /* NCI Command, Notification or Data*/
#define BT_EVT_TO_NFC_INIT 0x4100 /* Initialization message */
-#define BT_EVT_TO_LLCP_ECHO 0x4200 /* LLCP Echo Service */
-#define BT_EVT_TO_LLCP_SOCKET 0x4300 /* LLCP over TCP/IP */
-#define BT_EVT_TO_NCI_LP 0x4400 /* Low power */
-#define BT_EVT_TO_NFC_ERR 0x4500 /* Error notification to NFC Task */
+#define BT_EVT_TO_NCI_LP 0x4200 /* Low power */
+#define BT_EVT_TO_NFC_ERR 0x4300 /* Error notification to NFC Task */
#define BT_EVT_TO_NFCCSIM_NCI 0x4a00 /* events to NFCC simulation (NCI packets) */
@@ -330,7 +331,7 @@ typedef UINT8 EXT_INQ_RESP[EXT_INQ_RESP_LEN];/* Extended Inquiry Response */
typedef UINT8 *EXT_INQ_RESP_PTR; /* Pointer to Extended Inquiry Response */
#define BD_NAME_LEN 248
-typedef UINT8 BD_NAME[BD_NAME_LEN]; /* Device name */
+typedef UINT8 BD_NAME[BD_NAME_LEN + 1]; /* Device name */
typedef UINT8 *BD_NAME_PTR; /* Pointer to Device name */
#define BD_FEATURES_LEN 8
@@ -580,13 +581,13 @@ typedef UINT8 tBT_DEVICE_TYPE;
#define TRACE_LAYER_SMP 0x00260000
#define TRACE_LAYER_NFC 0x00270000
#define TRACE_LAYER_NCI 0x00280000
-#define TRACE_LAYER_IDEP 0x00290000
-#define TRACE_LAYER_NDEP 0x002a0000
-#define TRACE_LAYER_LLCP 0x002b0000
-#define TRACE_LAYER_RW 0x002c0000
-#define TRACE_LAYER_CE 0x002d0000
+#define TRACE_LAYER_LLCP 0x00290000
+#define TRACE_LAYER_NDEF 0x002a0000
+#define TRACE_LAYER_RW 0x002b0000
+#define TRACE_LAYER_CE 0x002c0000
+#define TRACE_LAYER_P2P 0x002d0000
#define TRACE_LAYER_SNEP 0x002e0000
-#define TRACE_LAYER_NDEF 0x002f0000
+#define TRACE_LAYER_CHO 0x002f0000
#define TRACE_LAYER_NFA 0x00300000
#define TRACE_LAYER_MAX_NUM 0x0031
@@ -667,11 +668,13 @@ typedef UINT8 tBT_DEVICE_TYPE;
#define SCR_PROTO_TRACE_ATT 0x00001000
#define SCR_PROTO_TRACE_SMP 0x00002000
#define SCR_PROTO_TRACE_NCI 0x00004000
-#define SCR_PROTO_TRACE_DEP 0x00008000
-#define SCR_PROTO_TRACE_LLCP 0x00010000
-#define SCR_PROTO_TRACE_NDEF 0x00020000
-#define SCR_PROTO_TRACE_TAGS 0x00040000
-#define SCR_PROTO_TRACE_ALL 0x0007ffff
+#define SCR_PROTO_TRACE_LLCP 0x00008000
+#define SCR_PROTO_TRACE_NDEF 0x00010000
+#define SCR_PROTO_TRACE_RW 0x00020000
+#define SCR_PROTO_TRACE_CE 0x00040000
+#define SCR_PROTO_TRACE_SNEP 0x00080000
+#define SCR_PROTO_TRACE_CHO 0x00100000
+#define SCR_PROTO_TRACE_ALL 0x001fffff
#define SCR_PROTO_TRACE_HCI_LOGGING_VSE 0x0800 /* Brcm vs event for logmsg and protocol traces */
#define MAX_SCRIPT_TYPE 5
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 09bb749cd..a639fa686 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -172,9 +172,11 @@ typedef UINT8 (tBTM_FILTER_CB) (BD_ADDR bd_addr, DEV_CLASS dc);
/* Inquiry modes
* Note: These modes are associated with the inquiry active values (BTM_*ACTIVE) */
-#define BTM_GENERAL_INQUIRY 0
-#define BTM_LIMITED_INQUIRY 1
-#define BTM_BR_INQUIRY_MASK 0x0f
+#define BTM_INQUIRY_NONE 0
+#define BTM_GENERAL_INQUIRY 0x01
+#define BTM_LIMITED_INQUIRY 0x02
+#define BTM_BR_INQUIRY_MASK (BTM_GENERAL_INQUIRY | BTM_LIMITED_INQUIRY)
+
/* high byte of inquiry mode for BLE inquiry mode */
#define BTM_BLE_INQUIRY_NONE 0x00
#define BTM_BLE_GENERAL_INQUIRY 0x10
@@ -188,6 +190,16 @@ typedef UINT8 (tBTM_FILTER_CB) (BD_ADDR bd_addr, DEV_CLASS dc);
#define BTM_LIMITED_INQUIRY_ACTIVE 0x2 /* a limited inquiry is in progress */
#define BTM_PERIODIC_INQUIRY_ACTIVE 0x8 /* a periodic inquiry is active */
#define BTM_SSP_INQUIRY_ACTIVE 0x4 /* SSP is active, so inquiry is disallowed (work around for FW bug) */
+#define BTM_LE_GENERAL_INQUIRY_ACTIVE 0x10 /* a general inquiry is in progress */
+#define BTM_LE_LIMITED_INQUIRY_ACTIVE 0x20 /* a limited inquiry is in progress */
+#define BTM_LE_SELECT_CONN_ACTIVE 0x40 /* selection connection is in progress */
+#define BTM_LE_OBSERVE_ACTIVE 0x80 /* selection connection is in progress */
+
+/* inquiry activity mask */
+#define BTM_BR_INQ_ACTIVE_MASK (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE|BTM_PERIODIC_INQUIRY_ACTIVE) /* BR/EDR inquiry activity mask */
+#define BTM_LE_SCAN_ACTIVE_MASK 0xF0 /* LE scan activity mask */
+#define BTM_LE_INQ_ACTIVE_MASK (BTM_LE_GENERAL_INQUIRY_ACTIVE|BTM_LE_LIMITED_INQUIRY_ACTIVE) /* LE inquiry activity mask*/
+#define BTM_INQUIRY_ACTIVE_MASK (BTM_BR_INQ_ACTIVE_MASK | BTM_LE_INQ_ACTIVE_MASK) /* inquiry activity mask */
/* Define scan types */
#define BTM_SCAN_TYPE_STANDARD 0
@@ -825,8 +837,9 @@ typedef struct
typedef struct
{
tBTM_BL_EVENT event; /* The event reported. */
- UINT8 busy_level;/* when paging or inquiring, level is as above.
+ UINT8 busy_level;/* when paging or inquiring, level is 10.
* Otherwise, the number of ACL links. */
+ UINT8 busy_level_flags; /* Notifies actual inquiry/page activities */
} tBTM_BL_UPDATE_DATA;
/* the data type associated with BTM_BL_ROLE_CHG_EVT */
@@ -877,6 +890,9 @@ typedef void (tBTM_ACL_DB_CHANGE_CB) (BD_ADDR p_bda, DEV_CLASS p_dc,
/* Define an invalid SCO disconnect reason */
#define BTM_INVALID_SCO_DISC_REASON 0xFFFF
+/* Define first active SCO index */
+#define BTM_FIRST_ACTIVE_SCO_INDEX BTM_MAX_SCO_LINKS
+
/* Define SCO packet types used in APIs */
#define BTM_SCO_PKT_TYPES_MASK_HV1 HCI_ESCO_PKT_TYPES_MASK_HV1
#define BTM_SCO_PKT_TYPES_MASK_HV2 HCI_ESCO_PKT_TYPES_MASK_HV2
@@ -929,6 +945,17 @@ typedef UINT8 tBTM_SCO_ROUTE_TYPE;
#define BTM_SCO_CODEC_MSBC 0x0002
typedef UINT16 tBTM_SCO_CODEC_TYPE;
+
+
+/*******************
+** SCO Air Mode Types
+********************/
+#define BTM_SCO_AIR_MODE_U_LAW 0
+#define BTM_SCO_AIR_MODE_A_LAW 1
+#define BTM_SCO_AIR_MODE_CVSD 2
+#define BTM_SCO_AIR_MODE_TRANSPNT 3
+typedef UINT8 tBTM_SCO_AIR_MODE_TYPE;
+
/*******************
** SCO Voice Settings
********************/
@@ -1198,11 +1225,11 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
(UINT32)(((UINT32)1 << (((UINT32)(service)) % BTM_SEC_ARRAY_BITS)))) ? TRUE : FALSE)
/* MACRO to copy two trusted device bitmask */
-#define BTM_SEC_COPY_TRUSTED_DEVICE(p_src, p_dst) {int trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
+#define BTM_SEC_COPY_TRUSTED_DEVICE(p_src, p_dst) {UINT32 trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
((UINT32 *)(p_dst))[trst] = ((UINT32 *)(p_src))[trst];}
/* MACRO to clear two trusted device bitmask */
-#define BTM_SEC_CLR_TRUSTED_DEVICE(p_dst) {int trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
+#define BTM_SEC_CLR_TRUSTED_DEVICE(p_dst) {UINT32 trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
((UINT32 *)(p_dst))[trst] = 0;}
/* Following bits can be provided by host in the trusted_mask array */
@@ -1556,8 +1583,8 @@ typedef UINT8 tBTM_LE_AUTH_REQ;
/* LE security level */
#define BTM_LE_SEC_NONE SMP_SEC_NONE
-#define BTM_LE_SEC_UNAUTHENTICATE SMP_SEC_UNAUTHENTICATE
-#define BTM_LE_SEC_AUTHENTICATED SMP_SEC_AUTHENTICATED
+#define BTM_LE_SEC_UNAUTHENTICATE SMP_SEC_UNAUTHENTICATE /* 1 */
+#define BTM_LE_SEC_AUTHENTICATED SMP_SEC_AUTHENTICATED /* 4 */
typedef UINT8 tBTM_LE_SEC;
@@ -1577,6 +1604,8 @@ typedef struct
{
UINT8 reason;
UINT8 sec_level;
+ BOOLEAN privacy_supported;
+ BOOLEAN is_pair_cancel;
}tBTM_LE_COMPLT;
#endif
@@ -1615,12 +1644,18 @@ typedef struct
}tBTM_LE_LCSRK_KEYS;
+typedef struct
+{
+ BT_OCTET16 irk;
+ tBLE_ADDR_TYPE addr_type;
+ BD_ADDR static_addr;
+}tBTM_LE_PID_KEYS;
typedef union
{
tBTM_LE_PENC_KEYS penc_key; /* received peer encryption key */
- tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
- BT_OCTET16 pid_key; /* peer device ID key */
+ tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
+ tBTM_LE_PID_KEYS pid_key; /* peer device ID key */
tBTM_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
tBTM_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
}tBTM_LE_KEY_VALUE;
@@ -2907,6 +2942,17 @@ BTM_API extern BOOLEAN BTM_TryAllocateSCN(UINT8 scn);
*******************************************************************************/
BTM_API extern tBTM_STATUS BTM_SetLinkSuperTout (BD_ADDR remote_bda,
UINT16 timeout);
+/*******************************************************************************
+**
+** Function BTM_GetLinkSuperTout
+**
+** Description Read the link supervision timeout value of the connection
+**
+** Returns status of the operation
+**
+*******************************************************************************/
+ BTM_API extern tBTM_STATUS BTM_GetLinkSuperTout (BD_ADDR remote_bda,
+ UINT16 *p_timeout);
/*******************************************************************************
**
@@ -3415,6 +3461,11 @@ BTM_API extern tBTM_STATUS BTM_SetWBSCodec (tBTM_SCO_CODEC_TYPE codec_type);
** is active, but is typically called after receiving the SCO
** opened callback.
**
+** Note: If called over a 1.1 controller, only the packet types
+** field has meaning.
+** Note: If the upper layer doesn't know the current sco index,
+** BTM_FIRST_ACTIVE_SCO_INDEX can be used as the first parameter to
+** find the first active SCO index
**
** Returns BTM_SUCCESS if returned data is valid connection.
** BTM_ILLEGAL_VALUE if no connection for specified sco_inx.
@@ -4450,27 +4501,6 @@ BTM_API extern tBTM_STATUS BTM_SetWBSCodec (tBTM_SCO_CODEC_TYPE codec_type);
*******************************************************************************/
BTM_API extern void BTM_N2BtDisconnect(void);
-
-/*******************************************************************************
-**
-** Function BTM_ConfigI2SPCM
-**
-** Description This function sends VSC Write_I2SPCM_Interface_Param
-** as to the specified codec_type.
-**
-**
-** Parameter codec_type: codec_type to be used for sco connection.
-** role: master or slave role
-** sample_rate: sampling rate
-** clock_rate:clock rate 128K to 2048K
-**
-**
-** Returns BTM_SUCCESS if the successful.
-** BTM_ILLEGAL_VALUE: wrong codec type
-**
-*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_ConfigI2SPCM (tBTM_SCO_CODEC_TYPE codec_type, UINT8 role, UINT8 sample_rate, UINT8 clock_rate);
-
/*****************************************************************************
** SCO OVER HCI
*****************************************************************************/
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 8456b9f6c..b86968d71 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -30,6 +30,16 @@
#define CHNL_MAP_LEN 5
typedef UINT8 tBTM_BLE_CHNL_MAP[CHNL_MAP_LEN];
+#define BTM_BLE_CONNECT_EVT 0x00
+#define BTM_BLE_CONNECT_DIR_EVT 0x01
+#define BTM_BLE_DISCOVER_EVT 0x02
+#define BTM_BLE_NON_CONNECT_EVT 0x03
+#define BTM_BLE_SCAN_RSP_EVT 0x04
+#define BTM_BLE_SCAN_REQ_EVT 0x06
+#define BTM_BLE_UNKNOWN_EVT 0xff
+
+#define BTM_BLE_UNKNOWN_EVT 0xff
+
#define BTM_BLE_SCAN_MODE_PASS 0
#define BTM_BLE_SCAN_MODE_ACTI 1
#define BTM_BLE_SCAN_MODE_NONE 0xff
@@ -72,7 +82,7 @@ typedef UINT8 tBTM_BLE_SFP;
#define BTM_BLE_ADV_INT_MIN 0x0020
#define BTM_BLE_ADV_INT_MAX 0x4000
-/* connection parameter boundary value */
+/* connection parameter boundary values */
#define BTM_BLE_SCAN_INT_MIN 0x0004
#define BTM_BLE_SCAN_INT_MAX 0x4000
#define BTM_BLE_SCAN_WIN_MIN 0x0004
@@ -83,32 +93,41 @@ typedef UINT8 tBTM_BLE_SFP;
#define BTM_BLE_CONN_SUP_TOUT_MIN 0x000A
#define BTM_BLE_CONN_SUP_TOUT_MAX 0x0C80
#define BTM_BLE_CONN_PARAM_UNDEF 0xffff /* use this value when a specific value not to be overwritten */
+#define BTM_BLE_CONN_SUP_TOUT_DEF 700
/* default connection parameters if not configured, use GAP recommend value for auto/selective connection */
/* default scan interval */
-#ifndef BTM_BLE_CONN_EST_SCAN_INT
-#define BTM_BLE_CONN_EST_SCAN_INT 96 /* 312.5 ms = 500 *0.625 */
+#ifndef BTM_BLE_SCAN_FAST_INT
+#define BTM_BLE_SCAN_FAST_INT 96 /* 30 ~ 60 ms (use 60) = 96 *0.625 */
#endif
/* default scan window for background connection, applicable for auto connection or selective conenction */
-#ifndef BTM_BLE_CONN_EST_SCAN_WIND
-#define BTM_BLE_CONN_EST_SCAN_WIND 48 /* 187.5 ms = 400 *0.625 */
+#ifndef BTM_BLE_SCAN_FAST_WIN
+#define BTM_BLE_SCAN_FAST_WIN 48 /* 30 ms = 48 *0.625 */
+#endif
+
+/* default scan paramter used in reduced power cycle (background scanning) */
+#ifndef BTM_BLE_SCAN_SLOW_INT_1
+#define BTM_BLE_SCAN_SLOW_INT_1 2048 /* 1.28 s = 2048 *0.625 */
+#endif
+#ifndef BTM_BLE_SCAN_SLOW_WIN_1
+#define BTM_BLE_SCAN_SLOW_WIN_1 18 /* 11.25 ms = 18 *0.625 */
#endif
-/* default scan paramter used in reduced power cycle */
-#ifndef BTM_BLE_CONN_EST_SCAN_INT_LO
-#define BTM_BLE_CONN_EST_SCAN_INT_LO 2048 /* 1.28 s = 500 *0.625 */
+/* default scan paramter used in reduced power cycle (background scanning) */
+#ifndef BTM_BLE_SCAN_SLOW_INT_2
+#define BTM_BLE_SCAN_SLOW_INT_2 4096 /* 2.56 s = 4096 *0.625 */
#endif
-#ifndef BTM_BLE_CONN_EST_SCAN_WIND_LO
-#define BTM_BLE_CONN_EST_SCAN_WIND_LO 18 /* 11.25 ms = 400 *0.625 */
+#ifndef BTM_BLE_SCAN_SLOW_WIN_2
+#define BTM_BLE_SCAN_SLOW_WIN_2 36 /* 22.5 ms = 36 *0.625 */
#endif
/* default connection interval min */
#ifndef BTM_BLE_CONN_INT_MIN_DEF
-#define BTM_BLE_CONN_INT_MIN_DEF 40 /* 50ms = 400 * 1.25 */
+#define BTM_BLE_CONN_INT_MIN_DEF 24 /* recommended min: 30ms = 24 * 1.25 */
#endif
/* default connectino interval max */
#ifndef BTM_BLE_CONN_INT_MAX_DEF
-#define BTM_BLE_CONN_INT_MAX_DEF 56 /* 70ms = 56 * 1.25 */
+#define BTM_BLE_CONN_INT_MAX_DEF 40 /* recommended max: 50 ms = 56 * 1.25 */
#endif
/* default slave latency */
#ifndef BTM_BLE_CONN_SLAVE_LATENCY_DEF
@@ -119,10 +138,25 @@ typedef UINT8 tBTM_BLE_SFP;
#define BTM_BLE_CONN_TIMEOUT_DEF 2000
#endif
+#define BTM_BLE_DIR_CONN_FALLBACK_UNDIR 1
+#define BTM_BLE_DIR_CONN_FALLBACK_NO_ADV 2
+
+#ifndef BTM_BLE_DIR_CONN_FALLBACK
+#define BTM_BLE_DIR_CONN_FALLBACK BTM_BLE_DIR_CONN_FALLBACK_UNDIR
+#endif
+
#define BTM_CMAC_TLEN_SIZE 8 /* 64 bits */
#define BTM_BLE_AUTH_SIGN_LEN 12 /* BLE data signature length 8 Bytes + 4 bytes counter*/
typedef UINT8 BLE_SIGNATURE[BTM_BLE_AUTH_SIGN_LEN]; /* Device address */
+#ifndef BTM_BLE_HOST_SUPPORT
+#define BTM_BLE_HOST_SUPPORT 0x01
+#endif
+
+#ifndef BTM_BLE_SIMULTANEOUS_HOST
+#define BTM_BLE_SIMULTANEOUS_HOST 0x01
+#endif
+
/* Structure returned with Rand/Encrypt complete callback */
typedef struct
{
@@ -165,27 +199,41 @@ typedef struct
#define BTM_BLE_AD_BIT_FLAGS (0x0001 << 1)
#define BTM_BLE_AD_BIT_MANU (0x0001 << 2)
#define BTM_BLE_AD_BIT_TX_PWR (0x0001 << 3)
-#define BTM_BLE_AD_BIT_ATTR (0x0001 << 4)
#define BTM_BLE_AD_BIT_INT_RANGE (0x0001 << 5)
#define BTM_BLE_AD_BIT_SERVICE (0x0001 << 6)
#define BTM_BLE_AD_BIT_SERVICE_SOL (0x0001 << 7)
#define BTM_BLE_AD_BIT_SERVICE_DATA (0x0001 << 8)
#define BTM_BLE_AD_BIT_SIGN_DATA (0x0001 << 9)
+#define BTM_BLE_AD_BIT_SERVICE_128SOL (0x0001 << 10)
+#define BTM_BLE_AD_BIT_APPEARANCE (0x0001 << 11)
+#define BTM_BLE_AD_BIT_PUBLIC_ADDR (0x0001 << 12)
+#define BTM_BLE_AD_BIT_RANDOM_ADDR (0x0001 << 13)
+
#define BTM_BLE_AD_BIT_PROPRIETARY (0x0001 << 15)
typedef UINT16 tBTM_BLE_AD_MASK;
-#define BTM_BLE_AD_TYPE_FLAG 0x01
-#define BTM_BLE_AD_TYPE_SRV_PART 0x02
-#define BTM_BLE_AD_TYPE_SRV_CMPL 0x03
-#define BTM_BLE_AD_TYPE_NAME_SHORT 0x08
-#define BTM_BLE_AD_TYPE_NAME_CMPL 0x09
-#define BTM_BLE_AD_TYPE_TX_PWR 0x0A
+#define BTM_BLE_AD_TYPE_FLAG HCI_EIR_FLAGS_TYPE /* 0x01 */
+#define BTM_BLE_AD_TYPE_16SRV_PART HCI_EIR_MORE_16BITS_UUID_TYPE /* 0x02 */
+#define BTM_BLE_AD_TYPE_16SRV_CMPL HCI_EIR_COMPLETE_16BITS_UUID_TYPE /* 0x03 */
+#define BTM_BLE_AD_TYPE_32SRV_PART HCI_EIR_MORE_32BITS_UUID_TYPE /* 0x04 */
+#define BTM_BLE_AD_TYPE_32SRV_CMPL HCI_EIR_COMPLETE_32BITS_UUID_TYPE /* 0x05 */
+#define BTM_BLE_AD_TYPE_128SRV_PART HCI_EIR_MORE_128BITS_UUID_TYPE /* 0x06 */
+#define BTM_BLE_AD_TYPE_128SRV_CMPL HCI_EIR_COMPLETE_128BITS_UUID_TYPE /* 0x07 */
+#define BTM_BLE_AD_TYPE_NAME_SHORT HCI_EIR_SHORTENED_LOCAL_NAME_TYPE /* 0x08 */
+#define BTM_BLE_AD_TYPE_NAME_CMPL HCI_EIR_COMPLETE_LOCAL_NAME_TYPE /* 0x09 */
+#define BTM_BLE_AD_TYPE_TX_PWR HCI_EIR_TX_POWER_LEVEL_TYPE /* 0x0A */
#define BTM_BLE_AD_TYPE_DEV_CLASS 0x0D
-#define BTM_BLE_AD_TYPE_ATTR 0x10
-#define BTM_BLE_AD_TYPE_MANU 0xff
+#define BTM_BLE_AD_TYPE_SM_TK 0x10
+#define BTM_BLE_AD_TYPE_SM_OOB_FLAG 0x11
#define BTM_BLE_AD_TYPE_INT_RANGE 0x12
#define BTM_BLE_AD_TYPE_SOL_SRV_UUID 0x14
+#define BTM_BLE_AD_TYPE_128SOL_SRV_UUID 0x15
+#define BTM_BLE_AD_TYPE_SERVICE_DATA 0x16
+#define BTM_BLE_AD_TYPE_PUBLIC_TARGET 0x17
+#define BTM_BLE_AD_TYPE_RANDOM_TARGET 0x18
+#define BTM_BLE_AD_TYPE_APPEARANCE 0x19
+#define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */
typedef UINT8 tBTM_BLE_AD_TYPE;
/* slave preferred connection interval range */
@@ -204,24 +252,6 @@ typedef struct
UINT16 *p_uuid;
}tBTM_BLE_SERVICE;
-/* attribute data */
-typedef struct
-{
- UINT16 uuid;
- UINT16 data_len;
- UINT8 *p_data;
-}tBTM_BLE_ATTR;
-
-#ifndef BTM_BLE_NUM_AD_ATTR_MAX
-#define BTM_BLE_NUM_AD_ATTR_MAX 10
-#endif
-/* attribute list contained in adv data */
-typedef struct
-{
- UINT8 num_attr;
- tBTM_BLE_ATTR attr_list[BTM_BLE_NUM_AD_ATTR_MAX];
-}tBTM_BLE_ATTR_DATA;
-
typedef struct
{
UINT8 len;
@@ -243,11 +273,11 @@ typedef struct
typedef struct
{
- tBTM_BLE_MANU manu; /* manufactuer data */
+ tBTM_BLE_MANU manu; /* manufactuer data */
tBTM_BLE_INT_RANGE int_range; /* slave prefered conn interval range */
tBTM_BLE_SERVICE services; /* services */
- tBTM_BLE_ATTR_DATA attr; /* attribute data */
UINT8 flag;
+ UINT16 appearance;
tBTM_BLE_PROPRIETARY *p_proprietary;
}tBTM_BLE_ADV_DATA;
@@ -262,7 +292,6 @@ typedef struct
UINT8 tx_power_level;
UINT8 remote_name_len;
UINT8 *p_remote_name;
- tBTM_BLE_ATTR_DATA attr_data;
tBTM_BLE_SERVICE service;
} tBTM_BLE_INQ_DATA;
@@ -283,6 +312,7 @@ typedef void (tBTM_BLE_VERIFY_CBACK)(void *p_ref_data, BOOLEAN match);
typedef void (tBTM_BLE_RANDOM_SET_CBACK) (BD_ADDR random_bda);
typedef void (tBTM_BLE_SCAN_REQ_CBACK)(BD_ADDR remote_bda, tBLE_ADDR_TYPE addr_type, UINT8 adv_evt);
+
/*****************************************************************************
** EXTERNAL FUNCTION DECLARATIONS
*****************************************************************************/
@@ -554,7 +584,7 @@ BTM_API extern BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig,
/*******************************************************************************
**
-** Function BTM_SetRandomAddr
+** Function BTM_ReadConnectionAddr
**
** Description This function is called to set the local device random address
** .
@@ -562,19 +592,24 @@ BTM_API extern BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig,
** Returns void
**
*******************************************************************************/
-BTM_API extern void BTM_SetRandomAddr (tBTM_BLE_RANDOM_SET_CBACK *p_cback);
+BTM_API extern void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr,
+ tBLE_ADDR_TYPE *p_addr_type);
+
+
/*******************************************************************************
**
-** Function BTM_ReadConnectionAddr
+** Function BTM_ReadRemoteConnectionAddr
**
-** Description This function is called to set the local device random address
+** Description This function is read the remote device address currently used
** .
**
** Returns void
**
*******************************************************************************/
-BTM_API extern void BTM_ReadConnectionAddr (BD_ADDR conn_addr);
+BTM_API extern BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr,
+ BD_ADDR conn_addr,
+ tBLE_ADDR_TYPE *p_addr_type);
/*******************************************************************************
**
@@ -721,7 +756,113 @@ BTM_API extern tBTM_STATUS BTM_BleBroadcast(BOOLEAN start);
*******************************************************************************/
BTM_API extern void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback);
+/*******************************************************************************
+**
+** Function BTM_BleConfigPrivacy
+**
+** Description This function is called to enable or disable the privacy in
+** the local device.
+**
+** Parameters enable: TRUE to enable it; FALSE to disable it.
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern void BTM_BleConfigPrivacy(BOOLEAN enable);
+
+/*******************************************************************************
+**
+** Function BTM_BleSetConnMode
+**
+** Description This function is called to set BLE connectable mode for a
+** peripheral device.
+**
+** Parameters directed: is directed connectable mode, or non-directed.
+** p_dir_bda: connectable direct initiator's LE device address
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed);
+
+/*******************************************************************************
+**
+** Function BTM_BleTurnOnPrivacyOnRemote
+**
+** Description This function is called to enable or disable the privacy on the
+** remote device.
+**
+** Parameters bd_addr: remote device address.
+** privacy_on: TRUE to enable it; FALSE to disable it.
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern void BTM_BleTurnOnPrivacyOnRemote(BD_ADDR bd_addr,
+ BOOLEAN privacy_on);
+
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvWhitelist
+**
+** Description Add or remove device from advertising white list
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR emote_bda);
+
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvFilterPolicy
+**
+** Description This function update the filter policy of advertiser.
+**
+** Parameter adv_policy: advertising filter policy
+**
+** Return void
+*******************************************************************************/
+BTM_API extern void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy);
+
+/*******************************************************************************
+**
+** Function BTM_BleReceiverTest
+**
+** Description This function is called to start the LE Receiver test
+**
+** Parameter rx_freq - Frequency Range
+** p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+
+/*******************************************************************************
+**
+** Function BTM_BleTransmitterTest
+**
+** Description This function is called to start the LE Transmitter test
+**
+** Parameter tx_freq - Frequency Range
+** test_data_len - Length in bytes of payload data in each packet
+** packet_payload - Pattern to use in the payload
+** p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+ UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+/*******************************************************************************
+**
+** Function BTM_BleTestEnd
+**
+** Description This function is called to stop the in-progress TX or RX test
+**
+** Parameter p_cmd_cmpl_cback - Command complete callback
+**
+*******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback);
#ifdef __cplusplus
}
#endif
diff --git a/stack/include/btu.h b/stack/include/btu.h
index d33f0bb38..4f0e1622c 100644
--- a/stack/include/btu.h
+++ b/stack/include/btu.h
@@ -152,7 +152,11 @@ typedef void (*tBTU_EVENT_CALLBACK)(BT_HDR *p_hdr);
#define BTU_TTYPE_BLE_RANDOM_ADDR 103
#define BTU_TTYPE_ATT_WAIT_FOR_APP_RSP 104
#define BTU_TTYPE_ATT_WAIT_FOR_IND_ACK 105
-#define BTU_TTYPE_BLE_SCAN_PARAM_IDLE 106
+
+#define BTU_TTYPE_UCD_TO 106
+
+/* BTU timer event for TBFC */
+#define BTU_TTYPE_TBFC_RESUME 107
/* Define the BTU_TASK APPL events
*/
diff --git a/stack/include/gap_api.h b/stack/include/gap_api.h
new file mode 100644
index 000000000..05affed7e
--- /dev/null
+++ b/stack/include/gap_api.h
@@ -0,0 +1,802 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef GAP_API_H
+#define GAP_API_H
+
+#include "profiles_api.h"
+#include "btm_api.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/*** GAP Error and Status Codes ***/
+#define GAP_UNSUPPORTED (GAP_ERR_GRP + 0x01) /* Unsupported call */
+#define GAP_EOINQDB (GAP_ERR_GRP + 0x02) /* End of inquiry database marker */
+#define GAP_ERR_BUSY (GAP_ERR_GRP + 0x03) /* The requested function was busy */
+#define GAP_ERR_NO_CTRL_BLK (GAP_ERR_GRP + 0x04) /* No control blocks available */
+#define GAP_ERR_STARTING_CMD (GAP_ERR_GRP + 0x05) /* Error occurred while initiating the command */
+#define GAP_NO_BDADDR_REC (GAP_ERR_GRP + 0x06) /* No Inquiry DB record for BD_ADDR */
+#define GAP_ERR_ILL_MODE (GAP_ERR_GRP + 0x07) /* An illegal mode parameter was detected */
+#define GAP_ERR_ILL_INQ_TIME (GAP_ERR_GRP + 0x08) /* An illegal time parameter was detected */
+#define GAP_ERR_ILL_PARM (GAP_ERR_GRP + 0x09) /* An illegal parameter was detected */
+#define GAP_ERR_REM_NAME (GAP_ERR_GRP + 0x0a) /* Error starting the remote device name request */
+#define GAP_CMD_INITIATED (GAP_ERR_GRP + 0x0b) /* The GAP command was started (result pending) */
+#define GAP_DEVICE_NOT_UP (GAP_ERR_GRP + 0x0c) /* The device was not up; the request was not executed */
+#define GAP_BAD_BD_ADDR (GAP_ERR_GRP + 0x0d) /* The bd addr passed in was not found or invalid */
+
+#define GAP_ERR_BAD_HANDLE (GAP_ERR_GRP + 0x0e) /* Bad GAP handle */
+#define GAP_ERR_BUF_OFFSET (GAP_ERR_GRP + 0x0f) /* Buffer offset invalid */
+#define GAP_ERR_BAD_STATE (GAP_ERR_GRP + 0x10) /* Connection is in invalid state */
+#define GAP_NO_DATA_AVAIL (GAP_ERR_GRP + 0x11) /* No data available */
+#define GAP_ERR_CONGESTED (GAP_ERR_GRP + 0x12) /* BT stack is congested */
+#define GAP_ERR_SECURITY (GAP_ERR_GRP + 0x13) /* Security failed */
+
+#define GAP_ERR_PROCESSING (GAP_ERR_GRP + 0x14) /* General error processing BTM request */
+#define GAP_ERR_TIMEOUT (GAP_ERR_GRP + 0x15) /* Timeout occurred while processing cmd */
+
+/** GAP Events - definitions of GAP return events ***/
+#define GAP_EVT_INQUIRY_RESULTS 0x0001
+#define GAP_EVT_INQUIRY_COMPLETE 0x0002
+#define GAP_EVT_DISCOVERY_COMPLETE 0x0003
+#define GAP_EVT_REM_NAME_COMPLETE 0x0004
+#define GAP_EVT_FIND_ADDR_COMPLETE 0x0005
+
+#define GAP_EVT_CONN_OPENED 0x0100
+#define GAP_EVT_CONN_CLOSED 0x0101
+#define GAP_EVT_CONN_DATA_AVAIL 0x0102
+#define GAP_EVT_CONN_CONGESTED 0x0103
+#define GAP_EVT_CONN_UNCONGESTED 0x0104
+
+/* Values for 'chan_mode_mask' field */
+/* GAP_ConnOpen() - optional channels to negotiate */
+#define GAP_FCR_CHAN_OPT_BASIC L2CAP_FCR_CHAN_OPT_BASIC
+#define GAP_FCR_CHAN_OPT_ERTM L2CAP_FCR_CHAN_OPT_ERTM
+#define GAP_FCR_CHAN_OPT_STREAM L2CAP_FCR_CHAN_OPT_STREAM
+
+/*** discovery of devices ***/
+#define GAP_INQUIRY_NONE BTM_INQUIRY_NONE
+#define GAP_GENERAL_INQUIRY BTM_GENERAL_INQUIRY
+#define GAP_LIMITED_INQUIRY BTM_LIMITED_INQUIRY
+
+#if BLE_INCLUDED == TRUE
+#define GAP_BLE_INQUIRY_NONE BTM_BLE_INQUIRY_NONE
+#define GAP_BLE_GENERAL_INQUIRY BTM_BLE_GENERAL_INQUIRY
+#define GAP_BLE_LIMITED_INQUIRY BTM_BLE_LIMITED_INQUIRY
+#endif
+
+/*** discoverable modes ***/
+#define GAP_NON_DISCOVERABLE BTM_NON_DISCOVERABLE
+#define GAP_LIMITED_DISCOVERABLE BTM_LIMITED_DISCOVERABLE
+#define GAP_GENERAL_DISCOVERABLE BTM_GENERAL_DISCOVERABLE
+
+/*** Inquiry Filter Condition types (The values are defined in btm_api.h) ***/
+#define GAP_CLR_INQUIRY_FILTER BTM_CLR_INQUIRY_FILTER /* Inquiry Filtering is turned off */
+#define GAP_FILTER_COND_DEVICE_CLASS BTM_FILTER_COND_DEVICE_CLASS /* Filter on device class */
+#define GAP_FILTER_COND_BD_ADDR BTM_FILTER_COND_BD_ADDR /* Filter on device addr */
+
+/*** connectability ***/
+#define GAP_NON_CONNECTABLE BTM_NON_CONNECTABLE
+#define GAP_CONNECTABLE BTM_CONNECTABLE
+
+/*** security features ***/
+#define GAP_DISALLOW_PAIRING 0
+#define GAP_ALLOW_PAIRING 1
+
+/*** class of device settings ***/
+#define GAP_SET_COD_MAJOR_MINOR 0x01
+#define GAP_SET_COD_SERVICE_CLASS 0x02 /* only set the bits in the input */
+#define GAP_CLR_COD_SERVICE_CLASS 0x04
+#define GAP_SET_COD_ALL 0x08 /* take service class as the input (may clear some set bits!!) */
+#define GAP_INIT_COD 0x0a
+
+/*** used in connection variables and functions ***/
+#define GAP_INVALID_HANDLE 0xFFFF
+
+/* This is used to change the criteria for AMP */
+#define GAP_PROTOCOL_ID (UUID_PROTOCOL_UDP)
+
+/* slave preferred parameter, minimum connection interval */
+#ifndef GAP_SL_CONN_INT_MIN
+#define GAP_SL_CONN_INT_MIN 6
+#endif
+/* slave preferred parameter, maximum connection interval */
+#ifndef GAP_SL_CONN_INT_MAX
+#define GAP_SL_CONN_INT_MAX 20
+#endif
+/* slave preferred parameter */
+#ifndef GAP_SL_LATENCY
+#define GAP_SL_LATENCY 2
+#endif
+
+#ifndef GAP_BLE_PRIVACY_RECONN_ADDR_PERM
+#define GAP_BLE_PRIVACY_RECONN_ADDR_PERM (GATT_PERM_READ|GATT_PERM_WRITE)
+#endif
+
+#ifndef GAP_PREFER_CONN_INT_MAX
+#define GAP_PREFER_CONN_INT_MAX BTM_BLE_CONN_INT_MIN
+#endif
+
+#ifndef GAP_PREFER_CONN_INT_MIN
+#define GAP_PREFER_CONN_INT_MIN BTM_BLE_CONN_INT_MIN
+#endif
+
+#ifndef GAP_PREFER_CONN_LATENCY
+#define GAP_PREFER_CONN_LATENCY 0
+#endif
+
+#ifndef GAP_PREFER_CONN_SP_TOUT
+#define GAP_PREFER_CONN_SP_TOUT 2000
+#endif
+
+#if BLE_INCLUDED == TRUE
+#ifndef GAP_TRANSPORT_SUPPORTED
+#define GAP_TRANSPORT_SUPPORTED GATT_TRANSPORT_LE_BR_EDR
+#endif
+#endif
+/*****************************************************************************
+** Type Definitions
+*****************************************************************************/
+/*
+** Callback function for connection services
+*/
+typedef void (tGAP_CONN_CALLBACK) (UINT16 gap_handle, UINT16 event);
+
+/*
+** Define the callback function prototypes. Parameters are specific
+** to each event and are described below
+*/
+typedef void (tGAP_CALLBACK) (UINT16 event, void *p_data);
+
+typedef tBTM_REMOTE_DEV_NAME tGAP_REMOTE_DEV_NAME; /* see btm_api.h */
+typedef tBTM_INQ_PARMS tGAP_INQ_PARMS; /* see btm_api.h */
+typedef tBTM_INQ_RESULTS tGAP_INQ_RESULTS; /* see btm_api.h */
+
+/* Inquiry results structure */
+typedef struct
+{
+ UINT16 status;
+ UINT8 num_results;
+} tGAP_INQ_CMPL;
+
+/* Definition of the GAP_FindAddrByName results structure */
+typedef struct
+{
+ UINT16 status;
+ BD_ADDR bd_addr;
+ tBTM_BD_NAME devname;
+} tGAP_FINDADDR_RESULTS;
+
+/** for GAP_SetDeviceClass() **/
+/* Define Class of Device related values
+ *
+ * >>> changes to this type need to also be made to tHSP_COD in hsp2_int.h
+ */
+typedef struct
+{
+ UINT8 minor;
+ UINT8 major;
+ UINT16 service;
+} tGAP_COD;
+
+/*** Constants and functions for device features ***/
+typedef struct
+{
+ UINT8 lmp_version;
+ UINT16 mfc_name;
+ UINT16 lmp_subversion;
+} tGAP_LMP_VERSION;
+
+typedef struct
+{
+ UINT8 lmp_features[8];
+} tGAP_LMP_FEATURES;
+
+typedef struct
+{
+ UINT16 int_min;
+ UINT16 int_max;
+ UINT16 latency;
+ UINT16 sp_tout;
+}tGAP_BLE_PREF_PARAM;
+
+typedef union
+{
+ tGAP_BLE_PREF_PARAM conn_param;
+ BD_ADDR reconn_bda;
+ UINT16 icon;
+ UINT8 *p_dev_name;
+ UINT8 privacy;
+
+}tGAP_BLE_ATTR_VALUE;
+
+typedef void (tGAP_BLE_DEV_NAME_CBACK)(BOOLEAN status, BD_ADDR addr, UINT16 length, char *p_name);
+
+typedef void (tGAP_BLE_RECONN_ADDR_CBACK)(BOOLEAN status, BD_ADDR addr, BD_ADDR reconn_bda);
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function GAP_SetDiscoverableMode
+**
+** Description This function is called to allow or disallow a service to
+** discovered (Inquiry Scans).
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetDiscoverableMode (UINT16 mode, UINT16 duration,
+ UINT16 interval);
+
+/*******************************************************************************
+**
+** Function GAP_ReadDiscoverableMode
+**
+** Description This function is called to retrieve the current discoverable
+** mode for the local device.
+**
+** Returns GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE, or
+** GAP_GENERAL_DISCOVERABLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadDiscoverableMode (UINT16 *duration, UINT16 *interval);
+
+/*******************************************************************************
+**
+** Function GAP_StartInquiry
+**
+** Description This function initiates a single inquiry.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_StartInquiry (tGAP_INQ_PARMS *p_inq_parms,
+ tGAP_CALLBACK *p_results_cb,
+ tGAP_CALLBACK *p_cmpl_cb);
+
+/*******************************************************************************
+**
+** Function GAP_StartPeriodicInquiry
+**
+** Description This function initiates a periodic inquiry.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_StartPeriodicInquiry (tGAP_INQ_PARMS *p_inq_parms,
+ UINT16 min_time,
+ UINT16 max_time,
+ tGAP_CALLBACK *p_results_cb);
+
+/*******************************************************************************
+**
+** Function GAP_CancelInquiry
+**
+** Description This function cancels a single inquiry (if in progress)
+**
+** Returns BOOLEAN (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_CancelInquiry(void);
+
+/*******************************************************************************
+**
+** Function GAP_CancelPeriodicInquiry
+**
+** Description This function cancels a periodic inquiry (if in progress)
+**
+** Returns BOOLEAN: (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_CancelPeriodicInquiry(void);
+
+/*******************************************************************************
+**
+** Function GAP_GetFirstInquiryResult
+**
+** Description This function retrieves the first valid inquiry result.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetFirstInquiryResult(tGAP_INQ_RESULTS *p_results);
+
+/*******************************************************************************
+**
+** Function GAP_GetNextInquiryResult
+**
+** Description This function retrieves the next valid inquiry result.
+**
+** Returns BT_PASS (0) if successful, or a non-zero status code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetNextInquiryResult(tGAP_INQ_RESULTS *p_results);
+
+/*******************************************************************************
+**
+** Function GAP_FindAddrByName
+**
+** Description This function is called to retrieve a device address given
+** a device name. It first looks in the current local inquiry
+** database for the device with the specified name. If not found
+** it initiates a general inquiry. Upon completion, it retrieves
+** the name for each device until a match is found or all devices
+** have been checked. Note: This process can take a while to
+** complete.
+**
+** Returns BT_PASS if the name was immediately available. (BD_ADDR is returned)
+** GAP_CMD_INITIATED if an inquiry has been initiated
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_FindAddrByName (BD_NAME devname,
+ tGAP_INQ_PARMS *p_inq_parms,
+ tGAP_CALLBACK *p_addr_cb,
+ BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function GAP_SetConnectableMode
+**
+** Description This function is called to allow or disallow a
+** connections on the local device.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetConnectableMode (UINT16 mode, UINT16 duration,
+ UINT16 interval);
+
+/*******************************************************************************
+**
+** Function GAP_ReadConnectableMode
+**
+** Description This function is called to retrieve the current connectability
+** mode for the local device.
+**
+** Returns GAP_NON_CONNECTABLE, GAP_CONNECTABLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadConnectableMode (UINT16 *duration, UINT16 *interval);
+
+/*******************************************************************************
+**
+** Function GAP_SetSecurityMode
+**
+** Description Set security mode for the device (Service or Link level)
+**
+** Returns void
+**
+*******************************************************************************/
+GAP_API extern void GAP_SetSecurityMode (UINT8 sec_mode);
+
+/*******************************************************************************
+**
+** Function GAP_SecRegister
+**
+** Description Application calls this function to register for
+** security services.
+**
+** Returns TRUE if registered OK, else FALSE
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_SecRegister (tBTM_APPL_INFO *p_cb_info);
+
+/*******************************************************************************
+**
+** Function GAP_SetPairableMode
+**
+** Description This function is called to allow or disallow pairing
+** on the local device.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetPairableMode (UINT16 mode, BOOLEAN connect_only_paired);
+
+/*******************************************************************************
+**
+** Function GAP_Bond
+**
+** Description This function is called to initiate bonding with peer device
+**
+** Returns tBTM_STATUS - BTM_CMD_STARTED of successfully initiated
+**
+*******************************************************************************/
+GAP_API extern UINT8 GAP_Bond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function GAP_PinRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** PIN code request.
+**
+** Returns void
+**
+*******************************************************************************/
+GAP_API extern void GAP_PinRsp (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len,
+ UINT8 *p_pin, UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function GAP_AuthorizeRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** an authorization request.
+**
+** Returns void
+**
+*******************************************************************************/
+GAP_API extern void GAP_AuthorizeRsp (BD_ADDR bd_addr, UINT8 res,
+ UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function GAP_SetDeviceClass
+**
+** Description This function updates the local Device Class.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_BUSY if a discovery is already in progress
+** GAP_ERR_ILL_PARM if an illegal parameter was detected
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetDeviceClass(tGAP_COD *p_cod, UINT8 cmd);
+
+/*******************************************************************************
+**
+** Function GAP_ReadDeviceClass
+**
+** Description This function reads the current local Device Class setting.
+**
+** Returns BT_PASS
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadDeviceClass(tGAP_COD *p_cod);
+
+/*******************************************************************************
+**
+** Function GAP_ReadLocalDeviceInfo
+**
+** Description This function retrieves local device information to the caller.
+** NOTE: Return parameters that are set to NULL are not retrieved.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadLocalDeviceInfo( UINT8 *name, BD_ADDR *addr,
+ tGAP_LMP_VERSION *verinfo,
+ tGAP_LMP_FEATURES *features);
+
+
+/*******************************************************************************
+**
+** Function GAP_GetRemoteDeviceName
+**
+** Description The remote name is retrieved from the specified remote device. If
+** GAP_CMD_INITIATED is returned by the function, the command was
+** successfully sent to the controller. The GAP_EVT_NAME_RESP event
+** is passed in the callback when the remote device name has been retrieved.
+**
+** Returns
+** GAP_CMD_INITIATED if remote search successfully initiated
+** GAP_ERR_BUSY if a remote name request is already in progress,
+** GAP_ERR_NO_CTRL_BLK if out of control blocks (too many commands pending)
+** GAP_BAD_BD_ADDR if the device address is bad,
+** GAP_DEVICE_NOT_UP if the device has not been initialized yet
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetRemoteDeviceName (BD_ADDR addr, tGAP_CALLBACK *callback);
+
+/*** Functions for L2CAP connection interface ***/
+/*******************************************************************************
+**
+** Function GAP_ConnOpen
+**
+** Description This function is called to open a generic L2CAP connection.
+**
+** Returns handle of the connection if successful, else GAP_INVALID_HANDLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
+ BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
+ UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb);
+
+/*******************************************************************************
+**
+** Function GAP_ConnClose
+**
+** Description This function is called to close a connection.
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnClose (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_ConnReadData
+**
+** Description GKI buffer unaware application will call this function
+** after receiving GAP_EVT_RXDATA event. A data copy is made
+** into the receive buffer parameter.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data,
+ UINT16 max_len, UINT16 *p_len);
+
+/*******************************************************************************
+**
+** Function GAP_GetRxQueueCnt
+**
+** Description This function return number of bytes on the rx queue.
+**
+** Parameters: handle - Handle returned in the GAP_ConnOpen
+** p_rx_queue_count - Pointer to return queue count in.
+**
+**
+*******************************************************************************/
+GAP_API extern int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count);
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTRead
+**
+** Description GKI buffer aware applications will call this function after
+** receiving an GAP_EVT_RXDATA event to process the incoming
+** data buffer.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf);
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTWrite
+**
+** Description GKI buffer aware applications can call this function to write data
+** by passing a pointer to the GKI buffer of data.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_INVALID_BUF_OFFSET - buffer offset is invalid
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf);
+
+/*******************************************************************************
+**
+** Function GAP_ConnWriteData
+**
+** Description GKI buffer unaware application will call this function
+** to send data to the connection. A data copy is made into a GKI
+** buffer.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_CONGESTION - system is congested
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data,
+ UINT16 max_len, UINT16 *p_len);
+
+/*******************************************************************************
+**
+** Function GAP_ConnReconfig
+**
+** Description Applications can call this function to reconfigure the connection.
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg);
+
+/*******************************************************************************
+**
+** Function GAP_ConnSetIdleTimeout
+**
+** Description Higher layers call this function to set the idle timeout for
+** a connection, or for all future connections. The "idle timeout"
+** is the amount of time that a connection can remain up with
+** no L2CAP channels on it. A timeout of zero means that the
+** connection will be torn down immediately when the last channel
+** is removed. A timeout of 0xFFFF means no timeout. Values are
+** in seconds.
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout);
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemoteAddr
+**
+** Description This function is called to get the remote BD address
+** of a connection.
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemMtuSize
+**
+** Description Returns the remote device's MTU size.
+**
+** Returns UINT16 - maximum size buffer that can be transmitted to the peer
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetL2CAPCid
+**
+** Description Returns the L2CAP channel id
+**
+** Parameters: handle - Handle of the connection
+**
+** Returns UINT16 - The L2CAP channel id
+** 0, if error
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_SetTraceLevel
+**
+** Description This function sets the trace level for GAP. If called with
+** a value of 0xFF, it simply returns the current trace level.
+**
+** Returns The new or current trace level
+**
+*******************************************************************************/
+GAP_API extern UINT8 GAP_SetTraceLevel (UINT8 new_level);
+
+/*******************************************************************************
+**
+** Function GAP_Init
+**
+** Description Initializes the control blocks used by GAP.
+** This routine should not be called except once per
+** stack invocation.
+**
+** Returns Nothing
+**
+*******************************************************************************/
+GAP_API extern void GAP_Init(void);
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function GAP_BleAttrDBUpdate
+**
+** Description update GAP local BLE attribute database.
+**
+** Returns Nothing
+**
+*******************************************************************************/
+GAP_API extern void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value);
+
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerPrefConnParams
+**
+** Description Start a process to read a connected peripheral's preferred
+** connection parameters
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda);
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerDevName
+**
+** Description Start a process to read a connected peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function GAP_BleCancelReadPeerDevName
+**
+** Description Cancel reading a peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda);
+
+/*******************************************************************************
+**
+** Function GAP_BleUpdateReconnectAddr
+**
+** Description Start a process to udpate the reconnect address if remote devive
+** has privacy enabled.
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda,
+ BD_ADDR reconn_addr,
+ tGAP_BLE_RECONN_ADDR_CBACK *p_cback);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GAP_API_H */
+
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 2d13e5a32..d53a80e1a 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -137,6 +137,9 @@ typedef UINT16 tGATT_DISCONN_REASON;
#define GATT_MAX_SCCB 10
#endif
+#ifndef GATTP_TRANSPORT_SUPPORTED
+#define GATTP_TRANSPORT_SUPPORTED GATT_TRANSPORT_LE_BR_EDR
+#endif
/* GATT notification caching timer, default to be three seconds
@@ -164,7 +167,7 @@ typedef UINT16 tGATT_PERM;
#define GATT_ENCRYPT_KEY_SIZE_MASK (0xF000) /* the MS nibble of tGATT_PERM; key size 7=0; size 16=9 */
#define GATT_READ_ALLOWED (GATT_PERM_READ | GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM)
-#define GATT_READ_AUTH_REQUIRED (GATT_PERM_READ_ENC_MITM)
+#define GATT_READ_AUTH_REQUIRED (GATT_PERM_READ_ENCRYPTED)
#define GATT_READ_MITM_REQUIRED (GATT_PERM_READ_ENC_MITM)
#define GATT_READ_ENCRYPTED_REQUIRED (GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM)
@@ -1120,6 +1123,25 @@ extern "C"
*******************************************************************************/
GATT_API extern BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id);
+
+/*******************************************************************************
+**
+** Function GATT_Listen
+**
+** Description This function start or stop LE advertisement and listen for
+** connection.
+**
+** Parameters gatt_if: applicaiton interface
+** p_bd_addr: listen for specific address connection, or NULL for
+** listen to all device connection.
+** start: is a direct conenection or a background auto connection
+**
+** Returns TRUE if advertisement is started; FALSE if adv start failure.
+**
+*******************************************************************************/
+ GATT_API extern BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr);
+
+
#ifdef __cplusplus
}
diff --git a/stack/include/gattdefs.h b/stack/include/gattdefs.h
index 6eac0f438..e2150f2a6 100644
--- a/stack/include/gattdefs.h
+++ b/stack/include/gattdefs.h
@@ -57,53 +57,4 @@
#define GATT_UUID_GATT_SRV_CHGD 0x2A05
/* Attribute Protocol Test */
-/* Link Loss Service */
-#define GATT_UUID_ALERT_LEVEL 0x2A06 /* Alert Level */
-#define GATT_UUID_TX_POWER_LEVEL 0x2A07 /* TX power level */
-
-/* Time Profile */
-/* Current Time Service */
-#define GATT_UUID_CURRENT_TIME 0x2A2B /* Current Time */
-#define GATT_UUID_LOCAL_TIME_INFO 0x2A0F /* Local time info */
-#define GATT_UUID_REF_TIME_INFO 0x2A14 /* reference time information */
-
-/* NwA Profile */
-#define GATT_UUID_NW_STATUS 0x2A18 /* network availability status */
-#define GATT_UUID_NW_TRIGGER 0x2A1A /* Network availability trigger */
-
-/* phone alert */
-#define GATT_UUID_ALERT_STATUS 0x2A40 /* alert status */
-#define GATT_UUID_RINGER_CP 0x2A42 /* ringer control point */
-#define GATT_UUID_RINGER_SETTING 0x2A41 /* ringer setting */
-
-/* Glucose Service */
-#define GATT_UUID_GM_MEASUREMENT 0x2A18
-#define GATT_UUID_GM_CONTEXT 0x2A34
-#define GATT_UUID_GM_CONTROL_POINT 0x2A52
-#define GATT_UUID_GM_FEATURE 0x2A51
-
-/* device infor characteristic */
-#define GATT_UUID_SYSTEM_ID 0x2A23
-#define GATT_UUID_MODEL_NUMBER_STR 0x2A24
-#define GATT_UUID_SERIAL_NUMBER_STR 0x2A25
-#define GATT_UUID_FW_VERSION_STR 0x2A26
-#define GATT_UUID_HW_VERSION_STR 0x2A27
-#define GATT_UUID_SW_VERSION_STR 0x2A28
-#define GATT_UUID_MANU_NAME 0x2A29
-#define GATT_UUID_IEEE_DATA 0x2A2A
-#define GATT_UUID_PNP_ID 0x2A50
-
-/* HID characteristics */
-#define GATT_UUID_HID_INFORMATION 0x2A4A
-#define GATT_UUID_HID_REPORT_MAP 0x2A4B
-#define GATT_UUID_HID_CONTROL_POINT 0x2A4C
-#define GATT_UUID_HID_REPORT 0x2A4D
-#define GATT_UUID_HID_PROTO_MODE 0x2A4E
-#define GATT_UUID_HID_BT_KB_INPUT 0x2A22
-#define GATT_UUID_HID_BT_KB_OUTPUT 0x2A32
-#define GATT_UUID_HID_BT_MOUSE_INPUT 0x2A33
-
-/* Battery Service char */
-#define GATT_UUID_BATTERY_LEVEL 0x2A19
-
#endif
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 1a0b3e818..0584f65c6 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -19,10 +19,6 @@
#ifndef HCIDEFS_H
#define HCIDEFS_H
-#ifdef BRCM_VS
-#include "brcm_vs_include.h"
-#endif
-
#define HCI_PROTO_VERSION 0x01 /* Version for BT spec 1.1 */
#define HCI_PROTO_VERSION_1_2 0x02 /* Version for BT spec 1.2 */
#define HCI_PROTO_VERSION_2_0 0x03 /* Version for BT spec 2.0 */
@@ -100,8 +96,19 @@
#define HCI_LOGICAL_LINK_CANCEL (0x003B | HCI_GRP_LINK_CONTROL_CMDS)
#define HCI_FLOW_SPEC_MODIFY (0x003C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ENH_SETUP_ESCO_CONNECTION (0x003D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ENH_ACCEPT_ESCO_CONNECTION (0x003E | HCI_GRP_LINK_CONTROL_CMDS)
+
+/* ConnectionLess Broadcast */
+#define HCI_TRUNCATED_PAGE (0x003F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_TRUNCATED_PAGE_CANCEL (0x0040 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_SET_CLB (0x0041 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RECEIVE_CLB (0x0042 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_START_SYNC_TRAIN (0x0043 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RECEIVE_SYNC_TRAIN (0x0044 | HCI_GRP_LINK_CONTROL_CMDS)
+
#define HCI_LINK_CTRL_CMDS_FIRST HCI_INQUIRY
-#define HCI_LINK_CTRL_CMDS_LAST HCI_FLOW_SPEC_MODIFY
+#define HCI_LINK_CTRL_CMDS_LAST HCI_RECEIVE_SYNC_TRAIN
/* Commands of HCI_GRP_LINK_POLICY_CMDS */
#define HCI_HOLD_MODE (0x0001 | HCI_GRP_LINK_POLICY_CMDS)
@@ -131,6 +138,7 @@
#define HCI_READ_PIN_TYPE (0x0009 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_WRITE_PIN_TYPE (0x000A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_CREATE_NEW_UNIT_KEY (0x000B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_GET_MWS_TRANS_LAYER_CFG (0x000C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_READ_STORED_LINK_KEY (0x000D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_WRITE_STORED_LINK_KEY (0x0011 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_DELETE_STORED_LINK_KEY (0x0012 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
@@ -210,9 +218,27 @@
#define HCI_READ_BE_FLUSH_TOUT (0x0069 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_WRITE_BE_FLUSH_TOUT (0x006A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_SHORT_RANGE_MODE (0x006B | HCI_GRP_HOST_CONT_BASEBAND_CMDS) /* 802.11 only */
+#define HCI_READ_LE_HOST_SUPPORTED (0x006C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_LE_HOST_SUPPORTED (0x006D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+
+/* MWS coexistence */
+#define HCI_SET_MWS_CHANNEL_PARAMETERS (0x006E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_EXTERNAL_FRAME_CONFIGURATION (0x006F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_SIGNALING (0x0070 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_TRANSPORT_LAYER (0x0071 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_SCAN_FREQUENCY_TABLE (0x0072 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_PATTERN_CONFIGURATION (0x0073 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+/* ConnectionLess Broadcast */
+#define HCI_SET_RESERVED_LT_ADDR (0x0077 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_DELETE_RESERVED_LT_ADDR (0x0078 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CLB_DATA (0x0079 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SYNC_TRAIN_PARAM (0x007A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SYNC_TRAIN_PARAM (0x007B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_CONT_BASEBAND_CMDS_FIRST HCI_SET_EVENT_MASK
-#define HCI_CONT_BASEBAND_CMDS_LAST HCI_SHORT_RANGE_MODE
+#define HCI_CONT_BASEBAND_CMDS_LAST HCI_READ_SYNC_TRAIN_PARAM
/* Commands of HCI_GRP_INFORMATIONAL_PARAMS group */
@@ -224,9 +250,10 @@
#define HCI_READ_COUNTRY_CODE (0x0007 | HCI_GRP_INFORMATIONAL_PARAMS)
#define HCI_READ_BD_ADDR (0x0009 | HCI_GRP_INFORMATIONAL_PARAMS)
#define HCI_READ_DATA_BLOCK_SIZE (0x000A | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_SUPPORTED_CODECS (0x000B | HCI_GRP_INFORMATIONAL_PARAMS)
#define HCI_INFORMATIONAL_CMDS_FIRST HCI_READ_LOCAL_VERSION_INFO
-#define HCI_INFORMATIONAL_CMDS_LAST HCI_READ_BD_ADDR
+#define HCI_INFORMATIONAL_CMDS_LAST HCI_READ_LOCAL_SUPPORTED_CODECS
/* Commands of HCI_GRP_STATUS_PARAMS group */
@@ -296,6 +323,10 @@
#define HCI_BLE_LTK_REQ_REPLY (0x001A | HCI_GRP_BLE_CMDS)
#define HCI_BLE_LTK_REQ_NEG_REPLY (0x001B | HCI_GRP_BLE_CMDS)
#define HCI_BLE_READ_SUPPORTED_STATES (0x001C | HCI_GRP_BLE_CMDS)
+/* BLE TEST COMMANDS */
+#define HCI_BLE_RECEIVER_TEST (0x001D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TRANSMITTER_TEST (0x001E | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TEST_END (0x001F | HCI_GRP_BLE_CMDS)
#define HCI_BLE_RESET (0x0020 | HCI_GRP_BLE_CMDS)
@@ -390,8 +421,18 @@
#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04
#define HCI_BLE_LTK_REQ_EVT 0x05
-#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT
-#define HCI_EVENT_RSP_LAST HCI_AMP_STATUS_CHANGE_EVT
+/* ConnectionLess Broadcast events */
+#define HCI_SYNC_TRAIN_COMP_EVT 0x4F
+#define HCI_SYNC_TRAIN_RECEIVED_EVT 0x50
+#define HCI_CLB_RX_DATA_EVT 0x51
+#define HCI_CLB_RX_TIMEOUT_EVT 0x52
+#define HCI_TRUNCATED_PAGE_COMP_EVT 0x53
+#define HCI_SLAVE_PAGE_RESP_TIMEOUT_EVT 0x54
+#define HCI_CLB_CHANNEL_CHANGE_EVT 0x55
+#define HCI_INQUIRY_RESPONSE_NOTIF 0x56
+
+#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT
+#define HCI_EVENT_RSP_LAST HCI_CLB_CHANNEL_CHANGE_EVT
#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */
#define HCI_NAP_TRACE_EVT 0xFF /* was define 0xFE, 0xFD, change to 0xFF
@@ -469,7 +510,13 @@
#define HCI_ERR_CONN_FAILED_ESTABLISHMENT 0x3E
#define HCI_ERR_MAC_CONNECTION_FAILED 0x3F
-#define HCI_ERR_MAX_ERR 0x40
+/* ConnectionLess Broadcast errors */
+#define HCI_ERR_LT_ADDR_ALREADY_IN_USE 0x40
+#define HCI_ERR_LT_ADDR_NOT_ALLOCATED 0x41
+#define HCI_ERR_CLB_NOT_ENABLED 0x42
+#define HCI_ERR_CLB_DATA_TOO_BIG 0x43
+
+#define HCI_ERR_MAX_ERR 0x43
#define HCI_HINT_TO_RECREATE_AMP_PHYS_LINK 0xFF
@@ -965,8 +1012,15 @@
#define HCI_CONTROLLER_TYPE_ECMA 2
#define HCI_MAX_CONTROLLER_TYPES 3
+/* ConnectionLess Broadcast */
+#define HCI_CLB_DISABLE 0x00
+#define HCI_CLB_ENABLE 0x01
-
+/* ConnectionLess Broadcast Data fragment */
+#define HCI_CLB_FRAGMENT_CONT 0x00
+#define HCI_CLB_FRAGMENT_START 0x01
+#define HCI_CLB_FRAGMENT_END 0x02
+#define HCI_CLB_FRAGMENT_SINGLE 0x03
/* AMP Controller Status codes
*/
@@ -1152,7 +1206,43 @@ typedef struct
#define LMP_COMPID_SOUND ID 111
#define LMP_COMPID_MONSTER LLC 112
#define LMP_COMPID_CONNECTBLU 113
-#define LMP_COMPID_MAX_ID 114 /* this is a place holder */
+
+#define LMP_COMPID_SHANGHAI_SSE 114
+#define LMP_COMPID_GROUP_SENSE 115
+#define LMP_COMPID_ZOMM 116
+#define LMP_COMPID_SAMSUNG 117
+#define LMP_COMPID_CREATIVE_TECH 118
+#define LMP_COMPID_LAIRD_TECH 119
+#define LMP_COMPID_NIKE 120
+#define LMP_COMPID_LESSWIRE 121
+#define LMP_COMPID_MSTAR_SEMI 122
+#define LMP_COMPID_HANLYNN_TECH 123
+#define LMP_COMPID_AR_CAMBRIDGE 124
+#define LMP_COMPID_SEERS_TECH 125
+#define LMP_COMPID_SPORTS_TRACKING 126
+#define LMP_COMPID_AUTONET_MOBILE 127
+#define LMP_COMPID_DELORME_PUBLISH 128
+#define LMP_COMPID_WUXI_VIMICRO 129
+#define LMP_COMPID_SENNHEISER 130
+#define LMP_COMPID_TIME_KEEPING_SYS 131
+#define LMP_COMPID_LUDUS_HELSINKI 132
+#define LMP_COMPID_BLUE_RADIOS 133
+#define LMP_COMPID_EQUINUX 134
+#define LMP_COMPID_GARMIN_INTL 135
+#define LMP_COMPID_ECOTEST 136
+#define LMP_COMPID_GN_RESOUND 137
+#define LMP_COMPID_JAWBONE 138
+#define LMP_COMPID_TOPCON_POSITIONING 139
+#define LMP_COMPID_QUALCOMM_LABS 140
+#define LMP_COMPID_ZSCAN_SOFTWARE 141
+#define LMP_COMPID_QUINTIC 142
+#define LMP_COMPID_STOLLMAN_EV 143
+#define LMP_COMPID_FUNAI_ELECTRONIC 144
+#define LMP_COMPID_ADV_PANMOBILE 145
+#define LMP_COMPID_THINK_OPTICS 146
+#define LMP_COMPID_UNIVERSAL_ELEC 147
+#define LMP_COMPID_AIROHA_TECH 148
+#define LMP_COMPID_MAX_ID 149 /* this is a place holder */
#define LMP_COMPID_INTERNAL 65535
#define MAX_LMP_COMPID (LMP_COMPID_MAX_ID)
@@ -1349,6 +1439,16 @@ typedef struct
#define HCI_FEATURE_AFH_CLASS_SLAVE_OFF 4
#define HCI_LMP_AFH_CLASS_SLAVE_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CLASS_SLAVE_OFF] & HCI_FEATURE_AFH_CLASS_SLAVE_MASK)
+#if 1
+#define HCI_FEATURE_BREDR_NOT_SPT_MASK 0x20
+#define HCI_FEATURE_BREDR_NOT_SPT_OFF 4
+#define HCI_BREDR_NOT_SPT_SUPPORTED(x) ((x)[HCI_FEATURE_BREDR_NOT_SPT_OFF] & HCI_FEATURE_BREDR_NOT_SPT_MASK)
+
+#define HCI_FEATURE_LE_SPT_MASK 0x40
+#define HCI_FEATURE_LE_SPT_OFF 4
+#define HCI_LE_SPT_SUPPORTED(x) ((x)[HCI_FEATURE_LE_SPT_OFF] & HCI_FEATURE_LE_SPT_MASK)
+#else
+
#define HCI_FEATURE_ALIAS_AUTH_MASK 0x20
#define HCI_FEATURE_ALIAS_AUTH_OFF 4
#define HCI_LMP_ALIAS_AUTH_SUPPORTED(x) ((x)[HCI_FEATURE_ALIAS_AUTH_OFF] & HCI_FEATURE_ALIAS_AUTH_MASK)
@@ -1356,6 +1456,7 @@ typedef struct
#define HCI_FEATURE_ANON_MODE_MASK 0x40
#define HCI_FEATURE_ANON_MODE_OFF 4
#define HCI_LMP_ANON_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_ANON_MODE_OFF] & HCI_FEATURE_ANON_MODE_MASK)
+#endif
#define HCI_FEATURE_3_SLOT_EDR_ACL_MASK 0x80
#define HCI_FEATURE_3_SLOT_EDR_ACL_OFF 4
@@ -1397,9 +1498,16 @@ typedef struct
#define HCI_FEATURE_EXT_INQ_RSP_OFF 6
#define HCI_EXT_INQ_RSP_SUPPORTED(x) ((x)[HCI_FEATURE_EXT_INQ_RSP_OFF] & HCI_FEATURE_EXT_INQ_RSP_MASK)
+#if 1 /* TOKYO spec definition */
+#define HCI_FEATURE_SIMUL_LE_BREDR_MASK 0x02
+#define HCI_FEATURE_SIMUL_LE_BREDR_OFF 6
+#define HCI_SIMUL_LE_BREDR_SUPPORTED(x) ((x)[HCI_FEATURE_SIMUL_LE_BREDR_OFF] & HCI_FEATURE_SIMUL_LE_BREDR_MASK)
+
+#else
#define HCI_FEATURE_ANUM_PIN_AWARE_MASK 0x02
#define HCI_FEATURE_ANUM_PIN_AWARE_OFF 6
#define HCI_ANUM_PIN_AWARE_SUPPORTED(x) ((x)[HCI_FEATURE_ANUM_PIN_AWARE_OFF] & HCI_FEATURE_ANUM_PIN_AWARE_MASK)
+#endif
#define HCI_FEATURE_ANUM_PIN_CAP_MASK 0x04
#define HCI_FEATURE_ANUM_PIN_CAP_OFF 6
@@ -1448,6 +1556,14 @@ typedef struct
#define HCI_EXT_FEATURE_SSP_HOST_OFF 0
#define HCI_SSP_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SSP_HOST_OFF] & HCI_EXT_FEATURE_SSP_HOST_MASK)
+#define HCI_EXT_FEATURE_LE_HOST_MASK 0x02
+#define HCI_EXT_FEATURE_LE_HOST_OFF 0
+#define HCI_LE_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_LE_HOST_OFF] & HCI_EXT_FEATURE_LE_HOST_MASK)
+
+#define HCI_EXT_FEATURE_SIMUL_DUMO_HOST_MASK 0x04
+#define HCI_EXT_FEATURE_SIMUL_DUMO_HOST_OFF 0
+#define HCI_SIMUL_DUMO_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SIMUL_DUMO_HOST_OFF] & HCI_EXT_FEATURE_SIMUL_DUMO_HOST_MASK)
+
/*
** Local Supported Commands encoding
*/
@@ -2136,6 +2252,99 @@ typedef struct
** Supported Commands (Byte 28)
*/
+/* Supported Commands (Byte 29) */
+#define HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_MASK 0x08
+#define HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_OFF 29
+#define HCI_READ_ENH_SETUP_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_MASK 0x10
+#define HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_OFF 29
+#define HCI_READ_ENH_ACCEPT_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_OFF 29
+#define HCI_READ_LOCAL_CODECS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_MASK 0x40
+#define HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_OFF 29
+#define HCI_SET_MWS_CHANNEL_PARAMETERS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_OFF] & HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_MASK 0x80
+#define HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_OFF 29
+#define HCI_SET_EXTERNAL_FRAME_CONFIGURATION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_OFF] & HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_MASK)
+
+
+/* Supported Commands (Byte 30) */
+#define HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_MASK 0x01
+#define HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_OFF 30
+#define HCI_SET_MWS_SIGNALING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_OFF] & HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_MASK 0x02
+#define HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_OFF 30
+#define HCI_SET_MWS_TRANSPORT_LAYER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_OFF] & HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_MASK 0x04
+#define HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_OFF 30
+#define HCI_SET_MWS_SCAN_FREQUENCY_TABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_OFF] & HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_MASK 0x08
+#define HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_OFF 30
+#define HCI_GET_MWS_TRANS_LAYER_CFG_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_OFF] & HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_MASK 0x10
+#define HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF 30
+#define HCI_SET_MWS_PATTERN_CONFIGURATION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF] & HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_MASK)
+
+/* Supported Commands (Byte 30 bit 6-7) */
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE 0x06
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_OFF 30
+#define HCI_TRUNCATED_PAGE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_TRUNCATED_PAGE_OFF] & HCI_SUPP_COMMANDS_TRUNCATED_PAGE)
+
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL 0x07
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL_OFF 30
+#define HCI_TRUNCATED_PAGE_CANCEL_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL_OFF] & HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL)
+
+/* Supported Commands (Byte 31 bit 6-7) */
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST 0x00
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_OFF 31
+#define HCI_SET_CONLESS_SLAVE_BRCST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST)
+
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE 0x01
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE_OFF 31
+#define HCI_SET_CONLESS_SLAVE_BRCST_RECEIVE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE)
+
+#define HCI_SUPP_COMMANDS_START_SYNC_TRAIN 0x02
+#define HCI_SUPP_COMMANDS_START_SYNC_TRAIN_OFF 31
+#define HCI_START_SYNC_TRAIN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_START_SYNC_TRAIN_OFF] & HCI_SUPP_COMMANDS_START_SYNC_TRAIN)
+
+#define HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN 0x03
+#define HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN_OFF 31
+#define HCI_RECEIVE_SYNC_TRAIN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN_OFF] & HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN)
+
+#define HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR 0x04
+#define HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR_OFF 31
+#define HCI_SET_RESERVED_LT_ADDR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR_OFF] & HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR)
+
+#define HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR 0x05
+#define HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR_OFF 31
+#define HCI_DELETE_RESERVED_LT_ADDR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR_OFF] & HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR)
+
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA 0x06
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA_OFF 31
+#define HCI_SET_CONLESS_SLAVE_BRCST_DATA_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA)
+
+#define HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM 0x07
+#define HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM_OFF 31
+#define HCI_READ_SYNC_TRAIN_PARAM_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM_OFF] & HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM)
+
+/* Supported Commands (Byte 32 bit 0) */
+#define HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM 0x00
+#define HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM_OFF 32
+#define HCI_WRITE_SYNC_TRAIN_PARAM_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM_OFF] & HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM)
+
+
+
+
/*
Commands of HCI_GRP_VENDOR_SPECIFIC group for WIDCOMM SW LM Simulator
*/
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index 3a23dbe25..cb85cb127 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -1241,6 +1241,7 @@ HCI_API extern void btsnd_hcie_ext_inquiry_result(void *buffer, UINT8 num_resp,
#define HCIC_PARAM_SIZE_BLE_READ_REMOTE_FEAT 2
#define HCIC_PARAM_SIZE_BLE_ENCRYPT 32
#define HCIC_PARAM_SIZE_BLE_RAND 0
+#define HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED 2
#define HCIC_BLE_RAND_DI_SIZE 8
#define HCIC_BLE_ENCRYT_KEY_SIZE 16
@@ -1320,6 +1321,15 @@ HCI_API extern BOOLEAN btsnd_hcic_ble_ltk_req_neg_reply (UINT16 handle);
HCI_API extern BOOLEAN btsnd_hcic_ble_read_supported_states (void);
+HCI_API extern BOOLEAN btsnd_hcic_ble_write_host_supported (UINT8 le_host_spt, UINT8 simul_le_host_spt);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_read_host_supported (void);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len,
+ UINT8 payload);
+HCI_API extern BOOLEAN btsnd_hcic_ble_test_end(void);
#endif /* BLE_INCLUDED */
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 618ea8d54..95c44e0a4 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -123,16 +123,6 @@ typedef UINT8 tL2CAP_CHNL_DATA_RATE;
#define L2C_INVALID_PSM(psm) (((psm) & 0x0101) != 0x0001)
#define L2C_IS_VALID_PSM(psm) (((psm) & 0x0101) == 0x0001)
-#if (BLE_INCLUDED == TRUE)
-#define L2CAP_LE_INT_MIN 0x0006
-#define L2CAP_LE_INT_MAX 0x0C80
-#define L2CAP_LE_LATENCY_MAX 500
-#define L2CAP_LE_TIMEOUT_MIN 0x000a
-#define L2CAP_LE_TIMEOUT_MAX 0x0C80
-#define L2CAP_LE_TIMEOUT_DEFAULT 0x07D0
-#endif
-
-
/*****************************************************************************
** Type Definitions
*****************************************************************************/
diff --git a/stack/include/profiles_api.h b/stack/include/profiles_api.h
new file mode 100644
index 000000000..eee0dd834
--- /dev/null
+++ b/stack/include/profiles_api.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef PROFILES_API_H
+#define PROFILES_API_H
+
+#include "bt_target.h"
+#include "btm_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+#define BT_PASS 0 /* Used for general successful function returns */
+
+/*** Port entity passes back 8 bit errors; will use upper byte offset ***/
+#define PORT_ERR_GRP 0x0000 /* base offset for port entity */
+#define GAP_ERR_GRP 0x0100 /* base offset for GAP profile */
+#define SPP_ERR_GRP 0x0200 /* base offset for serial port profile */
+#define HCRP_ERR_GRP 0x0300 /* base offset for HCRP */
+#define HCRPM_ERR_GRP 0x0400 /* base offset for HCRPM */
+
+/* #define HSP2_ERR_GRP 0x0F00 */
+
+/* security level definitions (tBT_SECURITY) */
+#define BT_USE_DEF_SECURITY 0
+#define BT_SEC_MODE_NONE BTM_SEC_MODE_NONE
+#define BT_SEC_MODE_SERVICE BTM_SEC_MODE_SERVICE
+#define BT_SEC_MODE_LINK BTM_SEC_MODE_LINK
+
+/* security mask definitions (tBT_SECURITY) */
+/* The following definitions are OR'd together to form the security requirements */
+#define BT_SEC_IN_AUTHORIZE BTM_SEC_IN_AUTHORIZE /* Inbound call requires authorization */
+#define BT_SEC_IN_AUTHENTICATE BTM_SEC_IN_AUTHENTICATE /* Inbound call requires authentication */
+#define BT_SEC_IN_ENCRYPT BTM_SEC_IN_ENCRYPT /* Inbound call requires encryption */
+#define BT_SEC_OUT_AUTHORIZE BTM_SEC_OUT_AUTHORIZE /* Outbound call requires authorization */
+#define BT_SEC_OUT_AUTHENTICATE BTM_SEC_OUT_AUTHENTICATE /* Outbound call requires authentication */
+#define BT_SEC_OUT_ENCRYPT BTM_SEC_OUT_ENCRYPT /* Outbound call requires encryption */
+
+
+/*****************************************************************************
+** Type Definitions
+*****************************************************************************/
+
+/*
+** Security Definitions
+** This following definitions are used to indicate the security
+** requirements for a service.
+*/
+typedef struct
+{
+ UINT8 level;
+ UINT8 mask;
+} tBT_SECURITY;
+
+#endif /* PROFILES_API_H */
+
diff --git a/stack/include/sdpdefs.h b/stack/include/sdpdefs.h
index c290e03c1..fcd4a5e6f 100644
--- a/stack/include/sdpdefs.h
+++ b/stack/include/sdpdefs.h
@@ -262,10 +262,20 @@
#define UUID_SERVCLASS_CURRENT_TIME 0x1805 /* Link Loss Alert */
#define UUID_SERVCLASS_DST_CHG 0x1806 /* DST Time change */
#define UUID_SERVCLASS_REF_TIME_UPD 0x1807 /* reference time update */
+#define UUID_SERVCLASS_THERMOMETER 0x1809 /* Thermometer UUID */
#define UUID_SERVCLASS_DEVICE_INFO 0x180A /* device info service */
#define UUID_SERVCLASS_NWA 0x180B /* Network availability */
-#define UUID_SERVCLASS_PHALERT 0x180C /* phone alert service */
-#define UUID_SERVCLASS_GLUCOSE 0xC000 /* Glucose Meter Service */
+#define UUID_SERVCLASS_HEART_RATE 0x180D /* Heart Rate service */
+#define UUID_SERVCLASS_PHALERT 0x180E /* phone alert service */
+#define UUID_SERVCLASS_BATTERY 0x180F /* battery service */
+#define UUID_SERVCLASS_BPM 0x1810 /* blood pressure service */
+#define UUID_SERVCLASS_ALERT_NOTIFICATION 0x1811 /* alert notification service */
+#define UUID_SERVCLASS_LE_HID 0x1812 /* HID over LE */
+#define UUID_SERVCLASS_SCAN_PARAM 0x1813 /* Scan Parameter service */
+#define UUID_SERVCLASS_GLUCOSE 0x1808 /* Glucose Meter Service */
+#define UUID_SERVCLASS_RSC 0x1814 /* RUNNERS SPEED AND CADENCE SERVICE */
+#define UUID_SERVCLASS_CSC 0x1816 /* Cycling SPEED AND CADENCE SERVICE */
+
#define UUID_SERVCLASS_TEST_SERVER 0x9000 /* Test Group UUID */
#if (BTM_WBS_INCLUDED == TRUE )
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index bd7b13147..68c9ebff5 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -61,6 +61,7 @@ typedef UINT8 tSMP_EVT;
#define SMP_RSP_TIMEOUT 0x11
#define SMP_DIV_NOT_AVAIL 0x12
#define SMP_FAIL 0x13 /* unspecified failed reason */
+#define SMP_CONN_TOUT 0x14 /* unspecified failed reason */
#define SMP_SUCCESS 0
typedef UINT8 tSMP_STATUS;
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index f464ff34d..0a296c88a 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -48,7 +48,7 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
tL2C_LCB *p_lcb;
/* There can be only one BLE connection request outstanding at a time */
- if (!l2cb.is_ble_connecting)
+ if (btm_ble_get_conn_st() == BLE_DIR_CONN)
{
L2CAP_TRACE_WARNING0 ("L2CA_CancelBleConnectReq - no connection pending");
return(FALSE);
@@ -72,10 +72,8 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
p_lcb->disc_reason = L2CAP_CONN_CANCEL;
l2cu_release_lcb (p_lcb);
}
-
- l2cb.is_ble_connecting = FALSE;
- btm_ble_update_bg_state();
- btm_ble_resume_bg_conn(NULL, TRUE);
+ /* update conn state to IDLE */
+ btm_ble_set_conn_st (BLE_CONN_IDLE);
return(TRUE);
}
@@ -186,10 +184,10 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (rem_bda);
btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
- (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : L2CAP_LE_INT_MIN),
- (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : L2CAP_LE_INT_MAX),
- (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0),
- (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : L2CAP_LE_TIMEOUT_MAX),
+ (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),
+ (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),
+ (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF),
+ (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
0, 0);
}
p_lcb->upd_disabled = UPD_DISABLED;
@@ -250,7 +248,8 @@ UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda)
** Returns void
**
*******************************************************************************/
-void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
+void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
+ UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
tL2C_LCB *p_lcb;
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda);
@@ -260,9 +259,6 @@ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
l2cb.is_ble_connecting = FALSE;
- p_dev_rec->device_type = BT_DEVICE_TYPE_BLE;
- p_dev_rec->ble.ble_addr_type = type;
-
/* See if we have a link control block for the remote device */
p_lcb = l2cu_find_lcb_by_bd_addr (bda);
@@ -302,13 +298,13 @@ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
p_lcb->is_ble_link = TRUE;
/* If there are any preferred connection parameters, set them now */
- if ( (p_dev_rec->conn_params.min_conn_int >= L2CAP_LE_INT_MIN ) &&
- (p_dev_rec->conn_params.min_conn_int <= L2CAP_LE_INT_MAX ) &&
- (p_dev_rec->conn_params.max_conn_int >= L2CAP_LE_INT_MIN ) &&
- (p_dev_rec->conn_params.max_conn_int <= L2CAP_LE_INT_MAX ) &&
- (p_dev_rec->conn_params.slave_latency <= L2CAP_LE_LATENCY_MAX ) &&
- (p_dev_rec->conn_params.supervision_tout >= L2CAP_LE_TIMEOUT_MIN) &&
- (p_dev_rec->conn_params.supervision_tout <= L2CAP_LE_TIMEOUT_MAX) &&
+ if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
+ (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
+ (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
+ (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
+ (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) &&
+ (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
+ (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
((conn_interval < p_dev_rec->conn_params.min_conn_int &&
p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
(conn_interval > p_dev_rec->conn_params.max_conn_int) ||
@@ -393,9 +389,6 @@ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE typ
/* Tell BTM Acl management about the link */
p_dev_rec = btm_find_or_alloc_dev (bda);
- p_dev_rec->device_type = BT_DEVICE_TYPE_BLE;
- p_dev_rec->ble.ble_addr_type = type;
-
btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE);
p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
@@ -476,14 +469,14 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
/* If we are a master, the slave wants to update the parameters */
if (p_lcb->link_role == HCI_ROLE_MASTER)
{
- if (min_interval < L2CAP_LE_INT_MIN || min_interval > L2CAP_LE_INT_MAX ||
- max_interval < L2CAP_LE_INT_MIN || max_interval > L2CAP_LE_INT_MAX ||
- latency > L2CAP_LE_LATENCY_MAX ||
+ if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
+ max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
+ latency > BTM_BLE_CONN_LATENCY_MAX ||
/*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
- timeout < L2CAP_LE_TIMEOUT_MIN || timeout > L2CAP_LE_TIMEOUT_MAX ||
+ timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
max_interval < min_interval)
{
- result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
+ l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
}
else
{
@@ -526,58 +519,94 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
/*******************************************************************************
**
-** Function l2cble_create_conn
+** Function l2cble_init_direct_conn
**
-** Description This function initiates an acl connection via HCI
+** Description This function is to initate a direct connection
**
-** Returns TRUE if successful, FALSE if connection not started.
+** Returns TRUE connection initiated, FALSE otherwise.
**
*******************************************************************************/
-BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
+BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT16 scan_int, scan_win;
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+ UINT16 scan_int, scan_win;
+ BD_ADDR init_addr;
+ UINT8 init_addr_type = BLE_ADDR_PUBLIC,
+ own_addr_type = BLE_ADDR_PUBLIC;
/* There can be only one BLE connection request outstanding at a time */
- if (l2cb.is_ble_connecting)
+ if (p_dev_rec == NULL)
{
- L2CAP_TRACE_WARNING0 ("L2CAP - LE - cannot start new connection, already connecting");
+ BTM_TRACE_WARNING0 ("unknown device, can not initate connection");
return(FALSE);
}
- p_lcb->link_state = LST_CONNECTING;
- l2cb.is_ble_connecting = TRUE;
+ scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
+ scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
- memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
- btm_ble_suspend_bg_conn();
-
- scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? L2CAP_LE_INT_MIN : p_cb->scan_int;
- scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? L2CAP_LE_INT_MIN : p_cb->scan_win;
+ init_addr_type = p_lcb->ble_addr_type;
+ memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
scan_win, /* UINT16 scan_win */
FALSE, /* UINT8 white_list */
- p_lcb->ble_addr_type, /* UINT8 addr_type_peer */
- p_lcb->remote_bd_addr, /* BD_ADDR bda_peer */
+ p_lcb->ble_addr_type, /* UINT8 addr_type_peer */
+ p_lcb->remote_bd_addr, /* BD_ADDR bda_peer */
BLE_ADDR_PUBLIC, /* UINT8 addr_type_own */
- (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : L2CAP_LE_INT_MIN), /* UINT16 conn_int_min */
- (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : L2CAP_LE_INT_MIN), /* UINT16 conn_int_max */
+ (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN), /* UINT16 conn_int_min */
+ (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MIN), /* UINT16 conn_int_max */
(UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency */
- (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : L2CAP_LE_TIMEOUT_MAX), /* UINT16 conn_timeout */
+ (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_SUP_TOUT_DEF), /* UINT16 conn_timeout */
0, /* UINT16 min_len */
0)) /* UINT16 max_len */
{
- /* No buffer for connection request ? */
- l2cb.is_ble_connecting = FALSE;
- p_lcb->disc_reason = L2CAP_CONN_NO_RESOURCES;
l2cu_release_lcb (p_lcb);
- return(FALSE);
+ L2CAP_TRACE_ERROR0("initate direct connection fail, no resources");
+ return (FALSE);
}
else
+ {
+ p_lcb->link_state = LST_CONNECTING;
+ memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
+ btm_ble_set_conn_st (BLE_DIR_CONN);
- return(TRUE);
+ return (TRUE);
+ }
+}
+
+/*******************************************************************************
+**
+** Function l2cble_create_conn
+**
+** Description This function initiates an acl connection via HCI
+**
+** Returns TRUE if successful, FALSE if connection not started.
+**
+*******************************************************************************/
+BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
+{
+ tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
+ BOOLEAN rt = FALSE;
+
+ /* There can be only one BLE connection request outstanding at a time */
+ if (conn_st == BLE_CONN_IDLE)
+ {
+ rt = l2cble_init_direct_conn(p_lcb);
+ }
+ else
+ {
+ L2CAP_TRACE_WARNING1 ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
+
+ btm_ble_enqueue_direct_conn_req(p_lcb);
+
+ if (conn_st == BLE_BG_CONN)
+ btm_ble_suspend_bg_conn();
+
+ rt = TRUE;
+ }
+ return rt;
}
/*******************************************************************************
diff --git a/stack/l2cap/l2c_fcr.c b/stack/l2cap/l2c_fcr.c
index ff018c5cb..9685f774b 100644
--- a/stack/l2cap/l2c_fcr.c
+++ b/stack/l2cap/l2c_fcr.c
@@ -1486,8 +1486,12 @@ static BOOLEAN do_sar_reassembly (tL2C_CCB *p_ccb, BT_HDR *p_buf, UINT16 ctrl_wo
else if (p_buf != NULL)
{
#if (L2CAP_NUM_FIXED_CHNLS > 0)
- if (p_ccb->local_cid < L2CAP_BASE_APPL_CID)
- (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_ccb->p_lcb->remote_bd_addr, p_buf);
+ if (p_ccb->local_cid < L2CAP_BASE_APPL_CID &&
+ (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL && p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL))
+ {
+ if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
+ (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_ccb->p_lcb->remote_bd_addr, p_buf);
+ }
else
#endif
l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_buf);
@@ -1622,7 +1626,7 @@ BT_HDR *l2c_fcr_get_next_xmit_sdu_seg (tL2C_CCB *p_ccb, UINT16 max_packet_length
BOOLEAN first_seg = FALSE, /* The segment is the first part of data */
mid_seg = FALSE, /* The segment is the middle part of data */
last_seg = FALSE; /* The segment is the last part of data */
- UINT16 sdu_len;
+ UINT16 sdu_len = 0;
BT_HDR *p_buf, *p_xmit;
UINT8 *p;
UINT16 max_pdu = p_ccb->tx_mps /* Needed? - L2CAP_MAX_HEADER_FCS*/;
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 609c8251e..f4eb0086a 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -761,6 +761,7 @@ extern BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb);
extern void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len);
extern void l2cble_conn_comp (UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout);
+extern BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb);
#endif
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index 401084a93..4bb2be7e2 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -133,7 +133,10 @@ BOOLEAN l2c_link_hci_conn_req (BD_ADDR bd_addr)
}
else
{
- L2CAP_TRACE_ERROR0 ("L2CAP got conn_req while connected");
+ L2CAP_TRACE_ERROR1("L2CAP got conn_req while connected (state:%d). Reject it",
+ p_lcb->link_state);
+ /* Reject the connection with ACL Connection Already exist reason */
+ btsnd_hcic_reject_conn (bd_addr, HCI_ERR_CONNECTION_EXISTS);
}
return (FALSE);
}
@@ -202,6 +205,8 @@ BOOLEAN l2c_link_hci_conn_comp (UINT8 status, UINT16 handle, BD_ADDR p_bda)
else
btm_acl_created (ci.bd_addr, NULL, NULL, handle, p_lcb->link_role, FALSE);
+ BTM_SetLinkSuperTout (ci.bd_addr, btm_cb.btm_def_link_super_tout);
+
/* If dedicated bonding do not process any further */
if (p_lcb->is_bonding)
{
@@ -677,7 +682,7 @@ void l2c_link_adjust_allocation (void)
UINT16 controller_xmit_quota = l2cb.num_lm_acl_bufs;
UINT16 high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
- /* If no links active, nothing to do. */
+ /* If no links active, reset buffer quotas and controller buffers */
if (l2cb.num_links_active == 0)
{
l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
@@ -1027,7 +1032,6 @@ void l2c_pin_code_request (BD_ADDR bd_addr)
BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb)
{
tBTM_PM_MODE mode;
- tBTM_PM_PWR_MD pm;
tL2C_CCB *p_ccb;
BOOLEAN need_to_active = FALSE;
@@ -1054,29 +1058,10 @@ BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb)
/* check power mode */
if (BTM_ReadPowerMode(p_lcb->remote_bd_addr, &mode) == BTM_SUCCESS)
{
- /*
- if ( mode == BTM_PM_MD_PARK )
- {
- L2CAP_TRACE_DEBUG1 ("LCB(0x%x) is in park mode", p_lcb->handle);
-// Coverity:
-// FALSE-POSITIVE error from Coverity test tool. Please do NOT remove following comment.
-// coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-
- memset((void*)&pm, 0, sizeof(pm));
- pm.mode = BTM_PM_MD_ACTIVE;
- BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_lcb->remote_bd_addr, &pm);
- btu_start_timer (&p_lcb->timer_entry,
- BTU_TTYPE_L2CAP_LINK, L2CAP_WAIT_UNPARK_TOUT);
- return TRUE;
- }
- */
if ( mode == BTM_PM_STS_PENDING )
{
L2CAP_TRACE_DEBUG1 ("LCB(0x%x) is in PM pending state", p_lcb->handle);
- btu_start_timer (&p_lcb->timer_entry,
- BTU_TTYPE_L2CAP_LINK, L2CAP_WAIT_UNPARK_TOUT);
return TRUE;
}
}
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index 6c29cff31..49dd8113e 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -50,7 +50,7 @@ tL2C_CB l2cb;
/* Temporary - until l2cap implements group management */
#if (TCS_BCST_SETUP_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
extern void tcs_proc_bcst_msg( BD_ADDR addr, BT_HDR *p_msg ) ;
-
+#endif
/*******************************************************************************
**
** Function l2c_bcst_msg
@@ -104,7 +104,7 @@ void l2c_bcst_msg( BT_HDR *p_buf, UINT16 psm )
HCI_ACL_DATA_TO_LOWER (p_buf);
}
}
-#endif
+
/*******************************************************************************
**
@@ -680,31 +680,10 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
break;
case L2CAP_CMD_ECHO_REQ:
-
-#if (L2CAP_ENHANCED_FEATURES != 0)
- if (!l2cu_check_feature_req (p_lcb, id, p, cmd_len))
- {
- if (cmd_len < (btu_cb.hcit_acl_pkt_size - L2CAP_PKT_OVERHEAD
- - L2CAP_CMD_OVERHEAD
- - L2CAP_ECHO_RSP_LEN
- - HCI_DATA_PREAMBLE_SIZE))
- {
- l2cu_send_peer_echo_rsp (p_lcb, id, p, cmd_len);
- }
- else
- {
- l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0);
- }
- }
-#else
l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0);
-#endif
break;
case L2CAP_CMD_ECHO_RSP:
-#if (L2CAP_ENHANCED_FEATURES != 0)
- l2cu_check_feature_rsp (p_lcb, id, p, cmd_len);
-#endif
if (p_lcb->p_echo_rsp_cb)
{
tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb;
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index fd618ed6a..581930f1c 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -307,13 +307,6 @@ BT_HDR *l2cu_build_header (tL2C_LCB *p_lcb, UINT16 len, UINT8 cmd, UINT8 id)
*******************************************************************************/
void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask)
{
-#if (L2CAP_ENHANCED_FEATURES != 0)
- if ((adj_mask & L2CAP_ADJ_BRCM_ID) && p_lcb->id == L2CAP_FEATURE_REQ_ID)
- {
- p_lcb->id++;
- }
-#endif
-
if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id)
{
p_lcb->id++;
@@ -1546,6 +1539,9 @@ void l2cu_release_ccb (tL2C_CCB *p_ccb)
{
btm_sec_clr_service_by_psm(p_rcb->psm);
}
+
+ btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
+
/* Stop the timer */
btu_stop_timer (&p_ccb->timer_entry);
@@ -2056,6 +2052,9 @@ void l2cu_device_reset (void)
l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) -1);
}
}
+#if (BLE_INCLUDED == TRUE)
+ l2cb.is_ble_connecting = FALSE;
+#endif
}
#if (TCS_WUG_MEMBER_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
@@ -2391,153 +2390,6 @@ BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_af
return(TRUE);
}
-#if (L2CAP_ENHANCED_FEATURES != 0)
-/*******************************************************************************
-**
-** Function l2cu_send_feature_req
-**
-** Description Called at connection establishment by the originator
-** of the connection to send an L2CAP Echo request message
-** to the peer to determine if he supports Widcomm proprietary
-** features.
-**
-** Returns void
-**
-*******************************************************************************/
-void l2cu_send_feature_req (tL2C_CCB *p_ccb)
-{
- UINT8 saved_id;
- UINT8 buff[100], *p = buff;
-
- UINT8_TO_STREAM (p, 'R');
- UINT8_TO_STREAM (p, 'Q');
-
- UINT8_TO_STREAM (p, 'r');
- UINT8_TO_STREAM (p, 'q');
-
- /* save current ID to be restored after feature request */
- saved_id = p_ccb->p_lcb->id;
-
- /* Set appropriate ID */
- p_ccb->p_lcb->id = L2CAP_FEATURE_REQ_ID - 1;
-
- l2cu_send_peer_echo_req (p_ccb->p_lcb, buff, (UINT16)(p - buff));
-
- /* packet has been built so we can restore the control block id */
- p_ccb->p_lcb->id = saved_id;
-}
-
-
-
-/*******************************************************************************
-**
-** Function l2cu_check_feature_req
-**
-** Description Called when an echo request is received to check if the
-** other side is doing a proprietary feature request. If so,
-** extract the values and reply with a features response.
-**
-** Returns void
-**
-*******************************************************************************/
-BOOLEAN l2cu_check_feature_req (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
-{
- UINT8 buff[100];
- UINT8 *p_out = buff;
- UINT8 *p_end = p_data + data_len - 2;
- UINT8 pe_type, pe_len;
-
- if ((data_len <= 4)
- || (p_data[0] != 'R')
- || (p_data[1] != 'Q')
- || (p_data[data_len - 2] != 'r')
- || (p_data[data_len - 1] != 'q')
- || (id != L2CAP_FEATURE_REQ_ID))
- return (FALSE);
-
- /* Skip leading frame characters */
- p_data += 2;
-
- UINT8_TO_STREAM (p_out, 'R');
- UINT8_TO_STREAM (p_out, 'S');
-
- while (p_data < p_end)
- {
- pe_type = *p_data++;
- pe_len = *p_data++;
-
- switch (pe_type)
- {
- default:
- p_data += pe_len;
- break;
- }
- }
-
- /* Sanity check - we should not overrun the input */
- if (p_data != p_end)
- {
- L2CAP_TRACE_ERROR0 ("L2CAP - badly formatted feature req");
- return (FALSE);
- }
-
- UINT8_TO_STREAM (p_out, 'r');
- UINT8_TO_STREAM (p_out, 's');
-
- l2cu_send_peer_echo_rsp (p_lcb, L2CAP_FEATURE_RSP_ID, buff, (UINT16)(p_out - buff));
-
- return (TRUE);
-}
-
-/*******************************************************************************
-**
-** Function l2cu_check_feature_rsp
-**
-** Description Called when an echo response is received to check if the
-** other side is suports proprietary feature(s). If so,
-** extract the values.
-**
-** Returns void
-**
-*******************************************************************************/
-void l2cu_check_feature_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
-{
- UINT8 *p_end = p_data + data_len - 2;
-
- if ((data_len <= 4)
- || (p_data[0] != 'R')
- || (p_data[1] != 'S')
- || (p_data[data_len - 2] != 'r')
- || (p_data[data_len - 1] != 's')
- || (id != L2CAP_FEATURE_RSP_ID))
- {
- return;
- }
-
- /* Skip leading frame characters */
- p_data += 2;
-
- while (p_data < p_end)
- {
- UINT8 pe_id = *p_data++;
- UINT8 pe_len = *p_data++;
-
- switch (pe_id)
- {
- default:
- p_data += pe_len;
- break;
- }
- }
-
- /* Sanity check - we should not overrun the input */
- if (p_data != p_end)
- {
- L2CAP_TRACE_ERROR0 ("L2CAP - badly formatted feature rsp");
- }
-}
-#endif /* L2CAP_ENHANCED_FEATURES != 0 */
-
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
/******************************************************************************
**
@@ -2697,6 +2549,8 @@ BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR
if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL)
return (FALSE);
+ btu_stop_timer(&p_lcb->timer_entry);
+
/* Set CID for the connection */
p_ccb->local_cid = fixed_cid;
p_ccb->remote_cid = fixed_cid;
@@ -2836,11 +2690,15 @@ void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
(*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, reason);
}
- else if (p_lcb->p_fixed_ccbs[xx])
+ else
{
(*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason);
- l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
- p_lcb->p_fixed_ccbs[xx] = NULL;
+
+ if (p_lcb->p_fixed_ccbs[xx])
+ {
+ l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
+ p_lcb->p_fixed_ccbs[xx] = NULL;
+ }
}
}
}
@@ -3219,6 +3077,11 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
if (p_ccb->xmit_hold_q.count != 0)
{
p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
+ if(NULL == p_buf)
+ {
+ L2CAP_TRACE_ERROR0("l2cu_get_buffer_to_send: No data to be sent");
+ return (NULL);
+ }
l2cu_set_acl_hci_header (p_buf, p_ccb);
return (p_buf);
}
@@ -3245,6 +3108,11 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
else
{
p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
+ if(NULL == p_buf)
+ {
+ L2CAP_TRACE_ERROR0("l2cu_get_buffer_to_send() #2: No data to be sent");
+ return (NULL);
+ }
}
if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) )
diff --git a/stack/mcap/mca_int.h b/stack/mcap/mca_int.h
index 2563f7fb8..54ff0c039 100644
--- a/stack/mcap/mca_int.h
+++ b/stack/mcap/mca_int.h
@@ -322,9 +322,18 @@ extern void mca_process_timeout(TIMER_LIST_ENT *p_tle);
extern void mca_stop_timer(tMCA_CCB *p_ccb);
/* l2c functions */
+extern UINT16 mca_l2c_open_req(BD_ADDR bd_addr, UINT16 PSM, const tMCA_CHNL_CFG *p_chnl_cfg);
+
+/* callback function declarations */
extern void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
extern void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-extern UINT16 mca_l2c_open_req(BD_ADDR bd_addr, UINT16 PSM, const tMCA_CHNL_CFG *p_chnl_cfg);
+extern void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
+extern void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+extern void mca_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+extern void mca_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
+extern void mca_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
+extern void mca_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
+extern void mca_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
/*****************************************************************************
** global data
diff --git a/stack/mcap/mca_l2c.c b/stack/mcap/mca_l2c.c
index f8a48bfc4..23d56f5d6 100644
--- a/stack/mcap/mca_l2c.c
+++ b/stack/mcap/mca_l2c.c
@@ -30,19 +30,10 @@
#include "mca_defs.h"
#include "mca_int.h"
-/* callback function declarations */
-void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
-void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
-void mca_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
-void mca_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
-void mca_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
-void mca_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
-void mca_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
/* L2CAP callback function structure */
-const tL2CAP_APPL_INFO mca_l2c_int_appl = {
+const tL2CAP_APPL_INFO mca_l2c_int_appl =
+{
NULL,
mca_l2c_connect_cfm_cback,
NULL,
@@ -52,11 +43,13 @@ const tL2CAP_APPL_INFO mca_l2c_int_appl = {
mca_l2c_disconnect_cfm_cback,
NULL,
mca_l2c_data_ind_cback,
- mca_l2c_congestion_ind_cback
+ mca_l2c_congestion_ind_cback,
+ NULL
};
/* Control channel eL2CAP default options */
-const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def = {
+const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def =
+{
L2CAP_FCR_ERTM_MODE, /* Mandatory for MCAP */
MCA_FCR_OPT_TX_WINDOW_SIZE, /* Tx window size */
MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
diff --git a/stack/mcap/mca_main.c b/stack/mcap/mca_main.c
index 2e05d5ee4..d09319df5 100644
--- a/stack/mcap/mca_main.c
+++ b/stack/mcap/mca_main.c
@@ -563,6 +563,7 @@ void mca_rcb_dealloc(tMCA_HANDLE handle)
if (done)
{
memset (p_rcb, 0, sizeof(tMCA_RCB));
+ MCA_TRACE_DEBUG1("Reset MCA_RCB index=%d",handle);
}
}
}
diff --git a/stack/sdp/sdp_db.c b/stack/sdp/sdp_db.c
index b5ab31a78..318a8cc24 100644
--- a/stack/sdp/sdp_db.c
+++ b/stack/sdp/sdp_db.c
@@ -538,11 +538,18 @@ BOOLEAN SDP_AddSequence (UINT32 handle, UINT16 attr_id, UINT16 num_elem,
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
+ UINT8 *p_buff;
UINT8 *p;
UINT8 *p_head;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddSequence cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
- p = buff;
/* First, build the sequence */
for (xx = 0; xx < num_elem; xx++)
{
@@ -572,14 +579,15 @@ BOOLEAN SDP_AddSequence (UINT32 handle, UINT16 attr_id, UINT16 num_elem,
ARRAY_TO_BE_STREAM (p, p_val[xx], len[xx]);
- if (p - buff > SDP_MAX_ATTR_LEN)
+ if (p - p_buff > SDP_MAX_ATTR_LEN)
{
/* go back to before we add this element */
p = p_head;
- if(p_head == buff)
+ if(p_head == p_buff)
{
/* the first element exceed the max length */
SDP_TRACE_ERROR0 ("SDP_AddSequence - too long(attribute is not added)!!");
+ GKI_freebuf(p_buff);
return FALSE;
}
else
@@ -587,9 +595,9 @@ BOOLEAN SDP_AddSequence (UINT32 handle, UINT16 attr_id, UINT16 num_elem,
break;
}
}
-
- return (SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,
- (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -613,9 +621,17 @@ BOOLEAN SDP_AddUuidSequence (UINT32 handle, UINT16 attr_id, UINT16 num_uuids,
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- UINT8 *p = buff;
+ UINT8 *p_buff;
+ UINT8 *p;
INT32 max_len = SDP_MAX_ATTR_LEN -3;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddUuidSequence cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
/* First, build the sequence */
for (xx = 0; xx < num_uuids ; xx++, p_uuids++)
@@ -623,15 +639,16 @@ BOOLEAN SDP_AddUuidSequence (UINT32 handle, UINT16 attr_id, UINT16 num_uuids,
UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
UINT16_TO_BE_STREAM (p, *p_uuids);
- if((p - buff) > max_len)
+ if((p - p_buff) > max_len)
{
SDP_TRACE_WARNING2 ("SDP_AddUuidSequence - too long, add %d uuids of %d", xx, num_uuids);
break;
}
}
- return (SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,
- (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -653,13 +670,20 @@ BOOLEAN SDP_AddProtocolList (UINT32 handle, UINT16 num_elem,
tSDP_PROTOCOL_ELEM *p_elem_list)
{
#if SDP_SERVER_ENABLED == TRUE
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- int offset;
+ UINT8 *p_buff;
+ int offset;
+ BOOLEAN result;
- offset = sdp_compose_proto_list(buff, num_elem, p_elem_list);
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddProtocolList cannot get a buffer!");
+ return (FALSE);
+ }
- return (SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, buff));
+ offset = sdp_compose_proto_list(p_buff, num_elem, p_elem_list);
+ result = SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -683,10 +707,18 @@ BOOLEAN SDP_AddAdditionProtoLists (UINT32 handle, UINT16 num_elem,
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- UINT8 *p = buff;
- UINT8 *p_len;
- int offset;
+ UINT8 *p_buff;
+ UINT8 *p;
+ UINT8 *p_len;
+ int offset;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddAdditionProtoLists cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
/* for each ProtocolDescriptorList */
for (xx = 0; xx < num_elem; xx++, p_proto_list++)
@@ -700,9 +732,11 @@ BOOLEAN SDP_AddAdditionProtoLists (UINT32 handle, UINT16 num_elem,
*p_len = (UINT8)(p - p_len - 1);
}
+ result = SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,DATA_ELE_SEQ_DESC_TYPE,
+ (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
- return (SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -724,8 +758,16 @@ BOOLEAN SDP_AddProfileDescriptorList (UINT32 handle, UINT16 profile_uuid,
UINT16 version)
{
#if SDP_SERVER_ENABLED == TRUE
- UINT8 buff[SDP_MAX_ATTR_LEN];
- UINT8 *p = &buff[2];
+ UINT8 *p_buff;
+ UINT8 *p;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddProfileDescriptorList cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff+2;
/* First, build the profile descriptor list. This consists of a data element sequence. */
/* The sequence consists of profile's UUID and version number */
@@ -736,11 +778,13 @@ BOOLEAN SDP_AddProfileDescriptorList (UINT32 handle, UINT16 profile_uuid,
UINT16_TO_BE_STREAM (p, version);
/* Add in type and length fields */
- buff[0] = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
- buff[1] = (UINT8) (p - &buff[2]);
+ *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+ *(p_buff+1) = (UINT8) (p - (p_buff+2));
+
+ result = SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
- return (SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -763,8 +807,16 @@ BOOLEAN SDP_AddLanguageBaseAttrIDList (UINT32 handle, UINT16 lang,
UINT16 char_enc, UINT16 base_id)
{
#if SDP_SERVER_ENABLED == TRUE
- UINT8 buff[SDP_MAX_ATTR_LEN];
- UINT8 *p = buff;
+ UINT8 *p_buff;
+ UINT8 *p;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddLanguageBaseAttrIDList cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
/* First, build the language base descriptor list. This consists of a data */
/* element sequence. The sequence consists of 9 bytes (3 UINt16 fields) */
@@ -777,8 +829,10 @@ BOOLEAN SDP_AddLanguageBaseAttrIDList (UINT32 handle, UINT16 lang,
UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
UINT16_TO_BE_STREAM (p, base_id);
- return (SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
+ (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -802,8 +856,16 @@ BOOLEAN SDP_AddServiceClassIdList (UINT32 handle, UINT16 num_services,
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- UINT8 *p = buff;
+ UINT8 *p_buff;
+ UINT8 *p;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddServiceClassIdList cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
for (xx = 0; xx < num_services; xx++, p_service_uuids++)
{
@@ -811,8 +873,10 @@ BOOLEAN SDP_AddServiceClassIdList (UINT32 handle, UINT16 num_services,
UINT16_TO_BE_STREAM (p, *p_service_uuids);
}
- return (SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
+ (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
diff --git a/stack/sdp/sdp_server.c b/stack/sdp/sdp_server.c
index 5736b8dea..342d93e7a 100644
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -173,7 +173,7 @@ static void process_service_search (tCONN_CB *p_ccb, UINT16 trans_num,
tSDP_UUID_SEQ uid_seq;
UINT8 *p_rsp, *p_rsp_start, *p_rsp_param_len;
UINT16 rsp_param_len, num_rsp_handles, xx;
- UINT32 rsp_handles[SDP_MAX_RECORDS];
+ UINT32 rsp_handles[SDP_MAX_RECORDS] = {0};
tSDP_RECORD *p_rec = NULL;
BT_HDR *p_buf;
BOOLEAN is_cont = FALSE;
@@ -430,7 +430,7 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
}
else if (rem_len < attr_len) /* Not enough space for attr... so add partially */
{
- if (attr_len >= MAX_ATTR_LEN)
+ if (attr_len >= SDP_MAX_ATTR_LEN)
{
SDP_TRACE_ERROR2("SDP attr too big: max_list_len=%d,attr_len=%d", max_list_len, attr_len);
sdpu_build_n_send_error (p_ccb, trans_num, SDP_NO_RESOURCES, NULL);
@@ -697,7 +697,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
}
else if (rem_len < attr_len) /* Not enough space for attr... so add partially */
{
- if (attr_len >= MAX_ATTR_LEN)
+ if (attr_len >= SDP_MAX_ATTR_LEN)
{
SDP_TRACE_ERROR2("SDP attr too big: max_list_len=%d,attr_len=%d", max_list_len, attr_len);
sdpu_build_n_send_error (p_ccb, trans_num, SDP_NO_RESOURCES, NULL);
diff --git a/stack/sdp/sdp_utils.c b/stack/sdp/sdp_utils.c
index cda0570d9..842e75784 100644
--- a/stack/sdp/sdp_utils.c
+++ b/stack/sdp/sdp_utils.c
@@ -884,7 +884,7 @@ UINT16 sdpu_get_attrib_seq_len(tSDP_RECORD *p_rec, tSDP_ATTR_SEQ *attr_seq)
UINT16 len1 = 0;
UINT16 xx;
BOOLEAN is_range = FALSE;
- UINT16 start_id, end_id;
+ UINT16 start_id=0, end_id=0;
for (xx = 0; xx < attr_seq->num_attr; xx++)
{
@@ -999,21 +999,29 @@ UINT16 sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE *p_attr)
*******************************************************************************/
UINT8 *sdpu_build_partial_attrib_entry (UINT8 *p_out, tSDP_ATTRIBUTE *p_attr, UINT16 len, UINT16 *offset)
{
- UINT8 tmp_attr[MAX_ATTR_LEN];
- UINT8 *p_tmp_attr = &tmp_attr[0];
+ UINT8 *p_attr_buff;
+ UINT8 *p_tmp_attr;
size_t len_to_copy;
UINT16 attr_len;
+ if ((p_attr_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN )) == NULL)
+ {
+ SDP_TRACE_ERROR0("sdpu_build_partial_attrib_entry cannot get a buffer!");
+ return NULL;
+ }
+ p_tmp_attr = p_attr_buff;
+
sdpu_build_attrib_entry(p_tmp_attr, p_attr);
attr_len = sdpu_get_attrib_entry_len(p_attr);
len_to_copy = ((attr_len - *offset) < len) ? (attr_len - *offset): len;
- memcpy(p_out, &tmp_attr[*offset], len_to_copy);
+ memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
p_out = &p_out[len_to_copy];
*offset += len_to_copy;
+ GKI_freebuf(p_attr_buff);
return p_out;
}
diff --git a/stack/smp/aes.c b/stack/smp/aes.c
new file mode 100644
index 000000000..1028d5b06
--- /dev/null
+++ b/stack/smp/aes.c
@@ -0,0 +1,926 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state (there are options to use 32-bit types if available).
+
+ The combination of mix columns and byte substitution used here is based on
+ that developed by Karl Malbrain. His contribution is acknowledged.
+ */
+
+/* define if you have a fast memcpy function on your system */
+#if 1
+# define HAVE_MEMCPY
+# include <string.h>
+#if 0
+# if defined( _MSC_VER )
+# include <intrin.h>
+# pragma intrinsic( memcpy )
+# endif
+#endif
+#endif
+
+#include <stdlib.h>
+
+/* define if you have fast 32-bit types on your system */
+#if 1
+# define HAVE_UINT_32T
+#endif
+
+/* define if you don't want any tables */
+#if 1
+# define USE_TABLES
+#endif
+
+/* On Intel Core 2 duo VERSION_1 is faster */
+
+/* alternative versions (test for performance on your system) */
+#if 1
+# define VERSION_1
+#endif
+
+#include "aes.h"
+
+#if defined( HAVE_UINT_32T )
+ typedef unsigned long uint_32t;
+#endif
+
+/* functions for finite field multiplication in the AES Galois field */
+
+#define WPOLY 0x011b
+#define BPOLY 0x1b
+#define DPOLY 0x008d
+
+#define f1(x) (x)
+#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
+#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
+#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \
+ ^ (((x >> 5) & 4) * WPOLY))
+#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
+
+#define f3(x) (f2(x) ^ x)
+#define f9(x) (f8(x) ^ x)
+#define fb(x) (f8(x) ^ f2(x) ^ x)
+#define fd(x) (f8(x) ^ f4(x) ^ x)
+#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
+
+#if defined( USE_TABLES )
+
+#define sb_data(w) { /* S Box data values */ \
+ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+ w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+ w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+ w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+ w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+ w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+ w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+ w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+ w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+ w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+ w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+ w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+ w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+ w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+ w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+ w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+ w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+ w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+ w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+ w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+ w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+ w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+ w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+ w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+ w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+ w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+ w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+ w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
+
+#define isb_data(w) { /* inverse S Box data values */ \
+ w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
+ w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
+ w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
+ w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
+ w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
+ w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
+ w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
+ w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
+ w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
+ w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
+ w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
+ w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
+ w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
+ w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
+ w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
+ w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
+ w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
+ w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
+ w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
+ w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
+ w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
+ w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
+ w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
+ w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
+ w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
+ w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
+ w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
+ w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
+ w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
+ w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
+ w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
+ w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
+
+#define mm_data(w) { /* basic data for forming finite field tables */ \
+ w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
+ w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
+ w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
+ w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
+ w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
+ w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
+ w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
+ w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
+ w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
+ w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
+ w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
+ w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
+ w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
+ w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
+ w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
+ w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
+ w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
+ w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
+ w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
+ w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
+ w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
+ w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
+ w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
+ w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
+ w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
+ w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
+ w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
+ w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
+ w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
+ w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
+ w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
+ w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
+
+static const uint_8t sbox[256] = sb_data(f1);
+static const uint_8t isbox[256] = isb_data(f1);
+
+static const uint_8t gfm2_sbox[256] = sb_data(f2);
+static const uint_8t gfm3_sbox[256] = sb_data(f3);
+
+static const uint_8t gfmul_9[256] = mm_data(f9);
+static const uint_8t gfmul_b[256] = mm_data(fb);
+static const uint_8t gfmul_d[256] = mm_data(fd);
+static const uint_8t gfmul_e[256] = mm_data(fe);
+
+#define s_box(x) sbox[(x)]
+#define is_box(x) isbox[(x)]
+#define gfm2_sb(x) gfm2_sbox[(x)]
+#define gfm3_sb(x) gfm3_sbox[(x)]
+#define gfm_9(x) gfmul_9[(x)]
+#define gfm_b(x) gfmul_b[(x)]
+#define gfm_d(x) gfmul_d[(x)]
+#define gfm_e(x) gfmul_e[(x)]
+
+#else
+
+/* this is the high bit of x right shifted by 1 */
+/* position. Since the starting polynomial has */
+/* 9 bits (0x11b), this right shift keeps the */
+/* values of all top bits within a byte */
+
+static uint_8t hibit(const uint_8t x)
+{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2));
+
+ r |= (r >> 2);
+ r |= (r >> 4);
+ return (r + 1) >> 1;
+}
+
+/* return the inverse of the finite field element x */
+
+static uint_8t gf_inv(const uint_8t x)
+{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+ if(x < 2)
+ return x;
+
+ for( ; ; )
+ {
+ if(n1)
+ while(n2 >= n1) /* divide polynomial p2 by p1 */
+ {
+ n2 /= n1; /* shift smaller polynomial left */
+ p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
+ v2 ^= (v1 * n2); /* shift accumulated value and */
+ n2 = hibit(p2); /* add into result */
+ }
+ else
+ return v1;
+
+ if(n2) /* repeat with values swapped */
+ while(n1 >= n2)
+ {
+ n1 /= n2;
+ p1 ^= p2 * n1;
+ v1 ^= v2 * n1;
+ n1 = hibit(p1);
+ }
+ else
+ return v2;
+ }
+}
+
+/* The forward and inverse affine transformations used in the S-box */
+uint_8t fwd_affine(const uint_8t x)
+{
+#if defined( HAVE_UINT_32T )
+ uint_32t w = x;
+ w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
+ return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+ return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
+ ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
+#endif
+}
+
+uint_8t inv_affine(const uint_8t x)
+{
+#if defined( HAVE_UINT_32T )
+ uint_32t w = x;
+ w = (w << 1) ^ (w << 3) ^ (w << 6);
+ return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+ return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6)
+ ^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
+#endif
+}
+
+#define s_box(x) fwd_affine(gf_inv(x))
+#define is_box(x) gf_inv(inv_affine(x))
+#define gfm2_sb(x) f2(s_box(x))
+#define gfm3_sb(x) f3(s_box(x))
+#define gfm_9(x) f9(x)
+#define gfm_b(x) fb(x)
+#define gfm_d(x) fd(x)
+#define gfm_e(x) fe(x)
+
+#endif
+
+#if defined( HAVE_MEMCPY )
+# define block_copy_nn(d, s, l) memcpy(d, s, l)
+# define block_copy(d, s) memcpy(d, s, N_BLOCK)
+#else
+# define block_copy_nn(d, s, l) copy_block_nn(d, s, l)
+# define block_copy(d, s) copy_block(d, s)
+#endif
+
+#if !defined( HAVE_MEMCPY )
+static void copy_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+ ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0];
+ ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1];
+ ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2];
+ ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3];
+#else
+ ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0];
+ ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1];
+ ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2];
+ ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3];
+ ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4];
+ ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5];
+ ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6];
+ ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7];
+ ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8];
+ ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9];
+ ((uint_8t*)d)[10] = ((uint_8t*)s)[10];
+ ((uint_8t*)d)[11] = ((uint_8t*)s)[11];
+ ((uint_8t*)d)[12] = ((uint_8t*)s)[12];
+ ((uint_8t*)d)[13] = ((uint_8t*)s)[13];
+ ((uint_8t*)d)[14] = ((uint_8t*)s)[14];
+ ((uint_8t*)d)[15] = ((uint_8t*)s)[15];
+#endif
+}
+
+static void copy_block_nn( void * d, const void *s, uint_8t nn )
+{
+ while( nn-- )
+ *((uint_8t*)d)++ = *((uint_8t*)s)++;
+}
+#endif
+
+static void xor_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+ ((uint_32t*)d)[ 0] ^= ((uint_32t*)s)[ 0];
+ ((uint_32t*)d)[ 1] ^= ((uint_32t*)s)[ 1];
+ ((uint_32t*)d)[ 2] ^= ((uint_32t*)s)[ 2];
+ ((uint_32t*)d)[ 3] ^= ((uint_32t*)s)[ 3];
+#else
+ ((uint_8t*)d)[ 0] ^= ((uint_8t*)s)[ 0];
+ ((uint_8t*)d)[ 1] ^= ((uint_8t*)s)[ 1];
+ ((uint_8t*)d)[ 2] ^= ((uint_8t*)s)[ 2];
+ ((uint_8t*)d)[ 3] ^= ((uint_8t*)s)[ 3];
+ ((uint_8t*)d)[ 4] ^= ((uint_8t*)s)[ 4];
+ ((uint_8t*)d)[ 5] ^= ((uint_8t*)s)[ 5];
+ ((uint_8t*)d)[ 6] ^= ((uint_8t*)s)[ 6];
+ ((uint_8t*)d)[ 7] ^= ((uint_8t*)s)[ 7];
+ ((uint_8t*)d)[ 8] ^= ((uint_8t*)s)[ 8];
+ ((uint_8t*)d)[ 9] ^= ((uint_8t*)s)[ 9];
+ ((uint_8t*)d)[10] ^= ((uint_8t*)s)[10];
+ ((uint_8t*)d)[11] ^= ((uint_8t*)s)[11];
+ ((uint_8t*)d)[12] ^= ((uint_8t*)s)[12];
+ ((uint_8t*)d)[13] ^= ((uint_8t*)s)[13];
+ ((uint_8t*)d)[14] ^= ((uint_8t*)s)[14];
+ ((uint_8t*)d)[15] ^= ((uint_8t*)s)[15];
+#endif
+}
+
+static void copy_and_key( void *d, const void *s, const void *k )
+{
+#if defined( HAVE_UINT_32T )
+ ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0] ^ ((uint_32t*)k)[ 0];
+ ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1] ^ ((uint_32t*)k)[ 1];
+ ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2] ^ ((uint_32t*)k)[ 2];
+ ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3] ^ ((uint_32t*)k)[ 3];
+#elif 1
+ ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0] ^ ((uint_8t*)k)[ 0];
+ ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1] ^ ((uint_8t*)k)[ 1];
+ ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2] ^ ((uint_8t*)k)[ 2];
+ ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3] ^ ((uint_8t*)k)[ 3];
+ ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4] ^ ((uint_8t*)k)[ 4];
+ ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5] ^ ((uint_8t*)k)[ 5];
+ ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6] ^ ((uint_8t*)k)[ 6];
+ ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7] ^ ((uint_8t*)k)[ 7];
+ ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8] ^ ((uint_8t*)k)[ 8];
+ ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9] ^ ((uint_8t*)k)[ 9];
+ ((uint_8t*)d)[10] = ((uint_8t*)s)[10] ^ ((uint_8t*)k)[10];
+ ((uint_8t*)d)[11] = ((uint_8t*)s)[11] ^ ((uint_8t*)k)[11];
+ ((uint_8t*)d)[12] = ((uint_8t*)s)[12] ^ ((uint_8t*)k)[12];
+ ((uint_8t*)d)[13] = ((uint_8t*)s)[13] ^ ((uint_8t*)k)[13];
+ ((uint_8t*)d)[14] = ((uint_8t*)s)[14] ^ ((uint_8t*)k)[14];
+ ((uint_8t*)d)[15] = ((uint_8t*)s)[15] ^ ((uint_8t*)k)[15];
+#else
+ block_copy(d, s);
+ xor_block(d, k);
+#endif
+}
+
+static void add_round_key( uint_8t d[N_BLOCK], const uint_8t k[N_BLOCK] )
+{
+ xor_block(d, k);
+}
+
+static void shift_sub_rows( uint_8t st[N_BLOCK] )
+{ uint_8t tt;
+
+ st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]);
+ st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]);
+
+ tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]);
+ st[ 9] = s_box(st[13]); st[13] = s_box( tt );
+
+ tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt );
+ tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt );
+
+ tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]);
+ st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt );
+}
+
+static void inv_shift_sub_rows( uint_8t st[N_BLOCK] )
+{ uint_8t tt;
+
+ st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]);
+ st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]);
+
+ tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]);
+ st[ 5] = is_box(st[1]); st[ 1] = is_box( tt );
+
+ tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt );
+ tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt );
+
+ tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]);
+ st[11] = is_box(st[15]); st[15] = is_box( tt );
+}
+
+#if defined( VERSION_1 )
+ static void mix_sub_columns( uint_8t dt[N_BLOCK] )
+ { uint_8t st[N_BLOCK];
+ block_copy(st, dt);
+#else
+ static void mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
+ {
+#endif
+ dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
+ dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
+ dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
+ dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
+
+ dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
+ dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
+ dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
+ dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
+
+ dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
+ dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
+ dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
+ dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
+
+ dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
+ dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
+ dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
+ dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
+ }
+
+#if defined( VERSION_1 )
+ static void inv_mix_sub_columns( uint_8t dt[N_BLOCK] )
+ { uint_8t st[N_BLOCK];
+ block_copy(st, dt);
+#else
+ static void inv_mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
+ {
+#endif
+ dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3]));
+ dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3]));
+ dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3]));
+ dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3]));
+
+ dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7]));
+ dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7]));
+ dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7]));
+ dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7]));
+
+ dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
+ dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
+ dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
+ dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
+
+ dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
+ dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
+ dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
+ dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
+ }
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+/* Set the cipher key for the pre-keyed version */
+
+return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] )
+{
+ uint_8t cc, rc, hi;
+
+ switch( keylen )
+ {
+ case 16:
+ case 128:
+ keylen = 16;
+ break;
+ case 24:
+ case 192:
+ keylen = 24;
+ break;
+ case 32:
+ case 256:
+ keylen = 32;
+ break;
+ default:
+ ctx->rnd = 0;
+ return (return_type)-1;
+ }
+ block_copy_nn(ctx->ksch, key, keylen);
+ hi = (keylen + 28) << 2;
+ ctx->rnd = (hi >> 4) - 1;
+ for( cc = keylen, rc = 1; cc < hi; cc += 4 )
+ { uint_8t tt, t0, t1, t2, t3;
+
+ t0 = ctx->ksch[cc - 4];
+ t1 = ctx->ksch[cc - 3];
+ t2 = ctx->ksch[cc - 2];
+ t3 = ctx->ksch[cc - 1];
+ if( cc % keylen == 0 )
+ {
+ tt = t0;
+ t0 = s_box(t1) ^ rc;
+ t1 = s_box(t2);
+ t2 = s_box(t3);
+ t3 = s_box(tt);
+ rc = f2(rc);
+ }
+ else if( keylen > 24 && cc % keylen == 16 )
+ {
+ t0 = s_box(t0);
+ t1 = s_box(t1);
+ t2 = s_box(t2);
+ t3 = s_box(t3);
+ }
+ tt = cc - keylen;
+ ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
+ ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
+ ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
+ ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
+ }
+ return 0;
+}
+
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+/* Encrypt a single block of 16 bytes */
+
+return_type aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
+{
+ if( ctx->rnd )
+ {
+ uint_8t s1[N_BLOCK], r;
+ copy_and_key( s1, in, ctx->ksch );
+
+ for( r = 1 ; r < ctx->rnd ; ++r )
+#if defined( VERSION_1 )
+ {
+ mix_sub_columns( s1 );
+ add_round_key( s1, ctx->ksch + r * N_BLOCK);
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ mix_sub_columns( s2, s1 );
+ copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK);
+ }
+#endif
+ shift_sub_rows( s1 );
+ copy_and_key( out, s1, ctx->ksch + r * N_BLOCK );
+ }
+ else
+ return (return_type)-1;
+ return 0;
+}
+
+/* CBC encrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_encrypt( const unsigned char *in, unsigned char *out,
+ int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
+{
+
+ while(n_block--)
+ {
+ xor_block(iv, in);
+ if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ memcpy(out, iv, N_BLOCK);
+ in += N_BLOCK;
+ out += N_BLOCK;
+ }
+ return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+/* Decrypt a single block of 16 bytes */
+
+return_type aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
+{
+ if( ctx->rnd )
+ {
+ uint_8t s1[N_BLOCK], r;
+ copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK );
+ inv_shift_sub_rows( s1 );
+
+ for( r = ctx->rnd ; --r ; )
+#if defined( VERSION_1 )
+ {
+ add_round_key( s1, ctx->ksch + r * N_BLOCK );
+ inv_mix_sub_columns( s1 );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK );
+ inv_mix_sub_columns( s1, s2 );
+ }
+#endif
+ copy_and_key( out, s1, ctx->ksch );
+ }
+ else
+ return (return_type)-1;
+ return 0;
+}
+
+/* CBC decrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_decrypt( const unsigned char *in, unsigned char *out,
+ int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
+{
+ while(n_block--)
+ { uint_8t tmp[N_BLOCK];
+
+ memcpy(tmp, in, N_BLOCK);
+ if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ xor_block(out, iv);
+ memcpy(iv, tmp, N_BLOCK);
+ in += N_BLOCK;
+ out += N_BLOCK;
+ }
+ return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_ENC_128_OTFK )
+
+/* The 'on the fly' encryption key update for for 128 bit keys */
+
+static void update_encrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ k[0] ^= s_box(k[13]) ^ *rc;
+ k[1] ^= s_box(k[14]);
+ k[2] ^= s_box(k[15]);
+ k[3] ^= s_box(k[12]);
+ *rc = f2( *rc );
+
+ for(cc = 4; cc < 16; cc += 4 )
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+}
+
+/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
+{ uint_8t s1[N_BLOCK], r, rc = 1;
+
+ if(o_key != key)
+ block_copy( o_key, key );
+ copy_and_key( s1, in, o_key );
+
+ for( r = 1 ; r < 10 ; ++r )
+#if defined( VERSION_1 )
+ {
+ mix_sub_columns( s1 );
+ update_encrypt_key_128( o_key, &rc );
+ add_round_key( s1, o_key );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ mix_sub_columns( s2, s1 );
+ update_encrypt_key_128( o_key, &rc );
+ copy_and_key( s1, s2, o_key );
+ }
+#endif
+
+ shift_sub_rows( s1 );
+ update_encrypt_key_128( o_key, &rc );
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+
+/* The 'on the fly' decryption key update for for 128 bit keys */
+
+static void update_decrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ for( cc = 12; cc > 0; cc -= 4 )
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+ *rc = d2(*rc);
+ k[0] ^= s_box(k[13]) ^ *rc;
+ k[1] ^= s_box(k[14]);
+ k[2] ^= s_box(k[15]);
+ k[3] ^= s_box(k[12]);
+}
+
+/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
+{
+ uint_8t s1[N_BLOCK], r, rc = 0x6c;
+ if(o_key != key)
+ block_copy( o_key, key );
+
+ copy_and_key( s1, in, o_key );
+ inv_shift_sub_rows( s1 );
+
+ for( r = 10 ; --r ; )
+#if defined( VERSION_1 )
+ {
+ update_decrypt_key_128( o_key, &rc );
+ add_round_key( s1, o_key );
+ inv_mix_sub_columns( s1 );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ update_decrypt_key_128( o_key, &rc );
+ copy_and_key( s2, s1, o_key );
+ inv_mix_sub_columns( s1, s2 );
+ }
+#endif
+ update_decrypt_key_128( o_key, &rc );
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+
+/* The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_encrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ k[0] ^= s_box(k[29]) ^ *rc;
+ k[1] ^= s_box(k[30]);
+ k[2] ^= s_box(k[31]);
+ k[3] ^= s_box(k[28]);
+ *rc = f2( *rc );
+
+ for(cc = 4; cc < 16; cc += 4)
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+
+ k[16] ^= s_box(k[12]);
+ k[17] ^= s_box(k[13]);
+ k[18] ^= s_box(k[14]);
+ k[19] ^= s_box(k[15]);
+
+ for( cc = 20; cc < 32; cc += 4 )
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+}
+
+/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
+
+void aes_encrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
+{
+ uint_8t s1[N_BLOCK], r, rc = 1;
+ if(o_key != key)
+ {
+ block_copy( o_key, key );
+ block_copy( o_key + 16, key + 16 );
+ }
+ copy_and_key( s1, in, o_key );
+
+ for( r = 1 ; r < 14 ; ++r )
+#if defined( VERSION_1 )
+ {
+ mix_sub_columns(s1);
+ if( r & 1 )
+ add_round_key( s1, o_key + 16 );
+ else
+ {
+ update_encrypt_key_256( o_key, &rc );
+ add_round_key( s1, o_key );
+ }
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ mix_sub_columns( s2, s1 );
+ if( r & 1 )
+ copy_and_key( s1, s2, o_key + 16 );
+ else
+ {
+ update_encrypt_key_256( o_key, &rc );
+ copy_and_key( s1, s2, o_key );
+ }
+ }
+#endif
+
+ shift_sub_rows( s1 );
+ update_encrypt_key_256( o_key, &rc );
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+
+/* The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_decrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ for(cc = 28; cc > 16; cc -= 4)
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+
+ k[16] ^= s_box(k[12]);
+ k[17] ^= s_box(k[13]);
+ k[18] ^= s_box(k[14]);
+ k[19] ^= s_box(k[15]);
+
+ for(cc = 12; cc > 0; cc -= 4)
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+
+ *rc = d2(*rc);
+ k[0] ^= s_box(k[29]) ^ *rc;
+ k[1] ^= s_box(k[30]);
+ k[2] ^= s_box(k[31]);
+ k[3] ^= s_box(k[28]);
+}
+
+/* Decrypt a single block of 16 bytes with 'on the fly'
+ 256 bit keying
+*/
+void aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
+{
+ uint_8t s1[N_BLOCK], r, rc = 0x80;
+
+ if(o_key != key)
+ {
+ block_copy( o_key, key );
+ block_copy( o_key + 16, key + 16 );
+ }
+
+ copy_and_key( s1, in, o_key );
+ inv_shift_sub_rows( s1 );
+
+ for( r = 14 ; --r ; )
+#if defined( VERSION_1 )
+ {
+ if( ( r & 1 ) )
+ {
+ update_decrypt_key_256( o_key, &rc );
+ add_round_key( s1, o_key + 16 );
+ }
+ else
+ add_round_key( s1, o_key );
+ inv_mix_sub_columns( s1 );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ if( ( r & 1 ) )
+ {
+ update_decrypt_key_256( o_key, &rc );
+ copy_and_key( s2, s1, o_key + 16 );
+ }
+ else
+ copy_and_key( s2, s1, o_key );
+ inv_mix_sub_columns( s1, s2 );
+ }
+#endif
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
diff --git a/stack/smp/aes.h b/stack/smp/aes.h
new file mode 100644
index 000000000..dcfde93c0
--- /dev/null
+++ b/stack/smp/aes.h
@@ -0,0 +1,162 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#if 1
+# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
+#endif
+#if 1
+# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */
+#endif
+#if 1
+# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */
+#endif
+#if 1
+# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */
+#endif
+#if 1
+# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */
+#endif
+#if 1
+# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */
+#endif
+
+#define N_ROW 4
+#define N_COL 4
+#define N_BLOCK (N_ROW * N_COL)
+#define N_MAX_ROUNDS 14
+
+typedef unsigned char uint_8t;
+
+typedef uint_8t return_type;
+
+/* Warning: The key length for 256 bit keys overflows a byte
+ (see comment below)
+*/
+
+typedef uint_8t length_type;
+
+typedef struct
+{ uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
+ uint_8t rnd;
+} aes_context;
+
+/* The following calls are for a precomputed key schedule
+
+ NOTE: If the length_type used for the key length is an
+ unsigned 8-bit character, a key length of 256 bits must
+ be entered as a length in bytes (valid inputs are hence
+ 128, 192, 16, 24 and 32).
+*/
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+return_type aes_set_key( const unsigned char key[],
+ length_type keylen,
+ aes_context ctx[1] );
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+return_type aes_encrypt( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const aes_context ctx[1] );
+
+return_type aes_cbc_encrypt( const unsigned char *in,
+ unsigned char *out,
+ int n_block,
+ unsigned char iv[N_BLOCK],
+ const aes_context ctx[1] );
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+return_type aes_decrypt( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const aes_context ctx[1] );
+
+return_type aes_cbc_decrypt( const unsigned char *in,
+ unsigned char *out,
+ int n_block,
+ unsigned char iv[N_BLOCK],
+ const aes_context ctx[1] );
+#endif
+
+/* The following calls are for 'on the fly' keying. In this case the
+ encryption and decryption keys are different.
+
+ The encryption subroutines take a key in an array of bytes in
+ key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
+ 192, and 256 bits respectively. They then encrypts the input
+ data, in[] with this key and put the reult in the output array
+ out[]. In addition, the second key array, o_key[L], is used
+ to output the key that is needed by the decryption subroutine
+ to reverse the encryption operation. The two key arrays can
+ be the same array but in this case the original key will be
+ overwritten.
+
+ In the same way, the decryption subroutines output keys that
+ can be used to reverse their effect when used for encryption.
+
+ Only 128 and 256 bit keys are supported in these 'on the fly'
+ modes.
+*/
+
+#if defined( AES_ENC_128_OTFK )
+void aes_encrypt_128( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK],
+ uint_8t o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+void aes_decrypt_128( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK],
+ unsigned char o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+void aes_encrypt_256( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK],
+ unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+void aes_decrypt_256( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK],
+ unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#endif
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index ca24225d6..73f481139 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -36,7 +36,7 @@ const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
{SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}}, /* keyboard display */
/* responder */
{{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* Display Only */
- {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
+ {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
{SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}, /* keyboard only */
{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY},/* No Input No Output */
{SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}} /* keyboard display */
@@ -477,8 +477,6 @@ void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
SMP_TRACE_DEBUG0 ("smp_proc_id_info ");
STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
- /* store the ID key from peer device */
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, (tBTM_LE_KEY_VALUE *)&p_cb->tk, TRUE);
smp_key_distribution(p_cb, NULL);
}
@@ -489,14 +487,17 @@ void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 *p = (UINT8 *)p_data;
- BD_ADDR mac_bda;
+ tBTM_LE_PID_KEYS pid_key;
SMP_TRACE_DEBUG0 ("smp_proc_id_addr ");
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
- STREAM_TO_BDADDR(mac_bda, p);
+ STREAM_TO_UINT8(pid_key.addr_type, p);
+ STREAM_TO_BDADDR(pid_key.static_addr, p);
+ memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
- /* TODO, update MAC address */
+ /* store the ID key from peer device */
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
smp_key_distribution(p_cb, NULL);
}
@@ -529,7 +530,11 @@ void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
UINT8 reason;
SMP_TRACE_DEBUG0 ("smp_proc_compare ");
- if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
+ if (
+#if SMP_CONFORMANCE_TESTING == TRUE
+ p_cb->skip_test_compare_check ||
+#endif
+ !memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
{
/* compare the max encryption key size, and save the smaller one for the link */
if ( p_cb->peer_enc_size < p_cb->loc_enc_size)
@@ -602,7 +607,7 @@ void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
SMP_TRACE_DEBUG0 ("smp_proc_discard ");
- smp_cb_cleanup(p_cb);
+ smp_reset_control_value(p_cb);
}
/*******************************************************************************
** Function smp_proc_release_delay
@@ -736,7 +741,7 @@ void smp_decide_asso_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
tSMP_ASSO_MODEL model = SMP_MODEL_MAX;
UINT8 int_evt = 0;
tSMP_KEY key;
- tSMP_INT_DATA *p;
+ tSMP_INT_DATA *p = NULL;
SMP_TRACE_DEBUG3 ("smp_decide_asso_model p_cb->peer_io_caps = %d p_cb->loc_io_caps = %d \
p_cb->peer_auth_req = %02x",
@@ -875,7 +880,12 @@ void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
SMP_TRACE_DEBUG0 ("smp_pair_terminate ");
- p_cb->status = SMP_PAIR_FAIL_UNKNOWN;
+
+ if (p_data->reason == L2CAP_CONN_CANCEL)
+ p_cb->status = SMP_CONN_TOUT;
+ else
+ p_cb->status = SMP_PAIR_FAIL_UNKNOWN;
+
smp_proc_pairing_cmpl(p_cb);
}
/*******************************************************************************
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 9eb2f1074..e8d93deb4 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -198,6 +198,7 @@ typedef struct
UINT8 rand_enc_proc;
BOOLEAN last_cmd;
+ UINT8 addr_type;
BD_ADDR local_bda;
BOOLEAN is_pair_cancel;
BOOLEAN discard_sec_req;
@@ -209,6 +210,7 @@ typedef struct
BOOLEAN enable_test_pair_fail;
UINT8 pair_fail_status;
BOOLEAN remove_fixed_channel_disable;
+ BOOLEAN skip_test_compare_check;
#endif
}tSMP_CB;
@@ -242,6 +244,7 @@ SMP_API extern void smp_set_test_confirm_value (BOOLEAN enable, UINT8 *p_c_valu
SMP_API extern void smp_set_test_rand_value (BOOLEAN enable, UINT8 *p_c_value);
SMP_API extern void smp_set_test_pair_fail_status (BOOLEAN enable, UINT8 status);
SMP_API extern void smp_remove_fixed_channel_disable (BOOLEAN disable);
+SMP_API extern void smp_skip_compare_check (BOOLEAN enable);
#endif
/* smp main */
extern void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c
index c61b54809..a1955f202 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -181,7 +181,7 @@ void smp_proc_passkey(tSMP_CB *p_cb , tBTM_RAND_ENC *p)
{
UINT8 *tt = p_cb->tk;
tSMP_KEY key;
- UINT32 passkey; //= 19655 test number; */
+ UINT32 passkey; /* 19655 test number; */
UINT8 *pp = p->param_buf;
SMP_TRACE_DEBUG0 ("smp_proc_passkey ");
@@ -445,23 +445,25 @@ void smp_concatenate_peer( tSMP_CB *p_cb, UINT8 **p_data, UINT8 op_code)
void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
{
UINT8 *p = (UINT8 *)p1;
- tBTM_SEC_DEV_REC *p_dev_rec;
+ tBLE_ADDR_TYPE addr_type = 0;
+ BD_ADDR remote_bda;
SMP_TRACE_DEBUG0 ("smp_gen_p1_4_confirm");
- if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
+
+ if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type))
{
SMP_TRACE_ERROR0("can not generate confirm for unknown device");
return;
}
- BTM_ReadConnectionAddr(p_cb->local_bda);
+ BTM_ReadConnectionAddr( p_cb->pairing_bda, p_cb->local_bda, &p_cb->addr_type);
if (p_cb->role == HCI_ROLE_MASTER)
{
/* LSB : rat': initiator's(local) address type */
- UINT8_TO_STREAM(p, 0);
+ UINT8_TO_STREAM(p, p_cb->addr_type);
/* LSB : iat': responder's address type */
- UINT8_TO_STREAM(p, p_dev_rec->ble.ble_addr_type);
+ UINT8_TO_STREAM(p, addr_type);
/* concatinate preq */
smp_concatenate_local(p_cb, &p, SMP_OPCODE_PAIRING_REQ);
/* concatinate pres */
@@ -470,9 +472,9 @@ void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
else
{
/* LSB : iat': initiator's address type */
- UINT8_TO_STREAM(p, p_dev_rec->ble.ble_addr_type);
+ UINT8_TO_STREAM(p, addr_type);
/* LSB : rat': responder's(local) address type */
- UINT8_TO_STREAM(p, 0);
+ UINT8_TO_STREAM(p, p_cb->addr_type);
/* concatinate preq */
smp_concatenate_peer(p_cb, &p, SMP_OPCODE_PAIRING_REQ);
/* concatinate pres */
@@ -495,15 +497,24 @@ void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
*******************************************************************************/
void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
{
- UINT8 *p = (UINT8 *)p2;
+ UINT8 *p = (UINT8 *)p2;
+ BD_ADDR remote_bda;
+ tBLE_ADDR_TYPE addr_type = 0;
+
+ if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type))
+ {
+ SMP_TRACE_ERROR0("can not generate confirm p2 for unknown device");
+ return;
+ }
SMP_TRACE_DEBUG0 ("smp_gen_p2_4_confirm");
+
memset(p, 0, sizeof(BT_OCTET16));
if (p_cb->role == HCI_ROLE_MASTER)
{
/* LSB ra */
- BDADDR_TO_STREAM(p, p_cb->pairing_bda);
+ BDADDR_TO_STREAM(p, remote_bda);
/* ia */
BDADDR_TO_STREAM(p, p_cb->local_bda);
}
@@ -512,7 +523,7 @@ void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
/* LSB ra */
BDADDR_TO_STREAM(p, p_cb->local_bda);
/* ia */
- BDADDR_TO_STREAM(p, p_cb->pairing_bda);
+ BDADDR_TO_STREAM(p, remote_bda);
}
#if SMP_DEBUG == TRUE
SMP_TRACE_DEBUG0("p2 = padding || ia || ra");
diff --git a/stack/smp/smp_l2c.c b/stack/smp/smp_l2c.c
index 648cd5901..54b78b451 100644
--- a/stack/smp/smp_l2c.c
+++ b/stack/smp/smp_l2c.c
@@ -99,8 +99,6 @@ static void smp_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason
p_cb->loc_auth_req = p_cb->peer_auth_req = SMP_DEFAULT_AUTH_REQ;
p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
smp_sm_event(p_cb, SMP_L2CAP_CONN_EVT, NULL);
-
- BTM_ReadConnectionAddr(p_cb->local_bda);
}
}
else
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index a60f54bed..59dddb470 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -174,7 +174,7 @@ static const UINT8 smp_ma_entry_map[][SMP_ST_MAX] =
/* KEY_READY */{ 0, 3, 0, 3, 1, 0, 2, 1, 6, 0 },
/* ENC_CMPL */{ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 },
/* L2C_CONN */{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* L2C_DISC */{ 0, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 2 },
+/* L2C_DISC */{ 0x83, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 2 },
/* IO_RSP */{ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
/* SEC_GRANT */{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
/* TK_REQ */{ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 562288028..168d6bd11 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -336,18 +336,18 @@ static BT_HDR * smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
{
BT_HDR *p_buf = NULL ;
UINT8 *p;
- BT_OCTET16 irk;
+ BD_ADDR static_addr;
+
+
SMP_TRACE_EVENT0("smp_build_id_addr_cmd");
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_ID_ADDR_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
- BTM_GetDeviceIDRoot(irk);
-
UINT8_TO_STREAM (p, SMP_OPCODE_ID_ADDR);
UINT8_TO_STREAM (p, 0); /* TODO: update with local address type */
- BTM_ReadConnectionAddr(p_cb->local_bda);
- BDADDR_TO_STREAM (p, p_cb->local_bda);
+ BTM_GetLocalDeviceAddr(static_addr);
+ BDADDR_TO_STREAM (p, static_addr);
p_buf->offset = L2CAP_MIN_OFFSET;
p_buf->len = SMP_ID_ADDR_SIZE;
@@ -367,7 +367,7 @@ static BT_HDR * smp_build_signing_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
{
BT_HDR *p_buf = NULL ;
UINT8 *p;
- //BT_OCTET16 srk; remove
+
SMP_TRACE_EVENT0("smp_build_signing_info_cmd");
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_SIGN_INFO_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
@@ -667,6 +667,20 @@ void smp_remove_fixed_channel_disable (BOOLEAN disable)
SMP_TRACE_DEBUG1("smp_remove_fixed_channel_disable disable =%d", disable);
smp_cb.remove_fixed_channel_disable = disable;
}
+/*******************************************************************************
+**
+** Function smp_skip_compare_check
+**
+** Description This function is called to skip the compare value check
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_skip_compare_check(BOOLEAN enable)
+{
+ SMP_TRACE_DEBUG1("smp_skip_compare_check enable=%d", enable);
+ smp_cb.skip_test_compare_check = enable;
+}
#endif
diff --git a/test/bluedroidtest/README.txt b/test/bluedroidtest/README.txt
index a443a2955..0a4705074 100644
--- a/test/bluedroidtest/README.txt
+++ b/test/bluedroidtest/README.txt
@@ -41,16 +41,29 @@ HAL REQUEST SUCCESS
Enabling Test Mode (Bluetooth must be enabled for this command to work)
======================================================================
->enable_test_mode
-ENABLE BT TEST MODE
+>dut_mode_configure 1
+BT DUT MODE CONFIGURE
HAL REQUEST SUCCESS
>
Disabling Test Mode
===================
->disable_test_mode
-DISABLE BT TEST MODE
+>dut_mode_configure 0
+BT DUT MODE CONFIGURE
HAL REQUEST SUCCESS
+>
+
+Running BLE Test commands (Bluetooth must be enabled)
+=====================================================
+NOTE: Unlike BR/EDR, there is no explicit DUT mode to run these BLE tests.
+
+> le_test_mode 1 <rx_freq>
+
+> le_test_mode 2 <tx_freq> <test_data_len> <payload_pattern>
+
+> le_test_mode 3 <no_args>
+Please refer to the BT Core spec pages-1099 to 1102 for possible values for
+the above parameters. These values need to be provided in Decimal format.
Exit the test application
=========================
@@ -68,6 +81,8 @@ help lists all available console commands
quit
enable :: enables bluetooth
disable :: disables bluetooth
-enable_test_mode :: enters bluedroid test mode
-disable_test_mode :: exits bluedroid test mode
+dut_mode_configure :: DUT mode - 1 to enter,0 to exit
+le_test_mode :: LE Test Mode - RxTest - 1 <rx_freq>,
+ TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>,
+ End Test - 3 <no_args>
diff --git a/test/bluedroidtest/bluedroidtest.c b/test/bluedroidtest/bluedroidtest.c
index 130bc6054..ad9f4023c 100644
--- a/test/bluedroidtest/bluedroidtest.c
+++ b/test/bluedroidtest/bluedroidtest.c
@@ -474,6 +474,11 @@ static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len)
bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
}
+static void le_test_mode(bt_status_t status, uint16_t packet_count)
+{
+ bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count);
+}
+
static bt_callbacks_t bt_callbacks = {
sizeof(bt_callbacks_t),
adapter_state_changed,
@@ -487,6 +492,8 @@ static bt_callbacks_t bt_callbacks = {
NULL, /* acl_state_changed_cb */
NULL, /* thread_evt_cb */
dut_mode_recv, /*dut_mode_recv_cb */
+ NULL, /*authorize_request_cb */
+ le_test_mode /* le_test_mode_cb */
};
void bdt_init(void)
@@ -538,6 +545,58 @@ void bdt_dut_mode_configure(char *p)
check_return_status(status);
}
+#define HCI_LE_RECEIVER_TEST_OPCODE 0x201D
+#define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E
+#define HCI_LE_END_TEST_OPCODE 0x201F
+
+void bdt_le_test_mode(char *p)
+{
+ int cmd;
+ unsigned char buf[3];
+ int arg1, arg2, arg3;
+
+ bdt_log("BT LE TEST MODE");
+ if (!bt_enabled) {
+ bdt_log("Bluetooth must be enabled for le_test to work.");
+ return;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ cmd = get_int(&p, 0);
+ switch (cmd)
+ {
+ case 0x1: /* RX TEST */
+ arg1 = get_int(&p, -1);
+ if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__);
+ buf[0] = arg1;
+ status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1);
+ break;
+ case 0x2: /* TX TEST */
+ arg1 = get_int(&p, -1);
+ arg2 = get_int(&p, -1);
+ arg3 = get_int(&p, -1);
+ if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0))
+ bdt_log("%s Invalid arguments", __FUNCTION__);
+ buf[0] = arg1;
+ buf[1] = arg2;
+ buf[2] = arg3;
+ status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3);
+ break;
+ case 0x3: /* END TEST */
+ status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0);
+ break;
+ default:
+ bdt_log("Unsupported command");
+ return;
+ break;
+ }
+ if (status != BT_STATUS_SUCCESS)
+ {
+ bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status);
+ }
+ return;
+}
+
void bdt_cleanup(void)
{
bdt_log("CLEANUP");
@@ -595,6 +654,11 @@ void do_dut_mode_configure(char *p)
bdt_dut_mode_configure(p);
}
+void do_le_test_mode(char *p)
+{
+ bdt_le_test_mode(p);
+}
+
void do_cleanup(char *p)
{
bdt_cleanup();
@@ -623,7 +687,9 @@ const t_cmd console_cmd_list[] =
{ "enable", do_enable, ":: enables bluetooth", 0 },
{ "disable", do_disable, ":: disables bluetooth", 0 },
{ "dut_mode_configure", do_dut_mode_configure, ":: DUT mode - 1 to enter,0 to exit", 0 },
-
+ { "le_test_mode", do_le_test_mode, ":: LE Test Mode - RxTest - 1 <rx_freq>, \n\t \
+ TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>, \n\t \
+ End Test - 3 <no_args>", 0 },
/* add here */
/* last entry */