am 8b8050ad: am 197a801b: Merge "Bluedroid: Fix UUID unsigned/signed comparison"
* commit '8b8050ad5f2f4fd64766c99378fa0866d89230c6':
Bluedroid: Fix UUID unsigned/signed comparison
diff --git a/Android.mk b/Android.mk
index 9e197f0..83e6bbf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -11,6 +11,8 @@
bdroid_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
endif
+bdroid_CFLAGS += -Wall -Werror
+
include $(call all-subdir-makefiles)
# Cleanup our locals
diff --git a/audio_a2dp_hw/Android.mk b/audio_a2dp_hw/Android.mk
index d2a8f0a..c2c1110 100644
--- a/audio_a2dp_hw/Android.mk
+++ b/audio_a2dp_hw/Android.mk
@@ -8,6 +8,8 @@
LOCAL_C_INCLUDES+= . $(LOCAL_PATH)/../utils/include
LOCAL_CFLAGS := -Wno-unused-parameter
+LOCAL_CFLAGS += -std=c99
+
LOCAL_SHARED_LIBRARIES := \
libcutils liblog
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c
index dacba66..e53ad5d 100644
--- a/audio_a2dp_hw/audio_a2dp_hw.c
+++ b/audio_a2dp_hw/audio_a2dp_hw.c
@@ -286,9 +286,24 @@
if (recv(out->ctrl_fd, &ack, 1, MSG_NOSIGNAL) < 0)
{
ERROR("ack failed (%s)", strerror(errno));
- skt_disconnect(out->ctrl_fd);
- out->ctrl_fd = AUDIO_SKT_DISCONNECTED;
- return -1;
+ if (errno == EINTR)
+ {
+ /* retry again */
+ if (recv(out->ctrl_fd, &ack, 1, MSG_NOSIGNAL) < 0)
+ {
+ ERROR("ack failed (%s)", strerror(errno));
+ skt_disconnect(out->ctrl_fd);
+ out->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ return -1;
+ }
+ }
+ else
+ {
+ skt_disconnect(out->ctrl_fd);
+ out->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+ return -1;
+
+ }
}
DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
@@ -584,7 +599,8 @@
struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
struct str_parms *parms;
char keyval[16];
- int retval = 0;
+ int retval;
+ int status = 0;
INFO("state %d", out->state);
@@ -613,7 +629,7 @@
if (strcmp(keyval, "true") == 0)
{
if (out->state == AUDIO_A2DP_STATE_STARTED)
- retval = suspend_audio_datapath(out, false);
+ status = suspend_audio_datapath(out, false);
}
else
{
@@ -623,14 +639,13 @@
if (out->state == AUDIO_A2DP_STATE_SUSPENDED)
out->state = AUDIO_A2DP_STATE_STANDBY;
/* Irrespective of the state, return 0 */
- retval = 0;
}
}
pthread_mutex_unlock(&out->lock);
str_parms_destroy(parms);
- return retval;
+ return status;
}
static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
@@ -927,6 +942,7 @@
err_open:
free(out);
*stream_out = NULL;
+ a2dp_dev->output = NULL;
ERROR("failed");
return ret;
}
@@ -956,8 +972,10 @@
int retval = 0;
if (out == NULL)
+ {
+ ERROR("ERROR: set param called even when stream out is null");
return retval;
-
+ }
INFO("state %d", out->state);
retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
@@ -1147,7 +1165,7 @@
return -ENOMEM;
adev->device.common.tag = HARDWARE_DEVICE_TAG;
- adev->device.common.version = AUDIO_DEVICE_API_VERSION_CURRENT;
+ adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
adev->device.common.module = (struct hw_module_t *) module;
adev->device.common.close = adev_close;
diff --git a/bta/Android.mk b/bta/Android.mk
index 310080d..694e701 100644
--- a/bta/Android.mk
+++ b/bta/Android.mk
@@ -6,7 +6,7 @@
LOCAL_CFLAGS += \
-DBOARD_HAVE_BLUETOOTH_BCM
endif
-LOCAL_CFLAGS += -DBUILDCFG $(bdroid_CFLAGS)
+LOCAL_CFLAGS += -DBUILDCFG $(bdroid_CFLAGS) -std=c99
LOCAL_PRELINK_MODULE:=false
LOCAL_SRC_FILES:= \
@@ -75,12 +75,14 @@
./jv/bta_jv_act.c \
./jv/bta_jv_cfg.c \
./jv/bta_jv_main.c \
- ./jv/bta_jv_api.c
+ ./jv/bta_jv_api.c \
+ ../vnd/ble/bta_vendor.c
LOCAL_MODULE := libbt-brcm_bta
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libcutils libc
+LOCAL_MULTILIB := 32
LOCAL_C_INCLUDES+= . \
$(LOCAL_PATH)/include \
@@ -95,7 +97,7 @@
$(LOCAL_PATH)/../hcis \
$(LOCAL_PATH)/../hcis/patchram \
$(LOCAL_PATH)/../udrv/include \
- $(LOCAL_PATH)/../brcm/include \
+ $(LOCAL_PATH)/../vnd/include \
$(LOCAL_PATH)/../utils/include \
$(bdroid_C_INCLUDES) \
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c
index 11fc85c..cedbb3d 100644
--- a/bta/ag/bta_ag_act.c
+++ b/bta/ag/bta_ag_act.c
@@ -406,7 +406,7 @@
*******************************************************************************/
void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
{
- tBTA_AG_HDR close;
+ tBTA_AG_CLOSE close;
tBTA_SERVICE_MASK services;
int i, num_active_conn = 0;
UNUSED(p_data);
@@ -436,13 +436,14 @@
bta_sys_stop_timer(&p_scb->cn_timer);
#endif
- close.handle = bta_ag_scb_to_idx(p_scb);
- close.app_id = p_scb->app_id;
+ close.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ close.hdr.app_id = p_scb->app_id;
+ bdcpy(close.bd_addr, p_scb->peer_addr);
bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
/* call close call-out */
- bta_ag_co_data_close(close.handle);
+ bta_ag_co_data_close(close.hdr.handle);
/* call close cback */
(*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close);
@@ -819,6 +820,7 @@
evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
evt.hdr.app_id = p_scb->app_id;
evt.peer_feat = p_scb->peer_features;
+ bdcpy(evt.bd_addr, p_scb->peer_addr);
#if (BTM_WBS_INCLUDED == TRUE )
evt.peer_codec = p_scb->peer_codecs;
#endif
diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c
index 54cd4d3..577ebdf 100644
--- a/bta/ag/bta_ag_cmd.c
+++ b/bta/ag/bta_ag_cmd.c
@@ -21,7 +21,10 @@
* This file contains functions for processing AT commands and results.
*
******************************************************************************/
-
+#include "bt_target.h"
+#include "bt_types.h"
+#include "gki.h"
+#include "bd.h"
#include "bta_api.h"
#include "bta_sys.h"
#include "bta_ag_api.h"
@@ -867,6 +870,7 @@
val.hdr.handle = bta_ag_scb_to_idx(p_scb);
val.hdr.app_id = p_scb->app_id;
val.num = int_arg;
+ bdcpy(val.bd_addr, p_scb->peer_addr);
BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
val.str[BTA_AG_AT_MAX_LEN] = 0;
diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c
index bae992b..712e50e 100644
--- a/bta/ag/bta_ag_main.c
+++ b/bta/ag/bta_ag_main.c
@@ -753,6 +753,7 @@
/* allocate an scb */
if ((p_scb = bta_ag_scb_alloc()) != NULL)
{
+ APPL_TRACE_DEBUG1("bta_ag_api_register: p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, p_data->hdr.event, p_data);
}
else
@@ -781,6 +782,7 @@
{
if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL)
{
+ APPL_TRACE_DEBUG1("bta_ag_api_result: p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
}
}
@@ -788,8 +790,9 @@
{
for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++)
{
- if (p_scb->in_use)
+ if (p_scb->in_use && p_scb->svc_conn)
{
+ APPL_TRACE_DEBUG1("bta_ag_api_result p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
}
}
@@ -879,6 +882,7 @@
{
tBTA_AG_SCB *p_scb;
+ APPL_TRACE_DEBUG1("bta_ag_hdl_event: Event 0x%04x ", p_msg->event);
switch (p_msg->event)
{
/* handle enable event */
@@ -905,6 +909,7 @@
default:
if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
{
+ APPL_TRACE_DEBUG1("bta_ag_hdl_event: p_scb 0x%08x ", p_scb);
bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg);
}
break;
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
old mode 100755
new mode 100644
index 4408874..1637adc
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -870,7 +870,7 @@
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 (AVRC_METADATA_INCLUDED == TRUE)
tAVRC_STS res;
- UINT8 ctype;
+ UINT8 ctype = 0;
tAVRC_RESPONSE rc_rsp;
rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c
old mode 100755
new mode 100644
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
old mode 100755
new mode 100644
index 6a72e97..7013862
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -90,7 +90,7 @@
static char *bta_dm_get_remname(void);
static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result);
-static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr);
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr,tBT_TRANSPORT transport);
static void bta_dm_discover_device(BD_ADDR remote_bd_addr);
static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status );
@@ -517,6 +517,8 @@
{
UNUSED(p_tle);
UINT8 i;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+
APPL_TRACE_EVENT0(" bta_dm_disable_timer_cback ");
@@ -524,8 +526,10 @@
{
for(i=0; i<bta_dm_cb.device_list.count; i++)
{
- btm_remove_acl(bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
-
+#if (BLE_INCLUDED == TRUE)
+ transport = bta_dm_cb.device_list.peer_device[i].transport;
+#endif
+ btm_remove_acl(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, transport);
}
}
@@ -689,22 +693,25 @@
BTA_GATTC_CancelOpen(0, p_dev->bd_addr, FALSE);
#endif
- if (BTM_IsAclConnectionUp(p_dev->bd_addr))
+ if ( BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_LE) ||
+ BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_BR_EDR))
{
+ APPL_TRACE_DEBUG2("%s: ACL Up count %d", __FUNCTION__,bta_dm_cb.device_list.count);
/* Take the link down first, and mark the device for removal when disconnected */
- btm_remove_acl( p_dev->bd_addr) ;
for(i=0; i<bta_dm_cb.device_list.count; i++)
{
if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_dev->bd_addr))
- break;
- }
-
- if(i < bta_dm_cb.device_list.count)
- {
- bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
+ {
+ bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
+ btm_remove_acl( p_dev->bd_addr,bta_dm_cb.device_list.peer_device[i].transport);
+ APPL_TRACE_DEBUG2("%s:transport = %d", __FUNCTION__,
+ bta_dm_cb.device_list.peer_device[i].transport);
+ break;
+ }
}
}
+
else /* Ok to remove the device in application layer */
{
BTM_SecDeleteDevice(p_dev->bd_addr);
@@ -790,15 +797,23 @@
{
tBTA_DM_API_REMOVE_ACL *p_remove_acl = &p_data->remove_acl;
UINT8 index;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
APPL_TRACE_DEBUG0("bta_dm_close_acl");
- if (BTM_IsAclConnectionUp(p_remove_acl->bd_addr))
+ if ( BTM_IsAclConnectionUp(p_remove_acl->bd_addr, BT_TRANSPORT_LE) ||
+ BTM_IsAclConnectionUp(p_remove_acl->bd_addr, BT_TRANSPORT_BR_EDR))
+
{
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))
+ {
+#if defined (BLE_INCLUDED) && (BLE_INCLUDED == TRUE)
+ transport = bta_dm_cb.device_list.peer_device[index].transport;
+#endif
break;
+ }
}
if (index != bta_dm_cb.device_list.count)
{
@@ -810,7 +825,7 @@
APPL_TRACE_ERROR0("unknown device, remove ACL failed");
}
/* Disconnect the ACL link */
- btm_remove_acl(p_remove_acl->bd_addr);
+ btm_remove_acl(p_remove_acl->bd_addr, transport);
}
/* if to remove the device from security database ? do it now */
else if (p_remove_acl->remove_dev)
@@ -845,7 +860,11 @@
tBTA_DM_SEC sec_event;
char *p_name;
- status = BTM_SecBond ( p_data->bond.bd_addr, 0, NULL, 0 );
+ if (p_data->bond.transport == BTA_TRANSPORT_UNKNOWN)
+ status = BTM_SecBond ( p_data->bond.bd_addr, 0, NULL, 0 );
+ else
+ status = BTM_SecBondByTransport ( p_data->bond.bd_addr, p_data->bond.transport, 0, NULL, 0 );
+
if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED))
{
@@ -1335,6 +1354,7 @@
bta_dm_search_cb.peer_name[0] = 0;
bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
bta_dm_search_cb.p_btm_inq_info = BTM_InqDbRead (p_data->discover.bd_addr);
+ bta_dm_search_cb.transport = p_data->discover.transport;
bta_dm_search_cb.name_discover_done = FALSE;
memcpy(&bta_dm_search_cb.uuid, &p_data->discover.uuid, sizeof(tSDP_UUID));
@@ -1502,7 +1522,7 @@
** Returns TRUE if started to get remote name
**
*******************************************************************************/
-static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr)
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr,tBT_TRANSPORT transport)
{
tBTM_STATUS btm_status;
@@ -1512,7 +1532,8 @@
bta_dm_search_cb.peer_name[0] = 0;
btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
- (tBTM_CMPL_CB *) bta_dm_remname_cback);
+ (tBTM_CMPL_CB *) bta_dm_remname_cback,
+ transport);
if ( btm_status == BTM_CMD_STARTED )
{
@@ -2384,6 +2405,21 @@
static void bta_dm_discover_device(BD_ADDR remote_bd_addr)
{
tBTA_DM_MSG * p_msg;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+#if BLE_INCLUDED == TRUE
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type;
+
+ if (bta_dm_search_cb.transport == BTA_TRANSPORT_UNKNOWN)
+ {
+ BTM_ReadDevInfo(remote_bd_addr, &dev_type, &addr_type);
+ if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM )
+ transport = BT_TRANSPORT_LE;
+ }
+ else
+ transport = bta_dm_search_cb.transport;
+#endif
+
APPL_TRACE_DEBUG6("bta_dm_discover_device, BDA:0x%02X%02X%02X%02X%02X%02X",
remote_bd_addr[0],remote_bd_addr[1],
@@ -2408,7 +2444,7 @@
&& (( bta_dm_search_cb.p_btm_inq_info == NULL )
||(bta_dm_search_cb.p_btm_inq_info && (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name))))
{
- if( bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr) == TRUE )
+ if(bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, transport) == TRUE)
{
return;
}
@@ -2447,7 +2483,7 @@
/* check whether connection already exists to the device
if connection exists, we don't have to wait for ACL
link to go down to start search on next device */
- if(BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr))
+ if (BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr, BT_TRANSPORT_BR_EDR))
bta_dm_search_cb.wait_disc = FALSE;
else
bta_dm_search_cb.wait_disc = TRUE;
@@ -2461,8 +2497,7 @@
bta_dm_search_cb.services_to_search
);
}
- if (BTM_UseLeLink(bta_dm_search_cb.peer_bdaddr))
- /*
+ if (transport == BT_TRANSPORT_LE) /*
if ( bta_dm_search_cb.p_btm_inq_info != NULL &&
bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE &&
(bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK))*/
@@ -2560,7 +2595,7 @@
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;
-
+ result.inq_res.flag = p_inq->flag;
#endif
/* application will parse EIR to find out remote device name */
@@ -2650,7 +2685,8 @@
{
/* get name of device */
btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
- (tBTM_CMPL_CB *) bta_dm_remname_cback);
+ (tBTM_CMPL_CB *) bta_dm_remname_cback,
+ BT_TRANSPORT_BR_EDR);
if ( btm_status == BTM_BUSY )
{
/* wait for next chance(notification of remote name discovery done) */
@@ -2692,9 +2728,12 @@
bta_dm_search_cb.peer_name[BD_NAME_LEN]=0;
BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
#if BLE_INCLUDED == TRUE
- if (BTM_UseLeLink(bta_dm_search_cb.peer_bdaddr))
- GAP_BleReadPeerPrefConnParams (bta_dm_search_cb.peer_bdaddr);
+ if (bta_dm_search_cb.transport == BT_TRANSPORT_LE )
+ {
+ GAP_BleReadPeerPrefConnParams (bta_dm_search_cb.peer_bdaddr);
+ }
#endif
if ((p_msg = (tBTA_DM_REM_NAME *) GKI_getbuf(sizeof(tBTA_DM_REM_NAME))) != NULL)
{
@@ -2857,7 +2896,7 @@
bta_dm_cb.pin_evt = BTA_DM_PIN_REQ_EVT;
bdcpy(bta_dm_cb.pin_bd_addr, bd_addr);
BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, dev_class);
- if ((BTM_ReadRemoteDeviceName(bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
+ if ((BTM_ReadRemoteDeviceName(bd_addr, bta_dm_pinname_cback, BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
return BTM_CMD_STARTED;
APPL_TRACE_WARNING0(" bta_dm_pin_cback() -> Failed to start Remote Name Request ");
@@ -3045,22 +3084,56 @@
/*case BTM_SP_KEY_REQ_EVT: */
case BTM_SP_KEY_NOTIF_EVT:
#endif
- bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
- /* If the device name is not known, save bdaddr and devclass and initiate a name request */
- if (p_data->key_notif.bd_name[0] == 0)
+ if(BTM_SP_CFM_REQ_EVT == event)
{
- bta_dm_cb.pin_evt = pin_evt;
- bdcpy(bta_dm_cb.pin_bd_addr, p_data->key_notif.bd_addr);
- BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->key_notif.dev_class);
- if ((BTM_ReadRemoteDeviceName(p_data->key_notif.bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
- return BTM_CMD_STARTED;
-
- APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request ");
+ /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
+ call remote name request using values from cfm_req */
+ if(p_data->cfm_req.bd_name[0] == 0)
+ {
+ bta_dm_cb.pin_evt = pin_evt;
+ bdcpy(bta_dm_cb.pin_bd_addr, p_data->cfm_req.bd_addr);
+ BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->cfm_req.dev_class);
+ if ((BTM_ReadRemoteDeviceName(p_data->cfm_req.bd_addr, bta_dm_pinname_cback,
+ BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
+ return BTM_CMD_STARTED;
+ APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request ");
+ }
+ else
+ {
+ /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
+ copy these values into key_notif from cfm_req */
+ bdcpy(sec_event.key_notif.bd_addr, p_data->cfm_req.bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->cfm_req.dev_class);
+ BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME),
+ (char*)p_data->cfm_req.bd_name, (BD_NAME_LEN-1));
+ sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
+ }
}
- bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
- BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
- BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), (char*)p_data->key_notif.bd_name, (BD_NAME_LEN-1));
- sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
+ if (BTM_SP_KEY_NOTIF_EVT == event)
+ {
+ /* If the device name is not known, save bdaddr and devclass
+ and initiate a name request with values from key_notif */
+ if(p_data->key_notif.bd_name[0] == 0)
+ {
+ bta_dm_cb.pin_evt = pin_evt;
+ bdcpy(bta_dm_cb.pin_bd_addr, p_data->key_notif.bd_addr);
+ BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->key_notif.dev_class);
+ if ((BTM_ReadRemoteDeviceName(p_data->key_notif.bd_addr, bta_dm_pinname_cback,
+ BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
+ return BTM_CMD_STARTED;
+ APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request ");
+ }
+ else
+ {
+ bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
+ BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME),
+ (char*)p_data->key_notif.bd_name, (BD_NAME_LEN-1));
+ sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
+ }
+ }
bta_dm_cb.p_sec_cback(pin_evt, &sec_event);
@@ -3076,17 +3149,18 @@
/* If the device name is not known, save bdaddr and devclass and initiate a name request */
if (p_data->rmt_oob.bd_name[0] == 0)
{
- bta_dm_cb.pin_evt = BTA_DM_SP_RMT_OOB_EVT;
- bdcpy(bta_dm_cb.pin_bd_addr, p_data->rmt_oob.bd_addr);
- BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->rmt_oob.dev_class);
- if ((BTM_ReadRemoteDeviceName(p_data->rmt_oob.bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
- return BTM_CMD_STARTED;
+ bta_dm_cb.pin_evt = BTA_DM_SP_RMT_OOB_EVT;
+ bdcpy(bta_dm_cb.pin_bd_addr, p_data->rmt_oob.bd_addr);
+ BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->rmt_oob.dev_class);
+ if ((BTM_ReadRemoteDeviceName(p_data->rmt_oob.bd_addr, bta_dm_pinname_cback,
+ BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
+ return BTM_CMD_STARTED;
+ APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request ");
+ }
- APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request ");
- }
- bdcpy(sec_event.rmt_oob.bd_addr, p_data->rmt_oob.bd_addr);
- BTA_COPY_DEVICE_CLASS(sec_event.rmt_oob.dev_class, p_data->rmt_oob.dev_class);
- BCM_STRNCPY_S((char*)sec_event.rmt_oob.bd_name, sizeof(BD_NAME), (char*)p_data->rmt_oob.bd_name, (BD_NAME_LEN-1));
+ bdcpy(sec_event.rmt_oob.bd_addr, p_data->rmt_oob.bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.rmt_oob.dev_class, p_data->rmt_oob.dev_class);
+ BCM_STRNCPY_S((char*)sec_event.rmt_oob.bd_name, sizeof(BD_NAME), (char*)p_data->rmt_oob.bd_name, (BD_NAME_LEN-1));
sec_event.rmt_oob.bd_name[BD_NAME_LEN-1] = 0;
bta_dm_cb.p_sec_cback(BTA_DM_SP_RMT_OOB_EVT, &sec_event);
@@ -3228,9 +3302,17 @@
case BTM_BL_CONN_EVT:
p_msg->is_new = TRUE;
bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+#if BLE_INCLUDED == TRUE
+ p_msg->transport = p_data->conn.transport;
+ p_msg->handle = p_data->conn.handle;
+#endif
break;
case BTM_BL_DISCN_EVT:
bdcpy(p_msg->bd_addr, p_data->discn.p_bda);
+#if BLE_INCLUDED == TRUE
+ p_msg->transport = p_data->discn.transport;
+ p_msg->handle = p_data->discn.handle;
+#endif
break;
case BTM_BL_UPDATE_EVT:
p_msg->busy_level = p_data->update.busy_level;
@@ -3241,9 +3323,9 @@
p_msg->hci_status = p_data->role_chg.hci_status;
bdcpy(p_msg->bd_addr, p_data->role_chg.p_bda);
break;
- case BTM_BL_COLLISION_EVT:
- bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
- break;;
+ case BTM_BL_COLLISION_EVT:
+ bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+ break;
}
p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
@@ -3265,7 +3347,8 @@
**
*******************************************************************************/
static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn,
- UINT8 *features, BOOLEAN is_new)
+ UINT8 *features, BOOLEAN is_new,UINT16 handle,
+ tBT_TRANSPORT transport)
{
tBTA_DM_ACL_CHANGE * p_msg;
@@ -3274,7 +3357,10 @@
{
bdcpy (p_msg->bd_addr, p_bda);
p_msg->is_new = is_new;
-
+#if BLE_INCLUDED == TRUE
+ p_msg->handle = handle;
+ p_msg->transport = transport;
+#endif
/* This is collision case */
if (features != NULL)
{
@@ -3387,6 +3473,7 @@
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
tBTA_DM_PEER_DEVICE *p_dev;
+ memset(&conn, 0, sizeof(tBTA_DM_SEC));
switch(p_data->acl_change.event)
{
@@ -3438,7 +3525,7 @@
bdcpy(conn.role_chg.bd_addr, p_bda);
conn.role_chg.new_role = (UINT8) p_data->acl_change.new_role;
if( bta_dm_cb.p_sec_cback )
- bta_dm_cb.p_sec_cback(BTA_DM_ROLE_CHG_EVT, &conn);
+ bta_dm_cb.p_sec_cback(BTA_DM_ROLE_CHG_EVT, (tBTA_DM_SEC *)&conn);
}
return;
}
@@ -3455,7 +3542,11 @@
{
for(i=0; i<bta_dm_cb.device_list.count; i++)
{
- if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda))
+ if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda)
+#if BLE_INCLUDED == TRUE
+ && bta_dm_cb.device_list.peer_device[i].conn_handle == p_data->acl_change.handle
+#endif
+ )
break;
}
@@ -3465,14 +3556,24 @@
bdcpy(bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].peer_bdaddr, p_bda);
bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].link_policy = bta_dm_cb.cur_policy;
bta_dm_cb.device_list.count++;
+#if BLE_INCLUDED == TRUE
+ bta_dm_cb.device_list.peer_device[i].conn_handle = p_data->acl_change.handle;
+ if (p_data->acl_change.transport == BT_TRANSPORT_LE)
+ bta_dm_cb.device_list.le_count++;
+#endif
}
bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_CONNECTED;
bta_dm_cb.device_list.peer_device[i].pref_role = BTA_ANY_ROLE;
bdcpy(conn.link_up.bd_addr, p_bda);
bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_NONE;
- if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
- ((NULL != (p = BTM_ReadRemoteFeatures (p_bda))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) )
+#if BLE_INCLUDED == TRUE
+ conn.link_up.link_type = p_data->acl_change.transport;
+ bta_dm_cb.device_list.peer_device[i].transport = p_data->acl_change.transport;
+#endif
+
+ if (((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+ ((NULL != (p = BTM_ReadRemoteFeatures (p_bda))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)))
{
/* both local and remote devices support SSR */
bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_USE_SSR;
@@ -3486,17 +3587,23 @@
{
for(i=0; i<bta_dm_cb.device_list.count; i++)
{
- if(bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda))
+ if (bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda)
+#if BLE_INCLUDED == TRUE
+ ||bta_dm_cb.device_list.peer_device[i].transport != p_data->acl_change.transport
+#endif
+ )
continue;
if( bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING )
{
- BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
+ if (BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr))
+ {
#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
- /* remove all cached GATT information */
- BTA_GATTC_Refresh(p_bda);
+ /* remove all cached GATT information */
+ BTA_GATTC_Refresh(p_bda);
#endif
- issue_unpair_cb = TRUE;
+ issue_unpair_cb = TRUE;
+ }
}
conn.link_down.is_removed = bta_dm_cb.device_list.peer_device[i].remove_dev_pending;
@@ -3509,6 +3616,12 @@
}
if(bta_dm_cb.device_list.count)
bta_dm_cb.device_list.count--;
+#if BLE_INCLUDED == TRUE
+ if ((p_data->acl_change.transport == BT_TRANSPORT_LE) &&
+ (bta_dm_cb.device_list.le_count))
+ bta_dm_cb.device_list.le_count--;
+ conn.link_down.link_type = p_data->acl_change.transport;
+#endif
if(bta_dm_search_cb.wait_disc && !bdcmp(bta_dm_search_cb.peer_bdaddr, p_bda))
{
@@ -3786,7 +3899,8 @@
static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
{
UINT16 index = 0;
- if (BTM_IsAclConnectionUp(remote_bd_addr))
+ if ( BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_LE) ||
+ BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_BR_EDR))
{
APPL_TRACE_DEBUG1("%s ACL is not down. Schedule for Dev Removal when ACL closes",
__FUNCTION__);
@@ -3832,14 +3946,18 @@
UINT8 i;
BOOLEAN set_master_role = FALSE;
-
- if(bta_dm_cb.device_list.count)
+#if BLE_INCLUDED == TRUE
+ UINT8 br_count = bta_dm_cb.device_list.count - bta_dm_cb.device_list.le_count;
+#else
+ UINT8 br_count = bta_dm_cb.device_list.count;
+#endif
+ if (br_count)
{
/* the configuration is no scatternet
* or AV connection exists and there are more than one ACL link */
- if( (p_bta_dm_rm_cfg[0].cfg == BTA_DM_NO_SCATTERNET) ||
- (bta_dm_cb.cur_av_count && bta_dm_cb.device_list.count > 1) )
+ if ( (p_bta_dm_rm_cfg[0].cfg == BTA_DM_NO_SCATTERNET) ||
+ (bta_dm_cb.cur_av_count && br_count > 1) )
{
L2CA_SetDesireRole (HCI_ROLE_MASTER);
@@ -3849,7 +3967,11 @@
for(i=0; i<bta_dm_cb.device_list.count; i++)
{
- if(bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
+ if (bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED
+#if BLE_INCLUDED == TRUE
+ && bta_dm_cb.device_list.peer_device[i].transport == BT_TRANSPORT_BR_EDR
+#endif
+ )
{
if(!set_master_role && (bta_dm_cb.device_list.peer_device[i].pref_role != BTA_ANY_ROLE)
&& (p_bta_dm_rm_cfg[0].cfg == BTA_DM_PARTIAL_SCATTERNET))
@@ -3859,7 +3981,7 @@
}
if((bta_dm_cb.device_list.peer_device[i].pref_role == BTA_MASTER_ROLE_ONLY)
- || (bta_dm_cb.device_list.count > 1))
+ || (br_count > 1))
{
/* Initiating immediate role switch with certain remote devices
@@ -4509,13 +4631,26 @@
** Returns None
**
*******************************************************************************/
-void bta_dm_encrypt_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+void bta_dm_encrypt_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, tBTM_STATUS result)
{
tBTA_STATUS bta_status = BTA_SUCCESS;
- tBTA_DM_ENCRYPT_CBACK *p_callback = bta_dm_cb.p_encrypt_cback;
+ tBTA_DM_ENCRYPT_CBACK *p_callback = NULL;
+ UINT8 i ;
UNUSED(p_ref_data);
- bta_dm_cb.p_encrypt_cback = NULL;
+ for (i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ if (bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, bd_addr) == 0 &&
+ bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
+ break;
+ }
+
+ if (i < bta_dm_cb.device_list.count)
+ {
+ p_callback = bta_dm_cb.device_list.peer_device[i].p_encrypt_cback;
+ bta_dm_cb.device_list.peer_device[i].p_encrypt_cback = NULL;
+ }
+
switch (result)
{
case BTM_SUCCESS:
@@ -4538,7 +4673,7 @@
if (p_callback)
{
- (*p_callback)(bd_addr, bta_status);
+ (*p_callback)(bd_addr, transport, bta_status);
}
}
/*******************************************************************************
@@ -4552,6 +4687,7 @@
*******************************************************************************/
void bta_dm_set_encryption (tBTA_DM_MSG *p_data)
{
+ UINT8 i ;
APPL_TRACE_DEBUG0("bta_dm_set_encryption"); //todo
if (!p_data->set_encryption.p_callback)
@@ -4560,16 +4696,35 @@
return;
}
- if (bta_dm_cb.p_encrypt_cback)
+ for (i=0; i<bta_dm_cb.device_list.count; i++)
{
- (*p_data->set_encryption.p_callback)(p_data->set_encryption.bd_addr, BTA_BUSY);
- return;
+ if (bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_data->set_encryption.bd_addr) == 0 &&
+ bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
+ break;
}
+ if (i < bta_dm_cb.device_list.count)
+ {
+ if (bta_dm_cb.device_list.peer_device[i].p_encrypt_cback)
+ {
+ APPL_TRACE_ERROR0("earlier enc was not done for same device");
+ (*p_data->set_encryption.p_callback)(p_data->set_encryption.bd_addr,
+ p_data->set_encryption.transport, BTA_BUSY);
+ return;
+ }
-
- bta_dm_cb.p_encrypt_cback = p_data->set_encryption.p_callback;
- bta_dm_cb.sec_act = p_data->set_encryption.sec_act;
- BTM_SetEncryption(p_data->set_encryption.bd_addr, bta_dm_encrypt_cback, &bta_dm_cb.sec_act);
+ if (BTM_SetEncryption(p_data->set_encryption.bd_addr,
+ p_data->set_encryption.transport,
+ bta_dm_encrypt_cback,
+ &p_data->set_encryption.sec_act)
+ == BTM_CMD_STARTED)
+ {
+ bta_dm_cb.device_list.peer_device[i].p_encrypt_cback = p_data->set_encryption.p_callback;
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1(" %s Device not found/not connected", __FUNCTION__);
+ }
}
/*******************************************************************************
@@ -4992,7 +5147,42 @@
BTM_BleSetConnScanParams(p_data->ble_set_scan_params.scan_int,
p_data->ble_set_scan_params.scan_window);
}
+/*******************************************************************************
+**
+** Function bta_dm_ble_update_conn_params
+**
+** Description This function update LE connection parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data)
+{
+ if (!L2CA_UpdateBleConnParams(p_data->ble_update_conn_params.bd_addr,
+ p_data->ble_update_conn_params.min_int,
+ p_data-> ble_update_conn_params.max_int,
+ p_data->ble_update_conn_params.latency,
+ p_data->ble_update_conn_params.timeout))
+ {
+ APPL_TRACE_ERROR0("Update connection parameters failed!");
+ }
+}
+#if BLE_PRIVACY_SPT == TRUE
+/*******************************************************************************
+**
+** Function bta_dm_ble_config_local_privacy
+**
+** Description This function set the local device LE privacy settings.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data)
+{
+ BTM_BleConfigPrivacy (p_data->ble_local_privacy.privacy_enable);
+}
+#endif
/*******************************************************************************
**
@@ -5012,7 +5202,7 @@
/*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)
+ bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb))!= BTM_CMD_STARTED)
{
tBTA_DM_SEARCH data;
APPL_TRACE_WARNING2(" %s BTM_BleObserve failed. status %d",__FUNCTION__,status);
@@ -5057,8 +5247,16 @@
*******************************************************************************/
void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data)
{
- BTM_BleWriteAdvData(p_data->ble_set_adv_data.data_mask,
- (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg);
+ tBTA_STATUS status = BTA_FAILURE;
+
+ if (BTM_BleWriteAdvData(p_data->ble_set_adv_data.data_mask,
+ (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS)
+ {
+ status = BTA_SUCCESS;
+ }
+
+ if (p_data->ble_set_adv_data.p_adv_data_cback)
+ (*p_data->ble_set_adv_data.p_adv_data_cback)(status);
}
/*******************************************************************************
@@ -5072,8 +5270,16 @@
*******************************************************************************/
void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data)
{
- BTM_BleWriteScanRsp(p_data->ble_set_adv_data.data_mask,
- (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg);
+ tBTA_STATUS status = BTA_FAILURE;
+
+ if(BTM_BleWriteScanRsp(p_data->ble_set_adv_data.data_mask,
+ (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS)
+ {
+ status = BTA_SUCCESS;
+ }
+
+ if (p_data->ble_set_adv_data.p_adv_data_cback)
+ (*p_data->ble_set_adv_data.p_adv_data_cback)(status);
}
/*******************************************************************************
@@ -5090,6 +5296,71 @@
BTM_BleBroadcast(p_data->ble_observe.start);
}
+/*******************************************************************************
+**
+** Function bta_dm_ble_multi_adv_enb
+**
+** Description This function enables a single advertising instance
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+ BTM_BleEnableAdvInstance((tBTM_BLE_ADV_PARAMS*)p_data->ble_multi_adv_enb.p_params,
+ p_data->ble_multi_adv_enb.p_cback,p_data->ble_multi_adv_enb.p_ref);
+#endif
+}
+/*******************************************************************************
+**
+** Function bta_dm_ble_multi_adv_param_upd
+**
+** Description This function updates multiple advertising instance parameters
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+ BTM_BleUpdateAdvInstParam(p_data->ble_multi_adv_param.inst_id,
+ (tBTM_BLE_ADV_PARAMS*)p_data->ble_multi_adv_param.p_params);
+#endif
+}
+/*******************************************************************************
+**
+** Function bta_dm_ble_multi_adv_data
+**
+** Description This function write multiple advertising instance adv data
+** or scan response data
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+ BTM_BleCfgAdvInstData(p_data->ble_multi_adv_data.inst_id,p_data->ble_multi_adv_data.is_scan_rsp,
+ p_data->ble_multi_adv_data.data_mask,(tBTM_BLE_ADV_DATA*)p_data->ble_multi_adv_data.p_data);
+#endif
+}
+/*******************************************************************************
+**
+** Function btm_dm_ble_multi_adv_disable
+**
+** Description This function disable a single adv instance
+**
+** Parameters:
+**
+*******************************************************************************/
+void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+ BTM_BleDisableAdvInstance(p_data->ble_multi_adv_disable.inst_id);
+#endif
+}
+
#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
#ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT
#define BTA_DM_GATT_CLOSE_DELAY_TOUT 1000
@@ -5311,7 +5582,7 @@
btm_dm_start_disc_gatt_services(bta_dm_search_cb.conn_id);
}
else
- BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE);
+ BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE, BTA_GATT_TRANSPORT_LE);
}
/*******************************************************************************
@@ -5424,6 +5695,48 @@
break;
}
}
-
#endif /* BTA_GATT_INCLUDED */
+
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+/*******************************************************************************
+**
+** Function bta_dm_enable_scan_filter
+**
+** Description This function enable/disable adv payload filtering condition
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_enable_scan_filter (tBTA_DM_MSG *p_data)
+{
+ tBTA_SYS_VS_BLE_SCAN_PF_ENABLE param;
+
+ param.enable = p_data->ble_enable_scan_filter.enable;
+ param.p_target = p_data->ble_enable_scan_filter.p_target;
+ param.p_cmpl_cback = p_data->ble_enable_scan_filter.p_cmpl_cback;
+
+ bta_sys_vs_hdl(BTA_VS_BLE_SCAN_PF_ENABLE_EVT, (void *)¶m);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_cfg_filter_cond
+**
+** Description This function configure adv payload filtering condition
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data)
+{
+ tBTA_SYS_VS_BLE_SCAN_PF_COND param;
+
+ param.action = p_data->ble_cfg_filter_cond.action;
+ param.cond_type = p_data->ble_cfg_filter_cond.cond_type;
+ param.p_cond = (void *)p_data->ble_cfg_filter_cond.p_cond_param;
+ param.p_cmpl_cback = p_data->ble_cfg_filter_cond.p_cmpl_cback;
+
+ bta_sys_vs_hdl(BTA_VS_BLE_SCAN_PF_COND_EVT, (void *)¶m);
+}
+#endif /* BLE_ANDROID_CONTROLLER_SCAN_FILTER */
#endif /* BLE_INCLUDED */
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 7db7f7b..ff762f9 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -526,12 +526,29 @@
*******************************************************************************/
void BTA_DmBond(BD_ADDR bd_addr)
{
+ BTA_DmBondByTransport (bd_addr, BTA_TRANSPORT_UNKNOWN);
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmBondByTransports
+**
+** Description This function initiates a bonding procedure with a peer
+** device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBondByTransport(BD_ADDR bd_addr, tBTA_TRANSPORT transport)
+{
tBTA_DM_API_BOND *p_msg;
if ((p_msg = (tBTA_DM_API_BOND *) GKI_getbuf(sizeof(tBTA_DM_API_BOND))) != NULL)
{
p_msg->hdr.event = BTA_DM_API_BOND_EVT;
bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->transport = transport;
bta_sys_sendmsg(p_msg);
}
@@ -1487,6 +1504,9 @@
}
#endif
}
+/*******************************************************************************
+** BLE ADV data management API
+********************************************************************************/
#if BLE_INCLUDED == TRUE
/*******************************************************************************
@@ -1495,19 +1515,26 @@
**
** Description This function is called to override the BTA default ADV parameters.
**
-** Parameters Pointer to User defined ADV data structure
+** Parameters data_mask: adv data mask.
+** p_adv_cfg: Pointer to User defined ADV data structure. This
+** memory space can not be freed until p_adv_data_cback
+** is received.
+** p_adv_data_cback: set adv data complete callback.
**
** Returns None
**
*******************************************************************************/
-void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg)
+void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg,
+ tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
{
tBTA_DM_API_SET_ADV_CONFIG *p_msg;
- if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
+ if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *)
+ GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
{
p_msg->hdr.event = BTA_DM_API_BLE_SET_ADV_CONFIG_EVT;
- p_msg->data_mask = data_mask;
+ p_msg->data_mask = data_mask;
+ p_msg->p_adv_data_cback = p_adv_data_cback;
p_msg->p_adv_cfg = p_adv_cfg;
bta_sys_sendmsg(p_msg);
@@ -1525,14 +1552,17 @@
** Returns None
**
*******************************************************************************/
-BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg)
+BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg,
+ tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
{
tBTA_DM_API_SET_ADV_CONFIG *p_msg;
- if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
+ if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *)
+ GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
{
p_msg->hdr.event = BTA_DM_API_BLE_SET_SCAN_RSP_EVT;
- p_msg->data_mask = data_mask;
+ p_msg->data_mask = data_mask;
+ p_msg->p_adv_data_cback = p_adv_data_cback;
p_msg->p_adv_cfg = p_adv_cfg;
bta_sys_sendmsg(p_msg);
@@ -1599,28 +1629,24 @@
}
#endif
}
+
/*******************************************************************************
**
-** Function BTA_DmDiscoverExt
+** Function bta_dm_discover_send_msg
**
-** Description This function does service discovery for services of a
-** peer device. When services.num_uuid is 0, it indicates all
-** GATT based services are to be searched; other wise a list of
-** UUID of interested services should be provided through
-** p_services->p_uuid.
-**
-**
+** Description This function send discover message to BTA task.
**
** Returns void
**
*******************************************************************************/
-void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
- tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+static void bta_dm_discover_send_msg(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
+ tBTA_TRANSPORT transport)
{
-#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
tBTA_DM_API_DISCOVER *p_msg;
- UINT16 len = p_services ? (sizeof(tBTA_DM_API_DISCOVER) + sizeof(tBT_UUID) * p_services->num_uuid) :
- sizeof(tBTA_DM_API_DISCOVER);
+ UINT16 len = p_services ? (sizeof(tBTA_DM_API_DISCOVER) +
+ sizeof(tBT_UUID) * p_services->num_uuid) :
+ sizeof(tBTA_DM_API_DISCOVER);
if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(len)) != NULL)
{
@@ -1630,6 +1656,7 @@
bdcpy(p_msg->bd_addr, bd_addr);
p_msg->p_cback = p_cback;
p_msg->sdp_search = sdp_search;
+ p_msg->transport = transport;
if (p_services != NULL)
{
@@ -1645,12 +1672,60 @@
bta_sys_sendmsg(p_msg);
}
-#else
- UNUSED(bd_addr);
- UNUSED(p_services);
- UNUSED(p_cback);
- UNUSED(sdp_search);
-#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmDiscoverByTransport
+**
+** Description This function does service discovery on particular transport
+** for services of a
+** peer device. When services.num_uuid is 0, it indicates all
+** GATT based services are to be searched; otherwise a list of
+** UUID of interested services should be provided through
+** p_services->p_uuid.
+**
+** Parameters bd_addr: Bluetooth address of remote device
+** p_services :bit mask of the list of services to be discovered
+** p_cback : Callback on which result will be received
+** sdp_search: if TRUE SDP search will be initiated, else services present in
+** EIR structure of remote device will be returned.
+** transport : Physical transport BR/EDR or LE
+** Returns void
+**
+*******************************************************************************/
+
+void BTA_DmDiscoverByTransport(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
+ tBTA_TRANSPORT transport)
+{
+ bta_dm_discover_send_msg(bd_addr, p_services, p_cback, sdp_search, transport);
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_DmDiscoverExt
+**
+** Description This function does service discovery for services of a
+** peer device. When services.num_uuid is 0, it indicates all
+** GATT based services are to be searched; other wise a list of
+** UUID of interested services should be provided through
+** p_services->p_uuid.
+**
+** Parameters bd_addr: Bluetooth address of remote device
+** p_services :bit mask of the list of services to be discovered
+** p_cback : Callback on which result will be received
+** sdp_search: if TRUE SDP search will be initiated, else services present in
+** EIR structure of remote device will be returned.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+ bta_dm_discover_send_msg(bd_addr, p_services, p_cback, sdp_search, BTA_TRANSPORT_UNKNOWN);
}
@@ -1745,7 +1820,219 @@
*******************************************************************************/
void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable)
{
+#if BLE_INCLUDED == TRUE
+#if BLE_VND_INCLUDED == TRUE && BLE_PRIVACY_SPT == TRUE
+ tBTA_DM_API_LOCAL_PRIVACY *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_LOCAL_PRIVACY *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE_PRIVACY))) != NULL)
+ {
+ memset (p_msg, 0, sizeof(tBTA_DM_API_LOCAL_PRIVACY));
+
+ p_msg->hdr.event = BTA_DM_API_LOCAL_PRIVACY_EVT;
+ p_msg->privacy_enable = privacy_enable;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+#else
UNUSED(privacy_enable);
+#endif
+}
+#endif
+
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function BTA_BleEnableAdvInstance
+**
+** Description This function enable a Multi-ADV instance with the specififed
+** adv parameters
+**
+** Parameters p_params: pointer to the adv parameter structure.
+** p_cback: callback function associated to this adv instance.
+** p_ref: reference data pointer to this adv instance.
+**
+** Returns BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params,
+ tBTA_BLE_MULTI_ADV_CBACK *p_cback,
+ void *p_ref)
+{
+ tBTA_DM_API_BLE_MULTI_ADV_ENB *p_msg;
+ UINT16 len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB);
+
+ APPL_TRACE_API0 ("BTA_BleEnableAdvInstance");
+
+ if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_ENB *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_ENB_EVT;
+ p_msg->p_cback = (void *)p_cback;
+ if (p_params != NULL)
+ {
+ p_msg->p_params = (void *)(p_msg + 1);
+ memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS));
+ }
+ p_msg->p_ref = p_ref;
+
+ bta_sys_sendmsg(p_msg);
+
+ return BTA_SUCCESS;
+ }
+ return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function BTA_BleUpdateAdvInstParam
+**
+** Description This function update a Multi-ADV instance with the specififed
+** adv parameters.
+**
+** Parameters inst_id: Adv instance to update the parameter.
+** p_params: pointer to the adv parameter structure.
+**
+** Returns BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleUpdateAdvInstParam (UINT8 inst_id, tBTA_BLE_ADV_PARAMS *p_params)
+{
+ tBTA_DM_API_BLE_MULTI_ADV_PARAM *p_msg;
+ UINT16 len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM);
+
+ APPL_TRACE_API0 ("BTA_BleUpdateAdvInstParam");
+ if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTA_BLE_MULTI_ADV_ILLEGAL)
+ {
+ if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_PARAM *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT;
+ p_msg->inst_id = inst_id;
+ p_msg->p_params = (void *)(p_msg + 1);
+ memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS));
+
+ bta_sys_sendmsg(p_msg);
+
+ return BTA_SUCCESS;
+ }
+ }
+ return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function BTA_BleCfgAdvInstData
+**
+** Description This function configure a Multi-ADV instance with the specififed
+** adv data or scan response data.
+**
+** Parameter inst_id: Adv instance to configure the adv data or scan response.
+** is_scan_rsp: is the data scan response or adv data.
+** data_mask: adv data type as bit mask.
+** p_data: pointer to the ADV data structure tBTA_BLE_ADV_DATA. This
+** memory space can not be freed until BTA_BLE_MULTI_ADV_DATA_EVT
+** is sent to application.
+**
+** Returns BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+ tBTA_BLE_AD_MASK data_mask,
+ tBTA_BLE_ADV_DATA *p_data)
+{
+ tBTA_DM_API_BLE_MULTI_ADV_DATA *p_msg;
+ UINT16 len = sizeof(tBTA_DM_API_BLE_MULTI_ADV_DATA) ;
+
+ APPL_TRACE_API0 ("BTA_BleCfgAdvInstData");
+
+ if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTA_BLE_MULTI_ADV_ILLEGAL)
+ {
+ if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DATA *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_msg, 0, len);
+
+ p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_DATA_EVT;
+ p_msg->inst_id = inst_id;
+ p_msg->is_scan_rsp = is_scan_rsp;
+ p_msg->data_mask = data_mask;
+ p_msg->p_data = p_data;
+
+ bta_sys_sendmsg(p_msg);
+
+ return BTA_SUCCESS;
+ }
+ }
+ return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function BTA_BleDisableAdvInstance
+**
+** Description This function disable a Multi-ADV instance.
+**
+** Parameter inst_id: instance ID to disable.
+**
+** Returns BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleDisableAdvInstance (UINT8 inst_id)
+{
+ tBTA_DM_API_BLE_MULTI_ADV_DISABLE *p_msg;
+
+ APPL_TRACE_API1 ("BTA_BleDisableAdvInstance: %d", inst_id);
+
+ if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTA_BLE_MULTI_ADV_ILLEGAL)
+ {
+ if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DISABLE *)
+ GKI_getbuf(sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE));
+ p_msg->hdr.event = BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT;
+ p_msg->inst_id = inst_id;
+ bta_sys_sendmsg(p_msg);
+ return BTA_SUCCESS;
+ }
+ }
+ return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmBleUpdateConnectionParams
+**
+** Description Update connection parameters, can only be used when connection is up.
+**
+** Parameters: bd_addr - BD address of the peer
+** min_int - minimum connection interval, [0x0004~ 0x4000]
+** max_int - maximum connection interval, [0x0004~ 0x4000]
+** latency - slave latency [0 ~ 500]
+** timeout - supervision timeout [0x000a ~ 0xc80]
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int,
+ UINT16 latency, UINT16 timeout)
+{
+ tBTA_DM_API_UPDATE_CONN_PARAM *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_UPDATE_CONN_PARAM *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM))) != NULL)
+ {
+ memset (p_msg, 0, sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
+
+ p_msg->hdr.event = BTA_DM_API_UPDATE_CONN_PARAM_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->min_int = min_int;
+ p_msg->max_int = max_int;
+ p_msg->latency = latency;
+ p_msg->timeout = timeout;
+
+ bta_sys_sendmsg(p_msg);
+ }
}
#endif
@@ -1759,6 +2046,7 @@
** bring up unencrypted links, then later encrypt them.
**
** Parameters: bd_addr - Address of the peer device
+** transport - transport of the link to be encruypted
** p_callback - Pointer to callback function to indicat the
** link encryption status
** sec_act - This is the security action to indicate
@@ -1770,7 +2058,7 @@
** Returns void
**
*******************************************************************************/
-void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
+void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_DM_ENCRYPT_CBACK *p_callback,
tBTA_DM_BLE_SEC_ACT sec_act)
{
tBTA_DM_API_SET_ENCRYPTION *p_msg;
@@ -1783,6 +2071,7 @@
p_msg->hdr.event = BTA_DM_API_SET_ENCRYPTION_EVT;
memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
+ p_msg->transport = transport;
p_msg->p_callback = p_callback;
p_msg->sec_act = sec_act;
@@ -1803,7 +2092,7 @@
** Returns void
**
*******************************************************************************/
-void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev)
+void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transport)
{
tBTA_DM_API_REMOVE_ACL *p_msg;
@@ -1817,6 +2106,7 @@
memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
p_msg->remove_dev = remove_dev;
+ p_msg->transport = transport;
bta_sys_sendmsg(p_msg);
}
@@ -1841,8 +2131,6 @@
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);
@@ -1858,6 +2146,5 @@
bta_sys_sendmsg(p_msg);
}
-#endif
}
#endif
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
index cdc623d..e1fdcc5 100644
--- a/bta/dm/bta_dm_cfg.c
+++ b/bta/dm/bta_dm_cfg.c
@@ -168,12 +168,12 @@
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
- {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {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_SNIFF3, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */
- {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */
+ {{BTA_DM_PM_SNIFF_SCO_OPEN_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_RETRY, 5000}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
@@ -191,7 +191,7 @@
{{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_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open sniff */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open sniff */
{{BTA_DM_PM_PARK, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close park */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
@@ -225,14 +225,14 @@
(BTA_DM_PM_SSR3), /* the SSR entry */
#endif
{
- {{BTA_DM_PM_SNIFF4, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 5000}, {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 */
- {{BTA_DM_PM_SNIFF2, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
- {{BTA_DM_PM_SNIFF4, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_SNIFF_HD_IDLE_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
@@ -244,13 +244,13 @@
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
- {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {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 */
- {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
@@ -263,14 +263,14 @@
(BTA_DM_PM_SSR1), /* the SSR entry */
#endif
{
- {{BTA_DM_PM_SNIFF2, 30000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_SNIFF_HH_OPEN_IDX, BTA_DM_PM_HH_OPEN_DELAY},{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, 30000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
- {{BTA_DM_PM_SNIFF2, 30000}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_SNIFF_HH_IDLE_IDX, BTA_DM_PM_HH_IDLE_DELAY}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_HH_ACTIVE_IDX, BTA_DM_PM_HH_ACTIVE_DELAY}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
@@ -288,7 +288,7 @@
{{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 */
- {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
@@ -307,7 +307,7 @@
{{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 */
- {{BTA_DM_PM_SNIFF, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
@@ -320,7 +320,7 @@
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
- {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {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 */
@@ -345,7 +345,7 @@
{{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 */
- {{BTA_DM_PM_SNIFF, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
@@ -364,7 +364,7 @@
{{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 */
- {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
@@ -378,13 +378,13 @@
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
- {{BTA_DM_PM_SNIFF, 10000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 10000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_ACTIVE, 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 */
- {{BTA_DM_PM_SNIFF, 10000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, 10000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
#if (AMP_INCLUDED == TRUE)
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* amp */
@@ -427,21 +427,29 @@
#endif /* BTE_SIM_APP */
};
+/* Please refer to the SNIFF table definitions in bta_api.h.
+ *
+ * Adding to or Modifying the Table
+ * Additional sniff parameter entries can be added for BTA_DM_PM_SNIFF5 - BTA_DM_PM_SNIFF7.
+ * Overrides of additional table entries can be specified in bdroid_buildcfg.h. If additional
+ * sniff parameter entries are added or an override of an existing entry is specified in
+ * bdroid_buildcfg.h then the BTA_DM_PM_*_IDX defines in bta_api.h will need to be match the new
+ * ordering.
+ *
+ * Table Ordering
+ * Sniff Table entries must be ordered from highest latency (biggest interval) to lowest latency.
+ * If there is a conflict among the connected services the setting with the lowest latency will
+ * be selected.
+ */
tBTA_DM_PM_TYPE_QUALIFIER tBTM_PM_PWR_MD bta_dm_pm_md[] =
{
-/* more sniff parameter entries can be added for BTA_DM_PM_SNIFF3 - BTA_DM_PM_SNIFF7, if needed
-When entries are added or removed, BTA_DM_PM_PARK_IDX needs to be updated to reflect the actual index
-BTA_DM_PM_PARK_IDX is defined in bta_api.h and can be override by the bdroid_buildcfg.h settings.
-The SNIFF table entries must be in the order from highest latency (biggest interval) to lowest latency.
-If there's a conflict among the connected services, the setting with lowest latency wins.
-*/
/* sniff modes: max interval, min interval, attempt, timeout */
- {800, 400, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF - A2DP */
- {400, 200, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF1 */
- {180, 150, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF2- HD idle */
- {150, 50, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF3- SCO open */
- { 54, 30, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF4- HD active*/
- {800, 400, 0, 0, BTM_PM_MD_PARK}
+ {BTA_DM_PM_SNIFF_MAX, BTA_DM_PM_SNIFF_MIN, BTA_DM_PM_SNIFF_ATTEMPT, BTA_DM_PM_SNIFF_TIMEOUT, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF - A2DP */
+ {BTA_DM_PM_SNIFF1_MAX, BTA_DM_PM_SNIFF1_MIN, BTA_DM_PM_SNIFF1_ATTEMPT, BTA_DM_PM_SNIFF1_TIMEOUT, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF1 */
+ {BTA_DM_PM_SNIFF2_MAX, BTA_DM_PM_SNIFF2_MIN, BTA_DM_PM_SNIFF2_ATTEMPT, BTA_DM_PM_SNIFF2_TIMEOUT, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF2- HD idle */
+ {BTA_DM_PM_SNIFF3_MAX, BTA_DM_PM_SNIFF3_MIN, BTA_DM_PM_SNIFF3_ATTEMPT, BTA_DM_PM_SNIFF3_TIMEOUT, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF3- SCO open */
+ {BTA_DM_PM_SNIFF4_MAX, BTA_DM_PM_SNIFF4_MIN, BTA_DM_PM_SNIFF4_ATTEMPT, BTA_DM_PM_SNIFF4_TIMEOUT, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF4- HD active*/
+ {BTA_DM_PM_PARK_MAX, BTA_DM_PM_PARK_MIN, BTA_DM_PM_PARK_ATTEMPT, BTA_DM_PM_PARK_TIMEOUT, BTM_PM_MD_PARK}
#ifdef BTE_SIM_APP /* For Insight builds only */
/* Entries at the end of the bta_dm_pm_md table are user-defined (runtime configurable),
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index dd3e16c..9014501 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -99,10 +99,25 @@
BTA_DM_API_BLE_CONN_PARAM_EVT,
BTA_DM_API_BLE_SCAN_PARAM_EVT,
BTA_DM_API_BLE_OBSERVE_EVT,
+ BTA_DM_API_UPDATE_CONN_PARAM_EVT,
+
+#if BLE_PRIVACY_SPT == TRUE
+ BTA_DM_API_LOCAL_PRIVACY_EVT,
+#endif
+
BTA_DM_API_BLE_ADV_PARAM_EVT,
BTA_DM_API_BLE_SET_ADV_CONFIG_EVT,
BTA_DM_API_BLE_SET_SCAN_RSP_EVT,
BTA_DM_API_BLE_BROADCAST_EVT,
+
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+ BTA_DM_API_CFG_FILTER_COND_EVT,
+ BTA_DM_API_ENABLE_SCAN_FILTER_EVT,
+#endif
+ BTA_DM_API_BLE_MULTI_ADV_ENB_EVT,
+ BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT,
+ BTA_DM_API_BLE_MULTI_ADV_DATA_EVT,
+ BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT,
#endif
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -209,6 +224,7 @@
tBTA_SERVICE_MASK services;
tBTA_DM_SEARCH_CBACK * p_cback;
BOOLEAN sdp_search;
+ tBTA_TRANSPORT transport;
#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
UINT8 num_uuid;
tBT_UUID *p_uuid;
@@ -231,6 +247,7 @@
{
BT_HDR hdr;
BD_ADDR bd_addr;
+ tBTA_TRANSPORT transport;
} tBTA_DM_API_BOND;
/* data type for BTA_DM_API_BOND_CANCEL_EVT */
@@ -238,6 +255,7 @@
{
BT_HDR hdr;
BD_ADDR bd_addr;
+ tBTA_TRANSPORT transport;
} tBTA_DM_API_BOND_CANCEL;
/* data type for BTA_DM_API_PIN_REPLY_EVT */
@@ -365,6 +383,10 @@
UINT8 new_role;
BD_ADDR bd_addr;
UINT8 hci_status;
+#if BLE_INCLUDED == TRUE
+ UINT16 handle;
+ tBT_TRANSPORT transport;
+#endif
} tBTA_DM_ACL_CHANGE;
/* data type for BTA_DM_PM_BTM_STATUS_EVT */
@@ -424,6 +446,7 @@
typedef struct
{
BT_HDR hdr;
+ tBTA_TRANSPORT transport;
tBTA_DM_ENCRYPT_CBACK *p_callback;
tBTA_DM_BLE_SEC_ACT sec_act;
BD_ADDR bd_addr;
@@ -526,11 +549,51 @@
typedef struct
{
BT_HDR hdr;
+ BOOLEAN enable;
+
+}tBTA_DM_API_BLE_FEATURE;
+
+/* multi adv data structure */
+typedef struct
+{
+ BT_HDR hdr;
+ void *p_cback;
+ void *p_ref;
+ tBTA_BLE_ADV_PARAMS *p_params;
+}tBTA_DM_API_BLE_MULTI_ADV_ENB;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 inst_id;
+ tBTA_BLE_ADV_PARAMS *p_params;
+}tBTA_DM_API_BLE_MULTI_ADV_PARAM;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 inst_id;
+ BOOLEAN is_scan_rsp;
+ tBTA_BLE_AD_MASK data_mask;
+ tBTA_BLE_ADV_DATA *p_data;
+}tBTA_DM_API_BLE_MULTI_ADV_DATA;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 inst_id;
+}tBTA_DM_API_BLE_MULTI_ADV_DISABLE;
+
+
+typedef struct
+{
+ BT_HDR hdr;
UINT16 data_mask;
tBTA_BLE_ADV_DATA *p_adv_cfg;
+ tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback;
}tBTA_DM_API_SET_ADV_CONFIG;
-#endif
+#endif /* BLE_INCLUDED */
typedef struct
{
@@ -563,7 +626,37 @@
BT_HDR hdr;
BD_ADDR bd_addr;
BOOLEAN remove_dev;
+ tBTA_TRANSPORT transport;
+
}tBTA_DM_API_REMOVE_ACL;
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ UINT16 min_int;
+ UINT16 max_int;
+ UINT16 latency;
+ UINT16 timeout;
+}tBTA_DM_API_UPDATE_CONN_PARAM;
+
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_BLE_SCAN_COND_OP action;
+ tBTA_DM_BLE_PF_COND_TYPE cond_type;
+ tBTA_DM_BLE_PF_COND_PARAM *p_cond_param;
+ void *p_cmpl_cback;
+}tBTA_DM_API_CFG_FILTER_COND;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN enable;
+ tBLE_BD_ADDR *p_target;
+ void *p_cmpl_cback;
+}tBTA_DM_API_ENABLE_SCAN_FILTER;
+#endif
/* union of all data types */
typedef union
@@ -640,6 +733,15 @@
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;
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+ tBTA_DM_API_ENABLE_SCAN_FILTER ble_enable_scan_filter;
+ tBTA_DM_API_CFG_FILTER_COND ble_cfg_filter_cond;
+#endif
+ tBTA_DM_API_UPDATE_CONN_PARAM ble_update_conn_params;
+ tBTA_DM_API_BLE_MULTI_ADV_ENB ble_multi_adv_enb;
+ tBTA_DM_API_BLE_MULTI_ADV_PARAM ble_multi_adv_param;
+ tBTA_DM_API_BLE_MULTI_ADV_DATA ble_multi_adv_data;
+ tBTA_DM_API_BLE_MULTI_ADV_DISABLE ble_multi_adv_disable;
#endif
tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT set_afh_channel_assessment;
@@ -679,13 +781,15 @@
tBTA_PREF_ROLES pref_role;
BOOLEAN in_use;
tBTA_DM_DEV_INFO info;
+ tBTA_DM_ENCRYPT_CBACK *p_encrypt_cback;
#if (BTM_SSR_INCLUDED == TRUE)
tBTM_PM_STATUS prev_low; /* previous low power mode used */
#endif
tBTA_DM_PM_ACTTION pm_mode_attempted;
tBTA_DM_PM_ACTTION pm_mode_failed;
BOOLEAN remove_dev_pending;
-
+ UINT16 conn_handle;
+ tBT_TRANSPORT transport;
} tBTA_DM_PEER_DEVICE;
@@ -696,7 +800,9 @@
{
tBTA_DM_PEER_DEVICE peer_device[BTA_DM_NUM_PEER_DEVICE];
UINT8 count;
-
+#if BLE_INCLUDED == TRUE
+ UINT8 le_count;
+#endif
} tBTA_DM_ACTIVE_LINK;
@@ -777,8 +883,6 @@
#endif
- tBTA_DM_ENCRYPT_CBACK *p_encrypt_cback;
- tBTA_DM_BLE_SEC_ACT sec_act;
TIMER_LIST_ENT switch_delay_timer;
} tBTA_DM_CB;
@@ -809,7 +913,7 @@
tSDP_UUID uuid;
UINT8 peer_scn;
BOOLEAN sdp_search;
-
+ tBTA_TRANSPORT transport;
#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
tBTA_DM_SEARCH_CBACK * p_scan_cback;
#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
@@ -996,11 +1100,24 @@
extern void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data);
extern void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data);
extern void bta_dm_ble_observe (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data);
+#if BLE_PRIVACY_SPT == TRUE
+extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data);
+#endif
extern void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data);
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+extern void bta_dm_enable_scan_filter (tBTA_DM_MSG *p_data);
+extern void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data);
+#endif
+extern void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_enb(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);
@@ -1035,6 +1152,10 @@
extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data);
extern tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr);
+#if BLE_PRIVACY_SPT == TRUE
+extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data);
+#endif
+
extern void bta_dm_pm_active(BD_ADDR peer_addr);
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index 0f6b91a..c68dac55 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -96,10 +96,22 @@
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,
+ bta_dm_ble_update_conn_params, /* BTA_DM_API_UPDATE_CONN_PARAM_EVT */
+#if BLE_PRIVACY_SPT == TRUE
+ bta_dm_ble_config_local_privacy, /* BTA_DM_API_LOCAL_PRIVACY_EVT */
+#endif
bta_dm_ble_set_adv_params, /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
bta_dm_ble_set_adv_config, /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */
bta_dm_ble_set_scan_rsp, /* BTA_DM_API_BLE_SET_SCAN_RSP_EVT */
bta_dm_ble_broadcast, /* BTA_DM_API_BLE_BROADCAST_EVT */
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+ bta_dm_cfg_filter_cond, /* BTA_DM_API_CFG_FILTER_COND_EVT */
+ bta_dm_enable_scan_filter, /* BTA_DM_API_ENABLE_SCAN_FILTER_EVT */
+#endif
+ bta_dm_ble_multi_adv_enb, /* BTA_DM_API_BLE_MULTI_ADV_ENB_EVT*/
+ bta_dm_ble_multi_adv_upd_param, /* BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT */
+ bta_dm_ble_multi_adv_data, /* BTA_DM_API_BLE_MULTI_ADV_DATA_EVT */
+ btm_dm_ble_multi_adv_disable, /* BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT */
#endif
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 44f88e4..fd0ac5b 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -45,7 +45,8 @@
** Constants
*****************************************************************************/
static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
- BOOLEAN connected, tGATT_DISCONN_REASON reason);
+ BOOLEAN connected, tGATT_DISCONN_REASON reason,
+ tBT_TRANSPORT transport);
static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
tGATT_CL_COMPLETE *p_data);
@@ -339,7 +340,8 @@
if (p_msg->api_conn.is_direct)
{
if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if,
- p_msg->api_conn.remote_bda)) != NULL)
+ p_msg->api_conn.remote_bda,
+ p_msg->api_conn.transport)) != NULL)
{
bta_gattc_sm_execute(p_clcb, event, p_msg);
}
@@ -351,7 +353,7 @@
BTA_GATT_NO_RESOURCES,
p_msg->api_conn.remote_bda,
BTA_GATT_INVALID_CONN_ID,
- 0);
+ p_msg->api_conn.transport, 0);
}
}
else
@@ -385,7 +387,8 @@
if (p_msg->api_cancel_conn.is_direct)
{
if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->api_cancel_conn.client_if,
- p_msg->api_cancel_conn.remote_bda)) != NULL)
+ p_msg->api_cancel_conn.remote_bda,
+ BTA_GATT_TRANSPORT_LE)) != NULL)
{
bta_gattc_sm_execute(p_clcb, event, p_msg);
}
@@ -476,6 +479,7 @@
BTA_GATT_OK,
p_clcb->bda,
p_clcb->bta_conn_id,
+ p_clcb->transport,
0);
}
/*******************************************************************************
@@ -495,8 +499,8 @@
BTA_GATT_ERROR,
p_clcb->bda,
p_clcb->bta_conn_id,
+ p_clcb->transport,
0);
-
/* open failure, remove clcb */
bta_gattc_clcb_dealloc(p_clcb);
}
@@ -515,7 +519,8 @@
tBTA_GATTC_DATA gattc_data;
/* open/hold a connection */
- if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, TRUE))
+ if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda,
+ TRUE, p_data->api_conn.transport))
{
APPL_TRACE_ERROR0("Connection open failure");
@@ -526,7 +531,8 @@
/* a connected remote device */
if (GATT_GetConnIdIfConnected(p_clcb->p_rcb->client_if,
p_data->api_conn.remote_bda,
- &p_clcb->bta_conn_id))
+ &p_clcb->bta_conn_id,
+ p_data->api_conn.transport))
{
gattc_data.int_conn.hdr.layer_specific = p_clcb->bta_conn_id;
@@ -553,8 +559,8 @@
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))
+ /* always call open to hold a connection */
+ if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE, p_data->transport))
{
status = BTA_GATT_ERROR;
APPL_TRACE_ERROR0("bta_gattc_init_bk_conn failed");
@@ -566,9 +572,11 @@
/* if is a connected remote device */
if (GATT_GetConnIdIfConnected(p_data->client_if,
p_data->remote_bda,
- &conn_id))
+ &conn_id,
+ p_data->transport))
{
- if ((p_clcb = bta_gattc_find_alloc_clcb(p_data->client_if, p_data->remote_bda)) != NULL)
+ if ((p_clcb = bta_gattc_find_alloc_clcb(p_data->client_if, p_data->remote_bda,
+ BTA_GATT_TRANSPORT_LE)) != NULL)
{
gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
@@ -583,7 +591,8 @@
/* open failure, report OPEN_EVT */
if (status != BTA_GATT_OK)
{
- bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda, BTA_GATT_INVALID_CONN_ID, 0);
+ bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda,
+ BTA_GATT_INVALID_CONN_ID, BTA_GATT_TRANSPORT_LE, 0);
}
}
/*******************************************************************************
@@ -687,7 +696,9 @@
{
APPL_TRACE_DEBUG1("bta_gattc_conn conn_id=%d",p_data->hdr.layer_specific);
p_clcb->bta_conn_id = p_data->int_conn.hdr.layer_specific;
- GATT_GetConnectionInfor(p_data->int_conn.hdr.layer_specific, &gatt_if, p_clcb->bda);
+
+ GATT_GetConnectionInfor(p_data->hdr.layer_specific,
+ &gatt_if, p_clcb->bda, &p_clcb->transport);
}
p_clcb->p_srcb->connected = TRUE;
@@ -721,14 +732,16 @@
if (p_clcb->p_rcb)
{
- /* there is no RM for GATT */
- if (!BTM_IsBleLink(p_clcb->bda))
- bta_sys_conn_open(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
- bta_gattc_send_open_cback(p_clcb->p_rcb,
- BTA_GATT_OK,
- p_clcb->bda,
- p_clcb->bta_conn_id,
- p_clcb->p_srcb->mtu);
+ /* there is no RM for GATT */
+ if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
+ bta_sys_conn_open(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+
+ bta_gattc_send_open_cback(p_clcb->p_rcb,
+ BTA_GATT_OK,
+ p_clcb->bda,
+ p_clcb->bta_conn_id,
+ p_clcb->transport,
+ p_clcb->p_srcb->mtu);
}
}
/*******************************************************************************
@@ -780,13 +793,19 @@
cb_data.close.status = p_clcb->status;
bdcpy(cb_data.close.remote_bda, p_clcb->bda);
- if (!BTM_IsBleLink(p_clcb->bda))
+ if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
bta_sys_conn_close( BTA_ID_GATTC ,BTA_ALL_APP_ID, p_clcb->bda);
bta_gattc_clcb_dealloc(p_clcb);
if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT)
+ {
cb_data.close.status = GATT_Disconnect(p_data->hdr.layer_specific);
+ }
+ else if (p_data->hdr.event == BTA_GATTC_INT_DISCONN_EVT)
+ {
+ cb_data.close.status = p_data->int_conn.reason;
+ }
if(p_cback)
(* p_cback)(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC *)&cb_data);
@@ -942,12 +961,16 @@
p_clcb->p_srcb->update_count = 0;
p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC_ACT;
+ if (p_clcb->transport == BTA_TRANSPORT_LE)
+ L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, FALSE);
+
/* set all srcb related clcb into discovery ST */
bta_gattc_set_discover_st(p_clcb->p_srcb);
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);
+ 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)
{
@@ -987,7 +1010,8 @@
APPL_TRACE_DEBUG1("bta_gattc_disc_cmpl conn_id=%d",p_clcb->bta_conn_id);
#if BLE_INCLUDED == TRUE
- L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE);
+ if(p_clcb->transport == BTA_TRANSPORT_LE)
+ L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE);
#endif
p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
@@ -1249,11 +1273,14 @@
{
APPL_TRACE_ERROR1("bta_gattc_confirm to handle [0x%04x] failed", handle);
}
- /* if over BR_EDR, inform PM for mode change */
- else if (!BTM_IsBleLink(p_clcb->bda))
+ else
{
- bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
- bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+ /* if over BR_EDR, inform PM for mode change */
+ if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
+ {
+ bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+ bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+ }
}
}
}
@@ -1286,7 +1313,8 @@
&cb_data.read.descr_type) == FALSE)
{
cb_data.read.status = BTA_GATT_INTERNAL_ERROR;
- APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", p_data->p_cmpl->att_value.handle);
+ APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x",
+ p_data->p_cmpl->att_value.handle);
}
else
{
@@ -1302,10 +1330,12 @@
cb_data.read.srvc_id = p_clcb->p_q_cmd->api_read.srvc_id;
cb_data.read.char_id = p_clcb->p_q_cmd->api_read.char_id;
if (p_clcb->p_q_cmd->api_read.p_descr_type)
- memcpy(&cb_data.read.descr_type, p_clcb->p_q_cmd->api_read.p_descr_type, sizeof(tBTA_GATT_ID));
+ memcpy(&cb_data.read.descr_type, p_clcb->p_q_cmd->api_read.p_descr_type,
+ sizeof(tBTA_GATT_ID));
}
- event = (p_clcb->p_q_cmd->api_read.p_descr_type == NULL) ? BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT;
+ event = (p_clcb->p_q_cmd->api_read.p_descr_type == NULL) ?
+ BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT;
cb_data.read.conn_id = p_clcb->bta_conn_id;
utl_freebuf((void **)&p_clcb->p_q_cmd);
@@ -1339,10 +1369,13 @@
}
else
{
- memcpy(&cb_data.write.srvc_id, &p_clcb->p_q_cmd->api_write.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
- memcpy(&cb_data.write.char_id, &p_clcb->p_q_cmd->api_write.char_id, sizeof(tBTA_GATT_ID));
+ memcpy(&cb_data.write.srvc_id, &p_clcb->p_q_cmd->api_write.srvc_id,
+ sizeof(tBTA_GATT_SRVC_ID));
+ memcpy(&cb_data.write.char_id, &p_clcb->p_q_cmd->api_write.char_id,
+ sizeof(tBTA_GATT_ID));
if (p_clcb->p_q_cmd->api_write.p_descr_type)
- memcpy(&cb_data.write.descr_type, p_clcb->p_q_cmd->api_write.p_descr_type, sizeof(tBTA_GATT_ID));
+ memcpy(&cb_data.write.descr_type, p_clcb->p_q_cmd->api_write.p_descr_type,
+ sizeof(tBTA_GATT_ID));
}
if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT &&
@@ -1623,7 +1656,8 @@
p_data->ci_load.status == BTA_GATT_MORE) &&
p_data->ci_load.num_attr > 0)
{
- bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr, p_data->ci_load.attr, p_clcb->p_srcb->attr_index);
+ bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr,
+ p_data->ci_load.attr, p_clcb->p_srcb->attr_index);
if (p_data->ci_load.status == BTA_GATT_OK)
{
@@ -1735,7 +1769,8 @@
**
*******************************************************************************/
static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
- BOOLEAN connected, tGATT_DISCONN_REASON reason)
+ BOOLEAN connected, tGATT_DISCONN_REASON reason,
+ tBT_TRANSPORT transport)
{
tBTA_GATTC_DATA *p_buf;
@@ -1746,11 +1781,13 @@
{
memset(p_buf, 0, sizeof(tBTA_GATTC_DATA));
- p_buf->int_conn.hdr.event = connected ? BTA_GATTC_INT_CONN_EVT: BTA_GATTC_INT_DISCONN_EVT;
+ p_buf->int_conn.hdr.event = connected ? BTA_GATTC_INT_CONN_EVT:
+ BTA_GATTC_INT_DISCONN_EVT;
p_buf->int_conn.hdr.layer_specific = conn_id;
p_buf->int_conn.client_if = gattc_if;
p_buf->int_conn.role = L2CA_GetBleConnRole(bda);
p_buf->int_conn.reason = reason;
+ p_buf->int_conn.transport = transport;
bdcpy(p_buf->int_conn.remote_bda, bda);
bta_sys_sendmsg(p_buf);
@@ -1771,7 +1808,7 @@
tBTA_GATTC_DATA *p_buf;
tBTA_GATTC_CLCB *p_clcb = NULL;
- if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL)
+ if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda, BTA_GATT_TRANSPORT_LE)) == NULL)
{
return;
}
@@ -1967,8 +2004,9 @@
tBTA_GATTC_NOTIFY notify;
BD_ADDR remote_bda;
tBTA_GATTC_IF gatt_if;
+ tBTA_TRANSPORT transport;
- if (!GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda))
+ if (!GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport))
{
APPL_TRACE_ERROR0("indication/notif for unknown app");
return;
@@ -2002,9 +2040,10 @@
/* connection not open yet */
if (p_clcb == NULL)
{
- if ((p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda)) != NULL)
+ if ((p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport)) != NULL)
{
p_clcb->bta_conn_id = conn_id;
+ p_clcb->transport = transport;
bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
}
@@ -2027,7 +2066,8 @@
}
else
{
- APPL_TRACE_ERROR1("Indi/Notif for Unknown handle[0x%04x], can not find in local cache.", handle);
+ APPL_TRACE_ERROR1("Indi/Notif for Unknown handle[0x%04x], can not find in local cache.",
+ handle);
}
}
/*******************************************************************************
@@ -2062,9 +2102,8 @@
return;
}
-
-/* if over BR_EDR, inform PM for mode change */
- if (!BTM_IsBleLink(p_clcb->bda))
+ /* if over BR_EDR, inform PM for mode change */
+ if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
{
bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
@@ -2106,14 +2145,14 @@
UINT16 conn_id;
/* should always get the connection ID */
- if (GATT_GetConnIdIfConnected(cif, remote_bda,&conn_id) == FALSE)
+ if (GATT_GetConnIdIfConnected(cif, remote_bda, &conn_id, BTA_GATT_TRANSPORT_LE) == 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)
+ if ((p_clcb = bta_gattc_clcb_alloc(cif, remote_bda, BTA_GATT_TRANSPORT_LE)) != NULL)
{
gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
@@ -2147,7 +2186,7 @@
{
if (p_conn->in_use )
{
- if (bta_gattc_find_clcb_by_cif(cif, p_conn->remote_bda) == NULL)
+ if (bta_gattc_find_clcb_by_cif(cif, p_conn->remote_bda, BTA_GATT_TRANSPORT_LE) == NULL)
{
bta_gattc_init_clcb_conn(cif, p_conn->remote_bda);
}
@@ -2206,7 +2245,9 @@
/* if is a connected remote device */
if (L2CA_GetBleConnRole(p_msg->api_listen.remote_bda) == HCI_ROLE_SLAVE &&
- bta_gattc_find_clcb_by_cif(p_msg->api_listen.client_if, p_msg->api_listen.remote_bda) == NULL)
+ bta_gattc_find_clcb_by_cif(p_msg->api_listen.client_if,
+ p_msg->api_listen.remote_bda,
+ BTA_GATT_TRANSPORT_LE) == NULL)
{
bta_gattc_init_clcb_conn(p_msg->api_listen.client_if,
@@ -2217,7 +2258,8 @@
else
{
APPL_TRACE_ERROR0("Listen For All now");
- /* go through all connected device and send callback for all connected slave connection */
+ /* go through all connected device and send
+ callback for all connected slave connection */
bta_gattc_process_listen_all(p_msg->api_listen.client_if);
}
}
@@ -2238,7 +2280,7 @@
{
tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if);
tBTA_GATTC cb_data;
- (void)(p_cb);
+ UNUSED(p_cb);
cb_data.reg_oper.client_if = p_msg->api_listen.client_if;
cb_data.reg_oper.status = BTM_BleBroadcast(p_msg->api_listen.start);
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
index 0bc87ec..bfbaf63 100644
--- a/bta/gatt/bta_gattc_api.c
+++ b/bta/gatt/bta_gattc_api.c
@@ -143,11 +143,13 @@
** Parameters client_if: server interface.
** remote_bda: remote device BD address.
** is_direct: direct connection or background auto connection
+** transport: Transport to be used for GATT connection (BREDR/LE)
**
** Returns void
**
*******************************************************************************/
-void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+ BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport)
{
tBTA_GATTC_API_OPEN *p_buf;
@@ -157,6 +159,7 @@
p_buf->client_if = client_if;
p_buf->is_direct = is_direct;
+ p_buf->transport = transport;
memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
index 3d603c3..64147e2 100644
--- a/bta/gatt/bta_gattc_cache.c
+++ b/bta/gatt/bta_gattc_cache.c
@@ -460,12 +460,21 @@
** Returns status of the operation.
**
*******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type)
+tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
+ UINT8 disc_type)
{
- if (BTM_IsBleLink(p_server_cb->server_bda))
- return bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
- else
- return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
+ tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+
+ if (p_clcb)
+ {
+ if (p_clcb->transport == BTA_TRANSPORT_LE)
+ status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
+ else
+ status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
+ }
+
+ return status;
}
/*******************************************************************************
**
@@ -476,7 +485,8 @@
** Returns status of the operation.
**
*******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type)
+tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
+ UINT8 disc_type)
{
tGATT_DISC_PARAM param;
BOOLEAN is_service = TRUE;
@@ -844,7 +854,7 @@
service_uuid.uu.uuid16, start_handle, end_handle);
#endif
- if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle) &&
+ if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle)&&
p_srvc_cb != NULL)
{
/* discover services result, add services into a service list */
@@ -856,7 +866,8 @@
}
else
{
- APPL_TRACE_ERROR2("invalid start_handle = %d end_handle = %d", start_handle, end_handle);
+ APPL_TRACE_ERROR2("invalid start_handle = %d end_handle = %d",
+ start_handle, end_handle);
}
}
@@ -904,9 +915,11 @@
attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
- SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid, num_attrs, attr_list);
+ SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
+ &uuid, num_attrs, attr_list);
- if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda, bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback))
+ if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda,
+ bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback))
{
GKI_freebuf(bta_gattc_cb.p_sdp_db);
bta_gattc_cb.p_sdp_db = NULL;
@@ -990,7 +1003,8 @@
break;
case GATT_DISC_CHAR_DSCPT:
- bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0, BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
+ bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
+ BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
break;
}
}
@@ -1073,7 +1087,8 @@
{
#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
- j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type);
+ j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
+ p_attr->inst_id, p_attr->attr_type);
#endif
bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
@@ -1120,7 +1135,7 @@
else /* another char */
{
#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
- APPL_TRACE_DEBUG0("no matching descriptor found!! start of next characteristic");
+ APPL_TRACE_DEBUG0("no matching descptr found!!start of next characteristic");
#endif
char_map = FALSE;
done = TRUE;
@@ -1178,7 +1193,8 @@
{
#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
- j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type);
+ j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
+ p_attr->inst_id, p_attr->attr_type);
#endif
if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
p_char = p_attr;
@@ -1199,7 +1215,7 @@
}
else
{
- APPL_TRACE_ERROR0("descriptor does not belong to any chracteristic, error");
+ APPL_TRACE_ERROR0("descptr does not belong to any chracteristic");
}
}
else
@@ -1249,7 +1265,8 @@
memset(&cb_data, 0, sizeof(tBTA_GATTC));
cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
- memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid ,sizeof(tBTA_GATT_SRVC_ID));
+ 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);
}
@@ -1533,7 +1550,8 @@
**
*******************************************************************************/
void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
- UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop, BOOLEAN is_primary)
+ UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop,
+ BOOLEAN is_primary)
{
p_attr->s_handle = s_handle;
p_attr->e_handle = e_handle;
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 4f192cb..37a14c9 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -118,6 +118,7 @@
BD_ADDR remote_bda;
tBTA_GATTC_IF client_if;
BOOLEAN is_direct;
+ tBTA_TRANSPORT transport;
} tBTA_GATTC_API_OPEN;
typedef tBTA_GATTC_API_OPEN tBTA_GATTC_API_CANCEL_OPEN;
@@ -202,6 +203,7 @@
BD_ADDR remote_bda;
tBTA_GATTC_IF client_if;
UINT8 role;
+ tBT_TRANSPORT transport;
tGATT_DISCONN_REASON reason;
}tBTA_GATTC_INT_CONN;
@@ -366,9 +368,11 @@
{
UINT16 bta_conn_id; /* client channel ID, unique for clcb */
BD_ADDR bda;
+ tBTA_TRANSPORT transport; /* channel transport */
tBTA_GATTC_RCB *p_rcb; /* pointer to the registration CB */
tBTA_GATTC_SERV *p_srcb; /* server cache CB */
tBTA_GATTC_DATA *p_q_cmd; /* command in queue waiting for execution */
+ BOOLEAN buf_held;
#define BTA_GATTC_NO_SCHEDULE 0
#define BTA_GATTC_DISC_WAITING 0x01
@@ -444,7 +448,7 @@
** Function prototypes
*****************************************************************************/
extern BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg);
-extern void bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data);
+extern BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data);
/* function processed outside SM */
extern void bta_gattc_disable(tBTA_GATTC_CB *p_cb);
@@ -491,7 +495,7 @@
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, UINT16 mtu);
+ BD_ADDR remote_bda, UINT16 conn_id, tBTA_TRANSPORT transport, UINT16 mtu);
extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
extern void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
#if BLE_INCLUDED == TRUE
@@ -499,11 +503,11 @@
extern void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
#endif
/* utility functions */
-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_cif (UINT8 client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
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 tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
extern void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb);
-extern tBTA_GATTC_CLCB * bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
+extern tBTA_GATTC_CLCB * bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
extern tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if);
extern tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda);
extern tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda);
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
index 932a1d7..c917d4a 100644
--- a/bta/gatt/bta_gattc_main.c
+++ b/bta/gatt/bta_gattc_main.c
@@ -288,14 +288,16 @@
** Description State machine event handling function for GATTC
**
**
-** Returns void
+** Returns BOOLEAN : TRUE if queued client request buffer can be immediately released
+** else FALSE
**
*******************************************************************************/
-void bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data)
+BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data)
{
tBTA_GATTC_ST_TBL state_table;
UINT8 action;
int i;
+ BOOLEAN rt = TRUE;
#if BTA_GATT_DEBUG == TRUE
tBTA_GATTC_STATE in_state = p_clcb->state;
UINT16 in_event = event;
@@ -320,6 +322,8 @@
if ((action = state_table[event][i]) != BTA_GATTC_IGNORE)
{
(*bta_gattc_action[action])(p_clcb, p_data);
+ p_clcb->buf_held = FALSE;
+ rt = FALSE;
}
else
{
@@ -336,6 +340,7 @@
gattc_evt_code(in_event));
}
#endif
+return rt;
}
/*******************************************************************************
@@ -345,7 +350,7 @@
** Description GATT client main event handling function.
**
**
-** Returns void
+** Returns BOOLEAN
**
*******************************************************************************/
BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
@@ -353,6 +358,7 @@
tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
tBTA_GATTC_CLCB *p_clcb = NULL;
tBTA_GATTC_RCB *p_clreg;
+ BOOLEAN rt = TRUE;
#if BTA_GATT_DEBUG == TRUE
APPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event));
#endif
@@ -410,7 +416,7 @@
if (p_clcb != NULL)
{
- bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg);
+ rt = bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg);
}
else
{
@@ -421,7 +427,7 @@
}
- return(TRUE);
+ return rt;
}
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
index b52e52c..99b222a 100644
--- a/bta/gatt/bta_gattc_utils.c
+++ b/bta/gatt/bta_gattc_utils.c
@@ -163,7 +163,8 @@
** Returns pointer to the clcb
**
*******************************************************************************/
-tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda)
+tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda,
+ tBTA_TRANSPORT transport)
{
tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
UINT8 i;
@@ -172,6 +173,7 @@
{
if (p_clcb->in_use &&
p_clcb->p_rcb->client_if == client_if &&
+ p_clcb->transport == transport &&
bdcmp(p_clcb->bda, remote_bda) == 0)
return p_clcb;
}
@@ -209,7 +211,8 @@
** Returns pointer to the clcb
**
*******************************************************************************/
-tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+ tBTA_TRANSPORT transport)
{
UINT8 i_clcb = 0;
tBTA_GATTC_CLCB *p_clcb = NULL;
@@ -224,6 +227,7 @@
p_clcb = &bta_gattc_cb.clcb[i_clcb];
p_clcb->in_use = TRUE;
p_clcb->status = BTA_GATT_OK;
+ p_clcb->transport = transport;
bdcpy(p_clcb->bda, remote_bda);
p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
@@ -256,13 +260,14 @@
** Returns pointer to the clcb
**
*******************************************************************************/
-tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+ tBTA_TRANSPORT transport)
{
tBTA_GATTC_CLCB *p_clcb ;
- if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda)) == NULL)
+ if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda, transport)) == NULL)
{
- p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda);
+ p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda, transport);
}
return p_clcb;
}
@@ -427,167 +432,19 @@
*******************************************************************************/
BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
{
- BOOLEAN in_q = FALSE;
- if (p_clcb->p_q_cmd == NULL && p_data)
- {
- UINT16 len;
- switch (p_data->hdr.event)
- {
- case BTA_GATTC_API_SEARCH_EVT:
- {
- if (p_data->api_search.p_srvc_uuid)
- {
- len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(tBT_UUID);
- }
- else
- {
- len = sizeof(tBTA_GATTC_API_SEARCH);
- }
- p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(len);
- if (p_clcb->p_q_cmd == NULL)
- {
- APPL_TRACE_ERROR0("allocate buffer failed for p_q_cmd");
- return FALSE;
- }
- memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_API_SEARCH));
- if (p_data->api_search.p_srvc_uuid)
- {
- tBTA_GATTC_API_SEARCH *p_buf;
- p_buf = &(p_clcb->p_q_cmd->api_search);
- p_buf->p_srvc_uuid = (tBT_UUID *)(p_buf + 1);
- memcpy(p_buf->p_srvc_uuid, p_data->api_search.p_srvc_uuid,
- sizeof(tBT_UUID));
- }
- break;
- }
- case BTA_GATTC_API_READ_EVT:
- {
- if (p_data->api_read.p_descr_type)
- {
- len = sizeof(tBTA_GATT_ID) + sizeof(tBTA_GATTC_API_READ);
- }
- else
- {
- len = sizeof(tBTA_GATTC_API_READ);
- }
- p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(len);
- if (p_clcb->p_q_cmd == NULL)
- {
- APPL_TRACE_ERROR0("allocate buffer failed for p_q_cmd");
- return FALSE;
- }
- memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_API_READ));
- if (p_data->api_read.p_descr_type)
- {
- tBTA_GATTC_API_READ *p_buf;
- p_buf = &(p_clcb->p_q_cmd->api_read);
- p_buf->p_descr_type = (tBTA_GATT_ID *)(p_buf + 1);
- memcpy(p_buf->p_descr_type, p_data->api_read.p_descr_type,
- sizeof(tBTA_GATT_ID));
- }
- break;
- }
- case BTA_GATTC_API_WRITE_EVT:
- {
- tBTA_GATTC_API_WRITE *p_buf;
- len = sizeof(tBTA_GATTC_API_WRITE) + p_data->api_write.len;
- if (p_data->api_write.p_descr_type)
- {
- len += sizeof(tBTA_GATT_ID);
- }
- p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(len);
- if (p_clcb->p_q_cmd == NULL)
- {
- APPL_TRACE_ERROR0("allocate buffer failed for p_q_cmd");
- return FALSE;
- }
- memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_API_WRITE));
- p_buf = &(p_clcb->p_q_cmd->api_write);
- if (p_data->api_write.p_descr_type)
- {
- p_buf->p_descr_type = (tBTA_GATT_ID *)(p_buf + 1);
- memcpy(p_buf->p_descr_type, p_data->api_write.p_descr_type,
- sizeof(tBTA_GATT_ID));
- if (p_buf->len && p_buf->p_value)
- {
- p_buf->p_value = (UINT8 *)(p_buf->p_descr_type + 1);
- memcpy(p_buf->p_value, p_data->api_write.p_value,
- p_data->api_write.len);
- }
- }
- else if (p_buf->len && p_buf->p_value)
- {
- p_buf->p_value = (UINT8 *)(p_buf + 1);
- memcpy(p_buf->p_value, p_data->api_write.p_value,
- p_data->api_write.len);
- }
- break;
- }
- case BTA_GATTC_API_EXEC_EVT:
- {
- len = sizeof(tBTA_GATTC_API_EXEC);
- p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(len);
- if (p_clcb->p_q_cmd == NULL)
- {
- APPL_TRACE_ERROR0("allocate buffer failed for p_q_cmd");
- return FALSE;
- }
- memcpy(p_clcb->p_q_cmd, p_data, len);
- break;
- }
- case BTA_GATTC_API_READ_MULTI_EVT:
- {
- len = sizeof(tBTA_GATTC_API_READ_MULTI) +
- p_data->api_read_multi.num_attr * sizeof(tBTA_GATTC_ATTR_ID);
- p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(len);
- if (p_clcb->p_q_cmd == NULL)
- {
- APPL_TRACE_ERROR0("allocate buffer failed for p_q_cmd");
- return FALSE;
- }
- memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_API_READ_MULTI));
- if (p_data->api_read_multi.num_attr &&
- p_data->api_read_multi.p_id_list)
- {
- tBTA_GATTC_API_READ_MULTI *p_buf;
- p_buf = &(p_clcb->p_q_cmd->api_read_multi);
- p_buf->p_id_list = (tBTA_GATTC_ATTR_ID *)(p_buf + 1);
- memcpy(p_buf->p_id_list, p_data->api_read_multi.p_id_list,
- p_data->api_read_multi.num_attr * sizeof(tBTA_GATTC_ATTR_ID));
- }
- break;
- }
- case BTA_GATTC_API_CFG_MTU_EVT:
- {
- len = sizeof(tBTA_GATTC_API_CFG_MTU);
- p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(len);
- if (p_clcb->p_q_cmd == NULL)
- {
- APPL_TRACE_ERROR0("allocate buffer failed for p_q_cmd");
- return FALSE;
- }
- memcpy(p_clcb->p_q_cmd, p_data, len);
- break;
- }
- default:
- APPL_TRACE_ERROR1("queue unsupported command %d", p_data->hdr.event);
- return FALSE;
- }
+ if (p_clcb->p_q_cmd == NULL)
+ {
+ p_clcb->p_q_cmd = p_data;
+ p_clcb->buf_held = TRUE;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("already has a pending command!!");
+ /* skip the callback now. ----- need to send callback ? */
+ }
+ return p_clcb->buf_held;
- in_q = TRUE;
- }
- else if (p_clcb->p_q_cmd)
- {
- APPL_TRACE_ERROR0("already has a pending command!!");
- /* skip the callback now. ----- need to send callback ? */
- }
- else
- {
- APPL_TRACE_ERROR0("queue a null command");
- }
-
- return in_q;
}
/*******************************************************************************
**
@@ -738,14 +595,16 @@
tBTA_GATTC_IF gatt_if;
tBTA_GATTC_RCB *p_clrcb ;
UINT8 i;
+ tGATT_TRANSPORT transport;
- if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda))
+ if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport))
{
if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
{
for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
{
- if (p_clrcb->notif_reg[i].in_use && !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
+ if (p_clrcb->notif_reg[i].in_use &&
+ !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
}
}
@@ -919,7 +778,8 @@
**
*******************************************************************************/
void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
- BD_ADDR remote_bda, UINT16 conn_id, UINT16 mtu)
+ BD_ADDR remote_bda, UINT16 conn_id,
+ tBTA_TRANSPORT transport, UINT16 mtu)
{
tBTA_GATTC cb_data;
@@ -931,6 +791,7 @@
cb_data.open.client_if = p_clreg->client_if;
cb_data.open.conn_id = conn_id;
cb_data.open.mtu = mtu;
+ cb_data.open.transport = transport;
bdcpy(cb_data.open.remote_bda, remote_bda);
(*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
@@ -1053,16 +914,19 @@
/* try to locate a logic channel */
if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
- p_msg->int_conn.remote_bda)) == NULL)
+ p_msg->int_conn.remote_bda,
+ p_msg->int_conn.transport)) == NULL)
{
/* for a background connection or listening connection */
- if (p_msg->int_conn.role == HCI_ROLE_SLAVE ||
+ if (/*p_msg->int_conn.role == HCI_ROLE_SLAVE || */
bta_gattc_check_bg_conn(p_msg->int_conn.client_if,
p_msg->int_conn.remote_bda,
p_msg->int_conn.role))
{
/* allocate a new channel */
- p_clcb = bta_gattc_clcb_alloc(p_msg->int_conn.client_if, p_msg->int_conn.remote_bda);
+ p_clcb = bta_gattc_clcb_alloc(p_msg->int_conn.client_if,
+ p_msg->int_conn.remote_bda,
+ p_msg->int_conn.transport);
}
}
return p_clcb;
@@ -1087,12 +951,13 @@
if (reason == GATT_CONN_CANCEL || reason == GATT_CONN_L2C_FAILURE)
{
p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
- p_msg->int_conn.remote_bda);
+ p_msg->int_conn.remote_bda,
+ p_msg->int_conn.transport);
}
else if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->int_conn.hdr.layer_specific)) == NULL)
{
- APPL_TRACE_DEBUG1("disconnection ID: [%d] not used by BTA",
- p_msg->int_conn.hdr.layer_specific);
+ APPL_TRACE_DEBUG1(" disconnection ID: [%d] not used by BTA",
+ p_msg->int_conn.hdr.layer_specific);
}
return p_clcb;
}
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
index be03655..4a24d66 100644
--- a/bta/gatt/bta_gatts_act.c
+++ b/bta/gatt/bta_gatts_act.c
@@ -37,9 +37,12 @@
#include <string.h>
static void bta_gatts_nv_save_cback(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
-static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp);
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req,
+ tGATTS_SRV_CHG_RSP *p_rsp);
-static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason,
+ tGATT_TRANSPORT transport);
static void bta_gatts_send_request_cback (UINT16 conn_id,
UINT32 trans_id,
tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data);
@@ -85,7 +88,8 @@
** Returns none.
**
*******************************************************************************/
-static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp)
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd,
+ tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp)
{
return bta_gatts_co_srv_chg((tBTA_GATTS_SRV_CHG_CMD) cmd,
(tBTA_GATTS_SRV_CHG_REQ *) p_req,
@@ -223,14 +227,16 @@
p_cb->rcb[first_unuse].p_cback = p_msg->api_reg.p_cback;
memcpy(&p_cb->rcb[first_unuse].app_uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
cb_data.reg_oper.server_if =
- p_cb->rcb[first_unuse].gatt_if = GATT_Register(&p_msg->api_reg.app_uuid, &bta_gatts_cback);
+ p_cb->rcb[first_unuse].gatt_if =
+ GATT_Register(&p_msg->api_reg.app_uuid, &bta_gatts_cback);
if ( !p_cb->rcb[first_unuse].gatt_if)
{
status = BTA_GATT_NO_RESOURCES;
}
else
{
- if ((p_buf = (tBTA_GATTS_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTS_INT_START_IF))) != NULL)
+ if ((p_buf =
+ (tBTA_GATTS_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTS_INT_START_IF))) != NULL)
{
p_buf->hdr.event = BTA_GATTS_INT_START_IF_EVT;
p_buf->server_if = p_cb->rcb[first_unuse].gatt_if;
@@ -275,7 +281,8 @@
}
else
{
- APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.server_if );
+ APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",
+ p_msg->int_start_if.server_if );
}
}
/*******************************************************************************
@@ -358,7 +365,8 @@
if (service_id != 0)
{
- memcpy(&p_cb->srvc_cb[srvc_idx].service_uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
+ memcpy(&p_cb->srvc_cb[srvc_idx].service_uuid,
+ &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
p_cb->srvc_cb[srvc_idx].service_id = service_id;
p_cb->srvc_cb[srvc_idx].inst_num = p_msg->api_create_svc.inst;
p_cb->srvc_cb[srvc_idx].idx = srvc_idx;
@@ -617,11 +625,7 @@
**
** Function bta_gatts_indicate_handle
**
-<<<<<<< HEAD
-** Description GATTS indicate handel value
-=======
** Description GATTS send handle value indication or notification.
->>>>>>> 6ea30bf... LE: UPF 45 bug fixes
**
** Returns none.
**
@@ -632,13 +636,14 @@
tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
tGATT_IF gatt_if;
BD_ADDR remote_bda;
-
+ tBTA_TRANSPORT transport;
p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id (p_cb, p_msg->api_indicate.attr_id);
if (p_srvc_cb )
{
- if (GATT_GetConnectionInfor(p_msg->api_indicate.hdr.layer_specific, &gatt_if, remote_bda))
+ if (GATT_GetConnectionInfor(p_msg->api_indicate.hdr.layer_specific,
+ &gatt_if, remote_bda, &transport))
{
if (p_msg->api_indicate.need_confirm)
@@ -653,7 +658,7 @@
p_msg->api_indicate.value);
/* if over BR_EDR, inform PM for mode change */
- if (!BTM_IsBleLink(remote_bda))
+ if (transport == BTA_TRANSPORT_BR_EDR)
{
bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
@@ -664,8 +669,7 @@
APPL_TRACE_ERROR1("Unknown connection ID: %d fail sending notification",
p_msg->api_indicate.hdr.layer_specific);
}
-
- if (status != GATT_SUCCESS && p_msg->api_indicate.need_confirm &&
+ if ((status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) &&
p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)
{
(*p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)(BTA_GATTS_CONF_EVT, (tBTA_GATTS *)&status);
@@ -692,13 +696,22 @@
{
tBTA_GATTS_RCB *p_rcb=NULL;
tBTA_GATT_STATUS status= BTA_GATT_ERROR;
+ UINT16 conn_id;
UNUSED(p_cb);
if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_open.server_if)) != NULL)
{
- if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda, p_msg->api_open.is_direct))
+ /* should always get the connection ID */
+ if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda,
+ p_msg->api_open.is_direct, p_msg->api_open.transport))
{
status = BTA_GATT_OK;
+
+ if (GATT_GetConnIdIfConnected(p_rcb->gatt_if, p_msg->api_open.remote_bda,
+ &conn_id, p_msg->api_open.transport))
+ {
+ status = BTA_GATT_ALREADY_OPEN;
+ }
}
}
else
@@ -727,7 +740,8 @@
if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_cancel_open.server_if)) != NULL)
{
- if (!GATT_CancelConnect(p_rcb->gatt_if, p_msg->api_cancel_open.remote_bda, p_msg->api_cancel_open.is_direct))
+ if (!GATT_CancelConnect(p_rcb->gatt_if, p_msg->api_cancel_open.remote_bda,
+ p_msg->api_cancel_open.is_direct))
{
APPL_TRACE_ERROR0("bta_gatts_cancel_open failed for open request");
}
@@ -759,9 +773,11 @@
tBTA_GATT_STATUS status= BTA_GATT_ERROR;
tGATT_IF gatt_if;
BD_ADDR remote_bda;
+ tBTA_GATT_TRANSPORT transport;
+
UNUSED(p_cb);
- if (GATT_GetConnectionInfor(p_msg->hdr.layer_specific, &gatt_if, remote_bda))
+ if (GATT_GetConnectionInfor(p_msg->hdr.layer_specific, &gatt_if, remote_bda, &transport))
{
if (GATT_Disconnect(p_msg->hdr.layer_specific) != GATT_SUCCESS)
{
@@ -776,7 +792,7 @@
if (p_rcb && p_rcb->p_cback)
{
- if (!BTM_IsBleLink(remote_bda))
+ if (transport == BTA_TRANSPORT_BR_EDR)
bta_sys_conn_close( BTA_ID_GATTS ,BTA_ALL_APP_ID, remote_bda);
(*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT, (tBTA_GATTS *)&status);
@@ -840,19 +856,21 @@
tBTA_GATTS cb_data;
tBTA_GATTS_RCB *p_rcb;
tGATT_IF gatt_if;
+ tBTA_GATT_TRANSPORT transport;
memset(&cb_data, 0 , sizeof(tBTA_GATTS));
- if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda))
+ if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda, &transport))
{
p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
- APPL_TRACE_DEBUG3 ("bta_gatts_send_request_cback conn_id=%d trans_id=%d req_type=%d", conn_id, trans_id, req_type);
+ APPL_TRACE_DEBUG3 ("bta_gatts_send_request_cback conn_id=%d trans_id=%d req_type=%d",
+ conn_id, trans_id, req_type);
if (p_rcb && p_rcb->p_cback)
{
/* if over BR_EDR, inform PM for mode change */
- if (!BTM_IsBleLink(cb_data.req_data.remote_bda))
+ if (transport == BTA_TRANSPORT_BR_EDR)
{
bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, cb_data.req_data.remote_bda);
bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, cb_data.req_data.remote_bda);
@@ -885,7 +903,8 @@
**
*******************************************************************************/
static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
- BOOLEAN connected, tGATT_DISCONN_REASON reason)
+ BOOLEAN connected, tGATT_DISCONN_REASON reason,
+ tGATT_TRANSPORT transport)
{
tBTA_GATTS cb_data;
UINT8 evt = connected ? BTA_GATTS_CONNECT_EVT: BTA_GATTS_DISCONNECT_EVT;
@@ -901,7 +920,7 @@
if (p_reg && p_reg->p_cback)
{
/* there is no RM for GATT */
- if (!BTM_IsBleLink(bda))
+ if (transport == BTA_TRANSPORT_BR_EDR)
{
if (connected)
bta_sys_conn_open(BTA_ID_GATTS, BTA_ALL_APP_ID, bda);
@@ -912,6 +931,7 @@
cb_data.conn.conn_id = conn_id;
cb_data.conn.server_if = gatt_if;
cb_data.conn.reason = reason;
+ cb_data.conn.transport = transport;
memcpy(cb_data.conn.remote_bda, bda, BD_ADDR_LEN);
(*p_reg->p_cback)(evt, &cb_data);
}
diff --git a/bta/gatt/bta_gatts_api.c b/bta/gatt/bta_gatts_api.c
index ad30d73..79eb6f9 100644
--- a/bta/gatt/bta_gatts_api.c
+++ b/bta/gatt/bta_gatts_api.c
@@ -464,11 +464,13 @@
** Parameters server_if: server interface.
** remote_bda: remote device BD address.
** is_direct: direct connection or background auto connection
+** transport : Transport on which GATT connection to be opened (BR/EDR or LE)
**
** Returns void
**
*******************************************************************************/
-void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct,
+ tBTA_GATT_TRANSPORT transport)
{
tBTA_GATTS_API_OPEN *p_buf;
@@ -477,6 +479,7 @@
p_buf->hdr.event = BTA_GATTS_API_OPEN_EVT;
p_buf->server_if = server_if;
p_buf->is_direct = is_direct;
+ p_buf->transport = transport;
memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
bta_sys_sendmsg(p_buf);
diff --git a/bta/gatt/bta_gatts_int.h b/bta/gatt/bta_gatts_int.h
index ce9553a..9a12dfd 100644
--- a/bta/gatt/bta_gatts_int.h
+++ b/bta/gatt/bta_gatts_int.h
@@ -139,10 +139,12 @@
typedef struct
{
- BT_HDR hdr;
- BD_ADDR remote_bda;
- tBTA_GATTS_IF server_if;
- BOOLEAN is_direct;
+ BT_HDR hdr;
+ BD_ADDR remote_bda;
+ tBTA_GATTS_IF server_if;
+ BOOLEAN is_direct;
+ tBTA_GATT_TRANSPORT transport;
+
}tBTA_GATTS_API_OPEN;
typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN;
diff --git a/bta/hh/bta_hh_le.c b/bta/hh/bta_hh_le.c
index 4f297ee..34447a5 100644
--- a/bta/hh/bta_hh_le.c
+++ b/bta/hh/bta_hh_le.c
@@ -347,7 +347,7 @@
bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
p_cb->in_use = TRUE;
- BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, TRUE);
+ BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, TRUE, BTA_GATT_TRANSPORT_LE);
}
/*******************************************************************************
**
@@ -640,7 +640,8 @@
while (p_rpt != NULL)
{
- if (!p_rpt->in_use) break;
+ if(!p_rpt->in_use)
+ break;
if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
{
@@ -674,8 +675,6 @@
break;
}
}
- else
- break;
if (p_rpt->index == BTA_HH_LE_RPT_MAX - 1)
break;
@@ -1210,11 +1209,13 @@
** Returns None
**
*******************************************************************************/
-void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, tBTA_GATT_TRANSPORT transport,
+ void *p_ref_data, tBTM_STATUS result)
{
UINT8 idx = bta_hh_find_cb(bd_addr);
tBTA_HH_DEV_CB *p_dev_cb;
UNUSED(p_ref_data);
+ UNUSED (transport);
APPL_TRACE_ERROR0("bta_hh_le_encrypt_cback");
@@ -1315,7 +1316,7 @@
}
/* verify bond */
- BTM_GetSecurityFlags(p_cb->addr, &sec_flag);
+ BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
/* if link has been encrypted */
if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
@@ -1327,14 +1328,14 @@
{
sec_flag = BTM_BLE_SEC_ENCRYPT;
p_cb->status = BTA_HH_ERR_AUTH_FAILED;
- BTM_SetEncryption(p_cb->addr, bta_hh_le_encrypt_cback, &sec_flag);
+ BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
}
/* unbonded device, report security error here */
else if (p_cb->sec_mask != BTA_SEC_NONE)
{
sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
p_cb->status = BTA_HH_ERR_AUTH_FAILED;
- BTM_SetEncryption(p_cb->addr, bta_hh_le_encrypt_cback, &sec_flag);
+ BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
}
/* otherwise let it go through */
else
@@ -2261,7 +2262,7 @@
else if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
app_id = BTA_HH_APP_ID_KB;
- APPL_TRACE_ERROR1("Notification received on report ID: %d", p_rpt->rpt_id);
+ APPL_TRACE_DEBUG1("Notification received on report ID: %d", p_rpt->rpt_id);
/* need to append report ID to the head of data */
if (p_rpt->rpt_id != 0)
@@ -2620,7 +2621,7 @@
!p_cb->in_bg_conn && to_add)
{
/* add device into BG connection to accept remote initiated connection */
- BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE);
+ BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
p_cb->in_bg_conn = TRUE;
BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
diff --git a/bta/hh/bta_hh_main.c b/bta/hh/bta_hh_main.c
index c2554c1..10e62cd 100644
--- a/bta/hh/bta_hh_main.c
+++ b/bta/hh/bta_hh_main.c
@@ -358,6 +358,12 @@
default:
/* invalid handle, call bad API event */
APPL_TRACE_ERROR1("wrong device handle: [%d]", p_data->hdr.layer_specific);
+ /* Free the callback buffer now */
+ if (p_data != NULL && p_data->hid_cback.p_data != NULL)
+ {
+ GKI_freebuf(p_data->hid_cback.p_data);
+ p_data->hid_cback.p_data = NULL;
+ }
break;
}
if (cback_event)
diff --git a/bta/hl/bta_hl_utils.c b/bta/hl/bta_hl_utils.c
index 6a08b74..bc37807 100644
--- a/bta/hl/bta_hl_utils.c
+++ b/bta/hl/bta_hl_utils.c
@@ -1462,6 +1462,8 @@
tBTA_HL_MDL_CFG *p_mdl;
UINT8 i ;
BOOLEAN found=FALSE;
+
+ *p_mdl_cfg_idx = 0;
for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
{
p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
@@ -2725,6 +2727,11 @@
}
success = TRUE;
}
+ else
+ {
+ p_cfg->mtu = L2CAP_DEFAULT_MTU;
+ p_cfg->fcs = BTA_HL_L2C_NO_FCS;
+ }
#if BTA_HL_DEBUG == TRUE
if (!success)
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
index f16687c..85f82a0 100644
--- a/bta/include/bta_ag_api.h
+++ b/bta/include/bta_ag_api.h
@@ -275,11 +275,19 @@
tBTA_AG_STATUS status;
} tBTA_AG_OPEN;
+/* data associated with BTA_AG_CLOSE_EVT */
+typedef struct
+{
+ tBTA_AG_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_AG_CLOSE;
+
/* data associated with BTA_AG_CONN_EVT */
typedef struct
{
tBTA_AG_HDR hdr;
tBTA_AG_PEER_FEAT peer_feat;
+ BD_ADDR bd_addr;
tBTA_AG_PEER_CODEC peer_codec;
} tBTA_AG_CONN;
@@ -287,6 +295,7 @@
typedef struct
{
tBTA_AG_HDR hdr;
+ BD_ADDR bd_addr;
char str[BTA_AG_AT_MAX_LEN+1];
UINT16 num;
UINT8 idx; /* call number used by CLCC and CHLD */
@@ -298,6 +307,7 @@
tBTA_AG_HDR hdr;
tBTA_AG_REGISTER reg;
tBTA_AG_OPEN open;
+ tBTA_AG_CLOSE close;
tBTA_AG_CONN conn;
tBTA_AG_VAL val;
} tBTA_AG;
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 4345fbf..4bb305d 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -200,7 +200,11 @@
// btla-specific ++
typedef UINT16 tBTA_DM_CONN;
-// btla-specific --
+
+#define BTA_TRANSPORT_UNKNOWN 0
+#define BTA_TRANSPORT_BR_EDR BT_TRANSPORT_BR_EDR
+#define BTA_TRANSPORT_LE BT_TRANSPORT_LE
+typedef tBT_TRANSPORT tBTA_TRANSPORT;
/* Pairable Modes */
#define BTA_DM_PAIRABLE 1
@@ -311,6 +315,8 @@
#define BTA_BLE_LIMIT_DISC_FLAG BTM_BLE_LIMIT_DISC_FLAG
#define BTA_BLE_GEN_DISC_FLAG BTM_BLE_GEN_DISC_FLAG
#define BTA_BLE_BREDR_NOT_SPT BTM_BLE_BREDR_NOT_SPT
+#define BTA_BLE_DMT_CONTROLLER_SPT BTM_BLE_DMT_CONTROLLER_SPT
+#define BTA_BLE_DMT_HOST_SPT BTM_BLE_DMT_HOST_SPT
#define BTA_BLE_NON_LIMIT_DISC_FLAG BTM_BLE_NON_LIMIT_DISC_FLAG
#define BTA_BLE_ADV_FLAG_MASK BTM_BLE_ADV_FLAG_MASK
#define BTA_BLE_LIMIT_DISC_MASK BTM_BLE_LIMIT_DISC_MASK
@@ -330,8 +336,9 @@
#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
+#define BTA_DM_BLE_AD_BIT_SERVICE_128 BTM_BLE_AD_BIT_SERVICE_128 /*128-bit Service UUIDs*/
-typedef UINT16 tBTA_BLE_AD_MASK;
+typedef tBTM_BLE_AD_MASK tBTA_BLE_AD_MASK;
/* slave preferred connection interval range */
typedef struct
@@ -372,15 +379,68 @@
typedef struct
{
- 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;
+ tBT_UUID service_uuid;
+ UINT8 len;
+ UINT8 *p_val;
+}tBTA_BLE_SERVICE_DATA;
+typedef tBTM_BLE_128SERVICE tBTA_BLE_128SERVICE;
+typedef tBTM_BLE_32SERVICE tBTA_BLE_32SERVICE;
+
+typedef struct
+{
+ tBTA_BLE_INT_RANGE int_range; /* slave prefered conn interval range */
+ tBTA_BLE_MANU *p_manu; /* manufacturer data */
+ tBTA_BLE_SERVICE *p_services; /* 16 bits services */
+ tBTA_BLE_128SERVICE *p_services_128b; /* 128 bits service */
+ tBTA_BLE_32SERVICE *p_service_32b; /* 32 bits Service UUID */
+ tBTA_BLE_SERVICE *p_sol_services; /* 16 bits services Solicitation UUIDs */
+ tBTA_BLE_32SERVICE *p_sol_service_32b; /* List of 32 bit Service Solicitation UUIDs */
+ tBTA_BLE_128SERVICE *p_sol_service_128b;/* List of 128 bit Service Solicitation UUIDs */
+ tBTA_BLE_PROPRIETARY *p_proprietary; /* proprietary data */
+ tBTA_BLE_SERVICE_DATA *p_service_data; /* service data */
+ UINT16 appearance; /* appearance data */
+ UINT8 flag;
+ UINT8 tx_power;
}tBTA_BLE_ADV_DATA;
+typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status);
+
+/* advertising channel map */
+#define BTA_BLE_ADV_CHNL_37 BTM_BLE_ADV_CHNL_37
+#define BTA_BLE_ADV_CHNL_38 BTM_BLE_ADV_CHNL_38
+#define BTA_BLE_ADV_CHNL_39 BTM_BLE_ADV_CHNL_39
+typedef tBTM_BLE_ADV_CHNL_MAP tBTA_BLE_ADV_CHNL_MAP; /* use as a bit mask */
+
+/* advertising filter policy */
+typedef tBTM_BLE_AFP tBTA_BLE_AFP;
+
+/* adv event type */
+#define BTA_BLE_CONNECT_EVT BTM_BLE_CONNECT_EVT /* Connectable undirected advertising */
+#define BTA_BLE_CONNECT_DIR_EVT BTM_BLE_CONNECT_DIR_EVT /* Connectable directed advertising */
+#define BTA_BLE_DISCOVER_EVT BTM_BLE_DISCOVER_EVT /* Scannable undirected advertising */
+#define BTA_BLE_NON_CONNECT_EVT BTM_BLE_NON_CONNECT_EVT /* Non connectable undirected advertising */
+typedef UINT8 tBTA_BLE_ADV_EVT;
+
+/* adv tx power level */
+#define BTA_BLE_ADV_TX_POWER_MIN 0 /* minimum tx power */
+#define BTA_BLE_ADV_TX_POWER_LOW 1 /* low tx power */
+#define BTA_BLE_ADV_TX_POWER_MID 2 /* middle tx power */
+#define BTA_BLE_ADV_TX_POWER_UPPER 3 /* upper tx power */
+#define BTA_BLE_ADV_TX_POWER_MAX 4 /* maximum tx power */
+typedef UINT8 tBTA_BLE_ADV_TX_POWER;
+
+/* advertising instance parameters */
+typedef struct
+{
+ UINT16 adv_int_min; /* minimum adv interval */
+ UINT16 adv_int_max; /* maximum adv interval */
+ tBTA_BLE_ADV_EVT adv_type; /* adv event type */
+ tBTA_BLE_ADV_CHNL_MAP channel_map; /* adv channel map */
+ tBTA_BLE_AFP adv_filter_policy; /* advertising filter policy */
+ tBTA_BLE_ADV_TX_POWER tx_power; /* adv tx power */
+}tBTA_BLE_ADV_PARAMS;
+
/* These are the fields returned in each device adv packet. It
** is returned in the results callback if registered.
*/
@@ -432,20 +492,31 @@
/* filter selection bit index */
#define BTA_DM_BLE_PF_ADDR_FILTER BTM_BLE_PF_ADDR_FILTER
+#define BTA_DM_BLE_PF_SRVC_DATA BTM_BLE_PF_SRVC_DATA
#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_SRVC_DATA_PATTERN BTM_BLE_PF_SRVC_DATA_PATTERN
#define BTA_DM_BLE_PF_TYPE_MAX BTM_BLE_PF_TYPE_MAX
+#define BTA_DM_BLE_PF_SRVC_DATA BTM_BLE_PF_SRVC_DATA
#define BTA_DM_BLE_PF_TYPE_ALL BTM_BLE_PF_TYPE_ALL
+#define BTA_DM_BLE_PF_TYPE_MAX BTM_BLE_PF_TYPE_MAX
typedef UINT8 tBTA_DM_BLE_PF_COND_TYPE;
+typedef union
+{
+ UINT16 uuid16_mask;
+ UINT32 uuid32_mask;
+ UINT8 uuid128_mask[LEN_UUID_128];
+}tBTA_DM_BLE_PF_COND_MASK;
+
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_COND_MASK *p_uuid_mask; /* UUID condition mask, if NULL, match exact as UUID condition */
}tBTA_DM_BLE_PF_UUID_COND;
typedef struct
@@ -459,8 +530,18 @@
UINT16 company_id; /* company ID */
UINT8 data_len; /* <= 20 bytes */
UINT8 *p_pattern;
+ UINT16 company_id_mask; /* UUID value mask */
+ UINT8 *p_pattern_mask; /* Manufactuer data matching mask, same length as data pattern,
+ set to all 0xff, match exact data */
}tBTA_DM_BLE_PF_MANU_COND;
+typedef struct
+{
+ UINT16 uuid; /* service ID */
+ UINT8 data_len; /* <= 20 bytes */
+ UINT8 *p_pattern;
+}tBTA_DM_BLE_PF_SRVC_PATTERN_COND;
+
typedef union
{
tBLE_BD_ADDR target_addr;
@@ -468,9 +549,9 @@
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_SRVC_PATTERN_COND srvc_data; /* service data pattern */
}tBTA_DM_BLE_PF_COND_PARAM;
-
typedef INT8 tBTA_DM_RSSI_VALUE;
typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE;
@@ -522,6 +603,7 @@
/* Structure associated with BTA_DM_PIN_REQ_EVT */
typedef struct
{
+ /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
BD_ADDR bd_addr; /* BD address peer device. */
DEV_CLASS dev_class; /* Class of Device */
BD_NAME bd_name; /* Name of peer device. */
@@ -655,6 +737,9 @@
typedef struct
{
BD_ADDR bd_addr; /* BD address peer device. */
+#if BLE_INCLUDED == TRUE
+ tBTA_TRANSPORT link_type;
+#endif
} tBTA_DM_LINK_UP;
/* Structure associated with BTA_DM_LINK_DOWN_EVT */
@@ -663,6 +748,9 @@
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 */
+#if BLE_INCLUDED == TRUE
+ tBTA_TRANSPORT link_type;
+#endif
} tBTA_DM_LINK_DOWN;
/* Structure associated with BTA_DM_ROLE_CHG_EVT */
@@ -809,6 +897,21 @@
/* Security callback */
typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data);
+#define BTA_BLE_MULTI_ADV_MAX BTM_BLE_MULTI_ADV_MAX
+#define BTA_BLE_MULTI_ADV_ILLEGAL 0
+
+/* multi adv callback event */
+#define BTA_BLE_MULTI_ADV_ENB_EVT 1
+#define BTA_BLE_MULTI_ADV_DISABLE_EVT 2
+#define BTA_BLE_MULTI_ADV_PARAM_EVT 3
+#define BTA_BLE_MULTI_ADV_DATA_EVT 4
+
+typedef UINT8 tBTA_BLE_MULTI_ADV_EVT;
+
+/* multi adv callback */
+typedef void (tBTA_BLE_MULTI_ADV_CBACK)(tBTA_BLE_MULTI_ADV_EVT event,
+ UINT8 inst_id, void *p_ref, tBTA_STATUS status);
+
/* Vendor Specific Command Callback */
typedef tBTM_VSC_CMPL_CB tBTA_VENDOR_CMPL_CBACK;
@@ -840,6 +943,7 @@
UINT8 ble_addr_type;
tBTM_BLE_EVT_TYPE ble_evt_type;
tBT_DEVICE_TYPE device_type;
+ UINT8 flag;
#endif
} tBTA_DM_INQ_RES;
@@ -901,7 +1005,7 @@
typedef void (tBTA_DM_EXEC_CBACK) (void * p_param);
/* Encryption callback*/
-typedef void (tBTA_DM_ENCRYPT_CBACK) (BD_ADDR bd_addr, tBTA_STATUS result);
+typedef void (tBTA_DM_ENCRYPT_CBACK) (BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_STATUS result);
#if BLE_INCLUDED == TRUE
#define BTA_DM_BLE_SEC_NONE BTM_BLE_SEC_NONE
@@ -961,12 +1065,95 @@
#define BTA_DM_PM_PARK_IDX 5 /* the actual index to bta_dm_pm_md[] for PARK mode */
#endif
-#define BTA_DM_SW_BB_TO_MM BTM_SW_BB_TO_MM
-#define BTA_DM_SW_MM_TO_BB BTM_SW_MM_TO_BB
-#define BTA_DM_SW_BB_TO_BTC BTM_SW_BB_TO_BTC
-#define BTA_DM_SW_BTC_TO_BB BTM_SW_BTC_TO_BB
+#ifndef BTA_DM_PM_SNIFF_A2DP_IDX
+#define BTA_DM_PM_SNIFF_A2DP_IDX BTA_DM_PM_SNIFF
+#endif
-typedef tBTM_SW_DIR tBTA_DM_SW_DIR;
+#ifndef BTA_DM_PM_SNIFF_HD_IDLE_IDX
+#define BTA_DM_PM_SNIFF_HD_IDLE_IDX BTA_DM_PM_SNIFF2
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_SCO_OPEN_IDX
+#define BTA_DM_PM_SNIFF_SCO_OPEN_IDX BTA_DM_PM_SNIFF3
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HD_ACTIVE_IDX
+#define BTA_DM_PM_SNIFF_HD_ACTIVE_IDX BTA_DM_PM_SNIFF4
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HH_OPEN_IDX
+#define BTA_DM_PM_SNIFF_HH_OPEN_IDX BTA_DM_PM_SNIFF2
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HH_ACTIVE_IDX
+#define BTA_DM_PM_SNIFF_HH_ACTIVE_IDX BTA_DM_PM_SNIFF2
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HH_IDLE_IDX
+#define BTA_DM_PM_SNIFF_HH_IDLE_IDX BTA_DM_PM_SNIFF2
+#endif
+
+
+#ifndef BTA_DM_PM_HH_OPEN_DELAY
+#define BTA_DM_PM_HH_OPEN_DELAY 30000
+#endif
+
+#ifndef BTA_DM_PM_HH_ACTIVE_DELAY
+#define BTA_DM_PM_HH_ACTIVE_DELAY 30000
+#endif
+
+#ifndef BTA_DM_PM_HH_IDLE_DELAY
+#define BTA_DM_PM_HH_IDLE_DELAY 30000
+#endif
+
+/* The Sniff Parameters defined below must be ordered from highest
+ * latency (biggest interval) to lowest latency. If there is a conflict
+ * among the connected services the setting with the lowest latency will
+ * be selected. If a device should override a sniff parameter then it
+ * must insure that order is maintained.
+ */
+#ifndef BTA_DM_PM_SNIFF_MAX
+#define BTA_DM_PM_SNIFF_MAX 800
+#define BTA_DM_PM_SNIFF_MIN 400
+#define BTA_DM_PM_SNIFF_ATTEMPT 4
+#define BTA_DM_PM_SNIFF_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF1_MAX
+#define BTA_DM_PM_SNIFF1_MAX 400
+#define BTA_DM_PM_SNIFF1_MIN 200
+#define BTA_DM_PM_SNIFF1_ATTEMPT 4
+#define BTA_DM_PM_SNIFF1_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF2_MAX
+#define BTA_DM_PM_SNIFF2_MAX 180
+#define BTA_DM_PM_SNIFF2_MIN 150
+#define BTA_DM_PM_SNIFF2_ATTEMPT 4
+#define BTA_DM_PM_SNIFF2_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF3_MAX
+#define BTA_DM_PM_SNIFF3_MAX 150
+#define BTA_DM_PM_SNIFF3_MIN 50
+#define BTA_DM_PM_SNIFF3_ATTEMPT 4
+#define BTA_DM_PM_SNIFF3_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF4_MAX
+#define BTA_DM_PM_SNIFF4_MAX 54
+#define BTA_DM_PM_SNIFF4_MIN 30
+#define BTA_DM_PM_SNIFF4_ATTEMPT 4
+#define BTA_DM_PM_SNIFF4_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_PARK_MAX
+#define BTA_DM_PM_PARK_MAX 800
+#define BTA_DM_PM_PARK_MIN 400
+#define BTA_DM_PM_PARK_ATTEMPT 0
+#define BTA_DM_PM_PARK_TIMEOUT 0
+#endif
+
/* Switch callback events */
#define BTA_DM_SWITCH_CMPL_EVT 0 /* Completion of the Switch API */
@@ -1004,6 +1191,12 @@
/* Device features mask definitions */
#define BTA_FEATURE_BYTES_PER_PAGE BTM_FEATURE_BYTES_PER_PAGE
#define BTA_EXT_FEATURES_PAGE_MAX BTM_EXT_FEATURES_PAGE_MAX
+/* ACL type
+*/
+#define BTA_DM_LINK_TYPE_BR_EDR 0x01
+#define BTA_DM_LINK_TYPE_LE 0x02
+#define BTA_DM_LINK_TYPE_ALL 0xFF
+typedef UINT8 tBTA_DM_LINK_TYPE;
/*****************************************************************************
** External Function Declarations
@@ -1255,6 +1448,21 @@
/*******************************************************************************
**
+** Function BTA_DmBondByTransport
+**
+** Description This function initiates a bonding procedure with a peer
+** device by designated transport. The bonding procedure enables
+** authentication and optionally encryption on the Bluetooth link.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBondByTransport(BD_ADDR bd_addr, tBTA_TRANSPORT transport);
+
+
+/*******************************************************************************
+**
** Function BTA_DmBondCancel
**
** Description This function cancels a bonding procedure with a peer
@@ -1577,11 +1785,13 @@
**
** Parameters: bd_addr - Address of the peer device
** remove_dev - remove device or not after link down
+** transport - which transport to close
+
**
** Returns void.
**
*******************************************************************************/
-BTA_API extern void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev);
+BTA_API extern void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transport);
/*******************************************************************************
**
@@ -1727,7 +1937,8 @@
** Returns void
**
*******************************************************************************/
-BTA_API extern void BTA_DmAddBleKey (BD_ADDR bd_addr, tBTA_LE_KEY_VALUE *p_le_key,
+BTA_API extern void BTA_DmAddBleKey (BD_ADDR bd_addr,
+ tBTA_LE_KEY_VALUE *p_le_key,
tBTA_LE_KEY_TYPE key_type);
/*******************************************************************************
@@ -1825,6 +2036,25 @@
BTA_API extern void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+/*******************************************************************************
+**
+** Function BTA_DmDiscoverByTransport
+**
+** Description This function does service discovery on particular transport
+** for services of a
+** peer device. When services.num_uuid is 0, it indicates all
+** GATT based services are to be searched; other wise a list of
+** UUID of interested services should be provided through
+** p_services->p_uuid.
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiscoverByTransport(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
+ tBTA_TRANSPORT transport);
/*******************************************************************************
**
@@ -1836,6 +2066,7 @@
** bring up unencrypted links, then later encrypt them.
**
** Parameters: bd_addr - Address of the peer device
+** transport - transport of the link to be encruypted
** p_callback - Pointer to callback function to indicat the
** link encryption status
** sec_act - This is the security action to indicate
@@ -1848,8 +2079,9 @@
**
**
*******************************************************************************/
-BTA_API extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
- tBTA_DM_BLE_SEC_ACT sec_act);
+BTA_API extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport,
+ tBTA_DM_ENCRYPT_CBACK *p_callback,
+ tBTA_DM_BLE_SEC_ACT sec_act);
/*******************************************************************************
@@ -1926,7 +2158,8 @@
**
*******************************************************************************/
BTA_API extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
- tBTA_BLE_ADV_DATA *p_adv_cfg);
+ tBTA_BLE_ADV_DATA *p_adv_cfg,
+ tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
/*******************************************************************************
**
@@ -1940,7 +2173,8 @@
**
*******************************************************************************/
BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask,
- tBTA_BLE_ADV_DATA *p_adv_cfg);
+ tBTA_BLE_ADV_DATA *p_adv_cfg,
+ tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
/*******************************************************************************
**
@@ -1955,6 +2189,83 @@
*******************************************************************************/
BTA_API extern void BTA_DmBleBroadcast (BOOLEAN start);
+
+/*******************************************************************************
+**
+** Function BTA_BleEnableAdvInstance
+**
+** Description This function enables the Multi ADV instance feature
+**
+** Parameters p_params Pointer to ADV param user defined structure
+** p_cback Pointer to Multi ADV callback structure
+** p_ref - Reference pointer
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params,
+ tBTA_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref);
+
+/*******************************************************************************
+**
+** Function BTA_BleUpdateAdvInstParam
+**
+** Description This function updates the Multi ADV instance params
+**
+** Parameters inst_id Instance ID
+** p_params Pointer to ADV param user defined structure
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleUpdateAdvInstParam (UINT8 inst_id,
+ tBTA_BLE_ADV_PARAMS *p_params);
+
+/*******************************************************************************
+**
+** Function BTA_BleCfgAdvInstData
+**
+** Description This function is called to configure the ADV instance data
+**
+** Parameters inst_id - Instance ID
+** is_scan_rsp - Boolean value Scan response
+** Pointer to User defined ADV data structure
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+ tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_data);
+
+/*******************************************************************************
+**
+** Function BTA_BleDisableAdvInstance
+**
+** Description This function is called to disable the ADV instance
+**
+** Parameters inst_id - Instance ID to be disabled
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleDisableAdvInstance(UINT8 inst_id);
+
+/*******************************************************************************
+**
+** Function BTA_DmBleUpdateConnectionParams
+**
+** Description Update connection parameters, can only be used when connection is up.
+**
+** Parameters: bd_addr - BD address of the peer
+** min_int - minimum connection interval, [0x0004~ 0x4000]
+** max_int - maximum connection interval, [0x0004~ 0x4000]
+** latency - slave latency [0 ~ 500]
+** timeout - supervision timeout [0x000a ~ 0xc80]
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
+ UINT16 max_int, UINT16 latency, UINT16 timeout);
#endif
#ifdef __cplusplus
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index b53b180..80af960 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -77,21 +77,32 @@
#define BTA_GATT_INSUF_RESOURCE GATT_INSUF_RESOURCE /* 0x0011 */
-#define BTA_GATT_ILLEGAL_PARAMETER GATT_ILLEGAL_PARAMETER /* 0x0087 */
-#define BTA_GATT_NO_RESOURCES GATT_NO_RESOURCES /* 0x0080 */
-#define BTA_GATT_INTERNAL_ERROR GATT_INTERNAL_ERROR /* 0x0081 */
-#define BTA_GATT_WRONG_STATE GATT_WRONG_STATE /* 0x0082 */
-#define BTA_GATT_DB_FULL GATT_DB_FULL /* 0x0083 */
-#define BTA_GATT_BUSY GATT_BUSY /* 0x0084 */
-#define BTA_GATT_ERROR GATT_ERROR /* 0x0085 */
-#define BTA_GATT_CMD_STARTED GATT_CMD_STARTED /* 0x0086 */
-#define BTA_GATT_PENDING GATT_PENDING /* 0x0088 */
-#define BTA_GATT_AUTH_FAIL GATT_AUTH_FAIL /* 0x0089 */
-#define BTA_GATT_MORE GATT_MORE /* 0x008a */
-#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 */
+#define BTA_GATT_NO_RESOURCES GATT_NO_RESOURCES /* 0x80 */
+#define BTA_GATT_INTERNAL_ERROR GATT_INTERNAL_ERROR /* 0x81 */
+#define BTA_GATT_WRONG_STATE GATT_WRONG_STATE /* 0x82 */
+#define BTA_GATT_DB_FULL GATT_DB_FULL /* 0x83 */
+#define BTA_GATT_BUSY GATT_BUSY /* 0x84 */
+#define BTA_GATT_ERROR GATT_ERROR /* 0x85 */
+#define BTA_GATT_CMD_STARTED GATT_CMD_STARTED /* 0x86 */
+#define BTA_GATT_ILLEGAL_PARAMETER GATT_ILLEGAL_PARAMETER /* 0x87 */
+#define BTA_GATT_PENDING GATT_PENDING /* 0x88 */
+#define BTA_GATT_AUTH_FAIL GATT_AUTH_FAIL /* 0x89 */
+#define BTA_GATT_MORE GATT_MORE /* 0x8a */
+#define BTA_GATT_INVALID_CFG GATT_INVALID_CFG /* 0x8b */
+#define BTA_GATT_SERVICE_STARTED GATT_SERVICE_STARTED /* 0x8c */
+#define BTA_GATT_ENCRYPED_MITM GATT_ENCRYPED_MITM /* GATT_SUCCESS */
+#define BTA_GATT_ENCRYPED_NO_MITM GATT_ENCRYPED_NO_MITM /* 0x8d */
+#define BTA_GATT_NOT_ENCRYPTED GATT_NOT_ENCRYPTED /* 0x8e */
+
+#define BTA_GATT_DUP_REG 0x8f /* 0x8f */
+#define BTA_GATT_ALREADY_OPEN 0x90 /* 0x90 */
+#define BTA_GATT_CANCEL 0x91 /* 0x91 */
+
+ /* 0xE0 ~ 0xFC reserved for future use */
+#define BTA_GATT_CCC_CFG_ERR GATT_CCC_CFG_ERR /* 0xFD Client Characteristic Configuration Descriptor Improperly Configured */
+#define BTA_GATT_PRC_IN_PROGRESS GATT_PRC_IN_PROGRESS /* 0xFE Procedure Already in progress */
+#define BTA_GATT_OUT_OF_RANGE GATT_OUT_OF_RANGE /* 0xFFAttribute value out of range */
+
typedef UINT8 tBTA_GATT_STATUS;
#define BTA_GATT_INVALID_CONN_ID GATT_INVALID_CONN_ID
@@ -117,6 +128,11 @@
#define BTA_GATTC_LISTEN_EVT 16 /* listen event */
#define BTA_GATTC_ENC_CMPL_CB_EVT 17 /* encryption complete callback event */
#define BTA_GATTC_CFG_MTU_EVT 18 /* configure MTU complete event */
+#define BTA_GATTC_ADV_DATA_EVT 19 /* ADV data event */
+#define BTA_GATTC_MULT_ADV_ENB_EVT 20 /* Enable Multi ADV event */
+#define BTA_GATTC_MULT_ADV_UPD_EVT 21 /* Update parameter event */
+#define BTA_GATTC_MULT_ADV_DATA_EVT 22 /* Multi ADV data event */
+#define BTA_GATTC_MULT_ADV_DIS_EVT 23 /* Disable Multi ADV event */
typedef UINT8 tBTA_GATTC_EVT;
@@ -325,6 +341,7 @@
UINT16 conn_id;
tBTA_GATTC_IF client_if;
BD_ADDR remote_bda;
+ tBTA_TRANSPORT transport;
UINT16 mtu;
}tBTA_GATTC_OPEN;
@@ -469,12 +486,9 @@
typedef tGATTS_SRV_CHG_REQ tBTA_GATTS_SRV_CHG_REQ;
typedef tGATTS_SRV_CHG_RSP tBTA_GATTS_SRV_CHG_RSP;
-enum
-{
- BTA_GATT_TRANSPORT_LE,
- BTA_GATT_TRANSPORT_BR_EDR,
- BTA_GATT_TRANSPORT_LE_BR_EDR
-};
+#define BTA_GATT_TRANSPORT_LE GATT_TRANSPORT_LE
+#define BTA_GATT_TRANSPORT_BR_EDR GATT_TRANSPORT_BR_EDR
+#define BTA_GATT_TRANSPORT_LE_BR_EDR GATT_TRANSPORT_LE_BR_EDR
typedef UINT8 tBTA_GATT_TRANSPORT;
/* attribute value */
@@ -552,6 +566,7 @@
BD_ADDR remote_bda;
UINT16 conn_id;
tBTA_GATT_REASON reason; /* report disconnect reason */
+ tBTA_GATT_TRANSPORT transport;
}tBTA_GATTS_CONN;
/* GATTS callback data */
@@ -560,7 +575,7 @@
tBTA_GATTS_REG_OPER reg_oper;
tBTA_GATTS_CREATE create;
tBTA_GATTS_SRVC_OPER srvc_oper;
- tBTA_GATT_STATUS status; /* BTA_GATTS_CONF_EVT */
+ tBTA_GATT_STATUS status; /* BTA_GATTS_CONF_EVT or BTA_GATTS_LISTEN_EVT */
tBTA_GATTS_ADD_RESULT add_result; /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
add char : BTA_GATTS_ADD_CHAR_EVT
add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
@@ -644,7 +659,8 @@
** Returns void
**
*******************************************************************************/
-BTA_API extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+BTA_API extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+ BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport);
/*******************************************************************************
**
@@ -1301,7 +1317,8 @@
** Returns void
**
*******************************************************************************/
- BTA_API extern void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+ BTA_API extern void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda,
+ BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport);
/*******************************************************************************
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
index ab51071..c1c6875 100644
--- a/bta/jv/bta_jv_act.c
+++ b/bta/jv/bta_jv_act.c
@@ -886,7 +886,7 @@
{
BTM_ReadRemoteDeviceName(p_data->get_rmt_name.bd_addr,
- (tBTM_CMPL_CB *)bta_jv_get_remote_device_name_cback);
+ (tBTM_CMPL_CB *)bta_jv_get_remote_device_name_cback, BT_TRANSPORT_BR_EDR);
}
/*******************************************************************************
@@ -903,11 +903,16 @@
tBTA_UTL_COD cod;
/* set class of device */
- /* BTA_JvSetServiceClass(UINT32 service) assumes that the service class passed to the API function as defined in the assigned number page.
- For example: the object transfer bit is bit 20 of the 24-bit Class of device; the value of this bit is 0x00100000 (value 1)
- Our btm_api.h defines this bit as #define BTM_COD_SERVICE_OBJ_TRANSFER 0x1000 // (value 2)
- This reflects that the service class defined at btm is UINT16, which starts at bit 8 of the 24 bit Class of Device
- The following statement converts from (value 1) into (value 2) */
+ /*
+ BTA_JvSetServiceClass(UINT32 service) assumes that the service class passed to the
+ API function as defined in the assigned number page.
+ For example: the object transfer bit is bit 20 of the 24-bit Class of device;
+ the value of this bit is 0x00100000 (value 1)
+ Our btm_api.h defines this bit as #define BTM_COD_SERVICE_OBJ_TRANSFER 0x1000 (value 2)
+ This reflects that the service class defined at btm is UINT16,
+ which starts at bit 8 of the 24 bit Class of Device
+ The following statement converts from (value 1) into (value 2)
+ */
cod.service = (p_data->set_service.service >> 8);
utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
}
@@ -921,9 +926,11 @@
** Returns void
**
*******************************************************************************/
-static void bta_jv_sec_cback (BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+static void bta_jv_sec_cback (BD_ADDR bd_addr, tBTA_TRANSPORT transport,
+ void *p_ref_data, tBTM_STATUS result)
{
UNUSED(p_ref_data);
+ UNUSED(transport);
tBTA_JV_SET_ENCRYPTION set_enc;
if(bta_jv_cb.p_dm_cback)
@@ -947,7 +954,7 @@
*******************************************************************************/
void bta_jv_set_encryption(tBTA_JV_MSG *p_data)
{
- BTM_SetEncryption(p_data->set_encrypt.bd_addr, bta_jv_sec_cback, NULL);
+ BTM_SetEncryption(p_data->set_encrypt.bd_addr, BTA_TRANSPORT_BR_EDR, bta_jv_sec_cback, NULL);
}
/*******************************************************************************
@@ -2578,7 +2585,7 @@
tBTA_JV_API_RFCOMM_SERVER *ls = &(p_data->rfcomm_server);
tBTA_JV_RFC_CB *p_cb = NULL;
tBTA_JV_PCB *p_pcb = NULL;
- APPL_TRACE_ERROR0("bta_jv_rfcomm_stop_server");
+ APPL_TRACE_DEBUG0("bta_jv_rfcomm_stop_server");
if(!ls->handle)
{
APPL_TRACE_ERROR0("bta_jv_rfcomm_stop_server, jv handle is null");
diff --git a/bta/jv/bta_jv_api.c b/bta/jv/bta_jv_api.c
index 16ab2d5..ad0b694 100644
--- a/bta/jv/bta_jv_api.c
+++ b/bta/jv/bta_jv_api.c
@@ -495,11 +495,13 @@
BOOLEAN BTA_JvIsEncrypted(BD_ADDR bd_addr)
{
BOOLEAN is_encrypted = FALSE;
- UINT8 sec_flags;
+ UINT8 sec_flags, le_flags;
- if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+ if (BTM_GetSecurityFlags(bd_addr, &sec_flags) &&
+ BTM_GetSecurityFlagsByTransport(bd_addr, &le_flags, BT_TRANSPORT_LE))
{
- if(sec_flags&BTM_SEC_FLAG_ENCRYPTED)
+ if(sec_flags & BTM_SEC_FLAG_ENCRYPTED ||
+ le_flags & BTM_SEC_FLAG_ENCRYPTED)
is_encrypted = TRUE;
}
return is_encrypted;
diff --git a/bta/sys/bta_sys.h b/bta/sys/bta_sys.h
index 5d724e5..8a66249 100644
--- a/bta/sys/bta_sys.h
+++ b/bta/sys/bta_sys.h
@@ -30,6 +30,30 @@
/*****************************************************************************
** Constants and data types
*****************************************************************************/
+/* ADV payload filtering vendor specific call event */
+enum
+{
+ BTA_VS_BLE_SCAN_PF_ENABLE_EVT = 7,
+ BTA_VS_BLE_SCAN_PF_COND_EVT
+};
+
+typedef struct
+{
+ BOOLEAN enable;
+ tBLE_BD_ADDR *p_target;
+ void *p_cmpl_cback;
+}tBTA_SYS_VS_BLE_SCAN_PF_ENABLE;
+
+typedef struct
+{
+ UINT8 action;
+ INT8 cond_type;
+ void *p_cond;
+ void *p_cmpl_cback;
+}tBTA_SYS_VS_BLE_SCAN_PF_COND;
+
+/* vendor specific event handler function type */
+typedef BOOLEAN (tBTA_SYS_VS_EVT_HDLR)(UINT16 evt, void *p);
/* event handler function type */
typedef BOOLEAN (tBTA_SYS_EVT_HDLR)(BT_HDR *p_msg);
@@ -300,6 +324,7 @@
extern void bta_sys_clear_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr);
extern void bta_sys_set_default_policy (UINT8 id, UINT8 policy);
extern void bta_sys_clear_default_policy (UINT8 id, UINT8 policy);
+extern BOOLEAN bta_sys_vs_hdl(UINT16 evt, void *p);
#ifdef __cplusplus
}
diff --git a/bta/sys/bta_sys_conn.c b/bta/sys/bta_sys_conn.c
index a5d1017..aef155b 100644
--- a/bta/sys/bta_sys_conn.c
+++ b/bta/sys/bta_sys_conn.c
@@ -578,3 +578,20 @@
}
#endif
+/*******************************************************************************
+**
+** Function bta_sys_vs_hdl
+**
+** Description Called by BTA subsystems to execute a VS event handler function
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_vs_hdl(UINT16 evt, void *p)
+{
+ if (bta_sys_cb.p_vs_evt_hdlr)
+ return (*bta_sys_cb.p_vs_evt_hdlr)(evt, p);
+
+ return FALSE;
+}
+
diff --git a/bta/sys/bta_sys_int.h b/bta/sys/bta_sys_int.h
index d187b29..32101a5 100644
--- a/bta/sys/bta_sys_int.h
+++ b/bta/sys/bta_sys_int.h
@@ -78,6 +78,9 @@
#if (BTM_SSR_INCLUDED == TRUE)
tBTA_SYS_SSR_CFG_CBACK *p_ssr_cb;
#endif
+ /* VS event handler */
+ tBTA_SYS_VS_EVT_HDLR *p_vs_evt_hdlr;
+
} tBTA_SYS_CB;
diff --git a/btif/co/bta_dm_co.c b/btif/co/bta_dm_co.c
index 13a5c8f..abf52bf 100644
--- a/btif/co/bta_dm_co.c
+++ b/btif/co/bta_dm_co.c
@@ -75,6 +75,7 @@
#if (BTM_OOB_INCLUDED == TRUE)
btif_dm_set_oob_for_io_req(p_oob_data);
#endif
+ btif_dm_proc_io_req(bd_addr, p_io_cap, p_oob_data, p_auth_req, is_orig);
BTIF_TRACE_DEBUG1("bta_dm_co_io_req *p_oob_data = %d", *p_oob_data);
BTIF_TRACE_DEBUG1("bta_dm_co_io_req *p_io_cap = %d", *p_io_cap);
BTIF_TRACE_DEBUG1("bta_dm_co_io_req *p_auth_req = %d", *p_auth_req);
@@ -99,10 +100,7 @@
void bta_dm_co_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req)
{
- UNUSED(bd_addr);
- UNUSED(io_cap);
- UNUSED(oob_data);
- UNUSED(auth_req);
+ btif_dm_proc_io_rsp(bd_addr, io_cap, oob_data, auth_req);
}
/*******************************************************************************
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index b393099..cf8569d 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -166,7 +166,7 @@
pfds[0].events = POLLIN;
while(p_dev->hh_keep_polling){
- ret = poll(pfds, 1, 500);
+ ret = poll(pfds, 1, 50);
if (ret < 0) {
APPL_TRACE_ERROR2("%s: Cannot poll for fds: %s\n", __FUNCTION__, strerror(errno));
break;
diff --git a/btif/co/bta_pan_co.c b/btif/co/bta_pan_co.c
index 1dcce8e..b0f2945 100644
--- a/btif/co/bta_pan_co.c
+++ b/btif/co/bta_pan_co.c
@@ -33,6 +33,7 @@
#include <hardware/bluetooth.h>
#include <hardware/bt_pan.h>
#include "btif_pan_internal.h"
+#include "btif_sock_thread.h"
#include "bd.h"
#include <string.h>
#include "btif_util.h"
@@ -98,6 +99,7 @@
}
if(btpan_cb.tap_fd >= 0)
{
+ btpan_cb.flow = 1;
conn->state = PAN_STATE_OPEN;
bta_pan_ci_rx_ready(handle);
}
@@ -129,14 +131,10 @@
conn->state = PAN_STATE_CLOSE;
btpan_cb.open_count--;
- if(btpan_cb.open_count == 0)
+ if(btpan_cb.open_count == 0 && btpan_cb.tap_fd != -1)
{
- destroy_tap_read_thread();
- if(btpan_cb.tap_fd != -1)
- {
- btpan_tap_close(btpan_cb.tap_fd);
- btpan_cb.tap_fd = -1;
- }
+ btpan_tap_close(btpan_cb.tap_fd);
+ btpan_cb.tap_fd = -1;
}
}
}
@@ -171,7 +169,7 @@
BTIF_TRACE_API2("bta_pan_co_tx_path, handle:%d, app_id:%d", handle, app_id);
btpan_conn_t* conn = btpan_find_conn_handle(handle);
- if(conn && conn->state != PAN_STATE_OPEN)
+ if(!conn || conn->state != PAN_STATE_OPEN)
{
BTIF_TRACE_ERROR2("bta_pan_co_tx_path: cannot find pan connction or conn"
"is not opened, conn:%p, conn->state:%d", conn, conn->state);
@@ -304,6 +302,10 @@
UNUSED(enable);
BTIF_TRACE_API1("bta_pan_co_rx_flow, enabled:%d, not used", enable);
+ btpan_conn_t* conn = btpan_find_conn_handle(handle);
+ if(!conn || conn->state != PAN_STATE_OPEN)
+ return;
+ btpan_set_flow_control(enable);
}
/*******************************************************************************
diff --git a/btif/include/btif_config_util.h b/btif/include/btif_config_util.h
index 3a2f53e..6a8bb72 100644
--- a/btif/include/btif_config_util.h
+++ b/btif/include/btif_config_util.h
@@ -44,7 +44,7 @@
#define BLUEZ_TYPES "types"
#define BLUEZ_CONFIG "config"
#define BLUEZ_ALIASES "aliases"
-
+#define BLUEZ_SDP "sdp"
/*******************************************************************************
** Functions
diff --git a/btif/include/btif_dm.h b/btif/include/btif_dm.h
index ed03e34..37f11b7 100644
--- a/btif/include/btif_dm.h
+++ b/btif/include/btif_dm.h
@@ -36,6 +36,17 @@
void btif_dm_on_disable(void);
/**
+ * Callout for handling io_capabilities request
+ */
+void btif_dm_proc_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap, tBTA_OOB_DATA *p_oob_data,
+ tBTA_AUTH_REQ *p_auth_req, BOOLEAN is_orig);
+/**
+ * Callout for handling io_capabilities response
+ */
+void btif_dm_proc_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+ tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req);
+
+/**
* Out-of-band functions
*/
#if (BTM_OOB_INCLUDED == TRUE)
diff --git a/btif/include/btif_gatt_multi_adv_util.h b/btif/include/btif_gatt_multi_adv_util.h
new file mode 100644
index 0000000..2fef449
--- /dev/null
+++ b/btif/include/btif_gatt_multi_adv_util.h
@@ -0,0 +1,87 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 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_MULTI_ADV_UTIL_H
+#define BTIF_GATT_MULTI_ADV_UTIL_H
+
+#include <hardware/bluetooth.h>
+#include "bta_api.h"
+
+#define CLNT_IF_IDX 0
+#define INST_ID_IDX 1
+#define INVALID_ADV_INST -1
+#define STD_ADV_INSTID 0
+#define ADV_FLAGS 0x02
+
+typedef struct
+{
+ int client_if;
+ BOOLEAN set_scan_rsp;
+ BOOLEAN include_name;
+ BOOLEAN include_txpower;
+ int min_interval;
+ int max_interval;
+ int appearance;
+ uint16_t manufacturer_len;
+ uint8_t* p_manufacturer_data;
+ uint16_t service_data_len;
+ uint8_t* p_service_data;
+ uint16_t service_uuid_len;
+ uint8_t* p_service_uuid;
+} btif_adv_data_t;
+
+typedef struct
+{
+ UINT8 inst_id;
+ BOOLEAN is_scan_rsp;
+ UINT8 client_if;
+ UINT16 service_uuid_len;
+ tBTA_BLE_AD_MASK mask;
+ tBTA_BLE_ADV_DATA data;
+ tBTA_BLE_ADV_PARAMS param;
+}btgatt_multi_adv_inst_cb;
+
+typedef struct
+{
+ INT8 clntif_map[BTM_BLE_MULTI_ADV_MAX][INST_ID_IDX+1];
+ // Includes the stored data for standard LE instance
+ btgatt_multi_adv_inst_cb inst_cb[BTM_BLE_MULTI_ADV_MAX+1];
+} btgatt_multi_adv_common_data;
+
+extern btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb();
+extern void btif_gattc_init_multi_adv_cb(void);
+extern void btif_gattc_destroy_multi_adv_cb();
+extern int btif_multi_adv_add_instid_map(int client_if, int inst_id,
+ BOOLEAN gen_temp_instid);
+extern int btif_multi_adv_instid_for_clientif(int client_if);
+extern int btif_gattc_obtain_idx_for_datacb(int value, int arrindex);
+extern void btif_gattc_clear_clientif(int client_if);
+extern void btif_gattc_cleanup_inst_cb(int inst_id);
+extern void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_inst_cb);
+extern BOOLEAN btif_gattc_copy_datacb(int arrindex, btif_adv_data_t *p_adv_data,
+ BOOLEAN bInstData);
+extern void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp,
+ bool include_name, bool include_txpower, int min_interval, int max_interval,
+ int appearance, uint16_t manufacturer_len, char* manufacturer_data,
+ uint16_t service_data_len, char* service_data, uint16_t service_uuid_len,
+ char* service_uuid, btif_adv_data_t *p_multi_adv_inst);
+
+#endif
+
+
diff --git a/btif/include/btif_gatt_util.h b/btif/include/btif_gatt_util.h
index 74ac6bc..87c263b 100644
--- a/btif/include/btif_gatt_util.h
+++ b/btif/include/btif_gatt_util.h
@@ -26,6 +26,7 @@
void btif_to_bta_gatt_id(tBTA_GATT_ID *p_dest, btgatt_gatt_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 btif_to_bta_uuid_mask(tBTA_DM_BLE_PF_COND_MASK *p_mask, bt_uuid_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);
diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h
old mode 100755
new mode 100644
diff --git a/btif/include/btif_pan_internal.h b/btif/include/btif_pan_internal.h
index d697ac8..64bab99 100644
--- a/btif/include/btif_pan_internal.h
+++ b/btif/include/btif_pan_internal.h
@@ -79,7 +79,10 @@
int tap_fd;
int enabled;
int open_count;
+ int flow; // 1: outbound data flow on; 0: outbound data flow off
btpan_conn_t conns[MAX_PAN_CONNS];
+ int congest_packet_size;
+ unsigned char congest_packet[1600]; //max ethernet packet size
} btpan_cb_t;
@@ -91,6 +94,7 @@
btpan_conn_t *btpan_new_conn(int handle, const BD_ADDR addr, int local_role, int peer_role);
btpan_conn_t *btpan_find_conn_addr(const BD_ADDR addr);
btpan_conn_t *btpan_find_conn_handle(UINT16 handle);
+void btpan_set_flow_control(BOOLEAN enable);
int btpan_get_connected_count(void);
int btpan_tap_open(void);
void create_tap_read_thread(int tap_fd);
diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h
index 9a69b00..f64c695 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -353,4 +353,34 @@
bt_status_t btif_storage_get_remote_version(const bt_bdaddr_t *remote_bd_addr,
bt_remote_version_t *p_ver);
+
+/*******************************************************************************
+**
+** Function btif_storage_set_dmt_support_type
+**
+** Description Sets DMT support status for a remote device
+**
+** Returns BT_STATUS_SUCCESS if config update is successful
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+
+bt_status_t btif_storage_set_dmt_support_type(const bt_bdaddr_t *remote_bd_addr,
+ BOOLEAN dmt_supported);
+
+
+
+/*******************************************************************************
+**
+** Function btif_storage_is_dmt_supported_device
+**
+** Description checks if a device supports Dual mode topology
+**
+** Returns TRUE if remote supports DMT else FALSE
+**
+*******************************************************************************/
+
+BOOLEAN btif_storage_is_dmt_supported_device(const bt_bdaddr_t *remote_bd_addr);
+
+
#endif /* BTIF_STORAGE_H */
diff --git a/btif/include/btif_util.h b/btif/include/btif_util.h
old mode 100755
new mode 100644
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c
old mode 100755
new mode 100644
index f6c2f48..fe4182f
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -68,8 +68,6 @@
** Externs
************************************************************************************/
-extern bt_wakelock_callback config_wakelock_callback;
-
/* list all extended interfaces here */
/* handsfree profile */
@@ -121,7 +119,6 @@
/* store reference to user callbacks */
bt_hal_cbacks = callbacks;
- config_wakelock_callback = callbacks->bt_wakelock_cb;
/* add checks for individual callbacks ? */
@@ -330,7 +327,7 @@
if (is_profile(profile_id, BT_PROFILE_HEALTH_ID))
return btif_hl_get_interface();
-#if BTA_GATT_INCLUDED == TRUE
+#if ( BTA_GATT_INCLUDED == TRUE &&BLE_INCLUDED == TRUE)
if (is_profile(profile_id, BT_PROFILE_GATT_ID))
return btif_gatt_get_interface();
#endif
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
old mode 100755
new mode 100644
index 3c0c293..f893c9e
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -39,6 +39,7 @@
#include "gki.h"
#include "bd.h"
#include "btu.h"
+#include "bt_utils.h"
/*****************************************************************************
** Constants & Macros
@@ -587,9 +588,17 @@
HAL_CBACK(bt_av_callbacks, audio_state_cb,
BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));
+
+ /* increase the a2dp consumer task priority temporarily when start
+ ** audio playing, to avoid overflow the audio packet queue. */
+ adjust_priority_a2dp(TRUE);
+
break;
case BTIF_SM_EXIT_EVT:
+ /* restore the a2dp consumer task priority when stop audio playing. */
+ adjust_priority_a2dp(FALSE);
+
break;
case BTIF_AV_START_STREAM_REQ_EVT:
diff --git a/btif/src/btif_config_util.cpp b/btif/src/btif_config_util.cpp
index 0cc2b36..a6d9f6f 100644
--- a/btif/src/btif_config_util.cpp
+++ b/btif/src/btif_config_util.cpp
@@ -56,6 +56,41 @@
#define BLUEDROID_VALUE_TYPE "Type"
#define BLUEDROID_TAG_REMOTE_DEVICE "Remote Devices"
+#define HID_SUB_CLASS "020208"
+#define HID_COUNTRY_CODE "020308"
+#define HID_VIRTUAL_CABLE "020428"
+#define HID_RECON_INNITIATE "020528"
+#define HID_REP_DSC_1 "020636"
+#define HID_REP_DSC_2 "020635"
+#define HID_SDP_DISABLE "020828"
+#define HID_BAT_POWER "020928"
+#define HID_REM_WAKE "020A28"
+#define HID_SUP_TIME "020C09"
+#define HID_NORM_CONN "020D28"
+#define HID_SSR_MAX_LAT "020F09"
+#define HID_SSR_MIN_TIM "021009"
+#define HID_VENDOR_ID "020109"
+#define HID_PRODUCT_ID "020209"
+#define HID_PRODUCT_VERSION "020309"
+#define HID_APP_ID_MOUSE 1
+#define HID_APP_ID_KYB 2
+#define HID_PAIRED_DEV_PRIORITY 100
+#define HID_SSR_PARAM_INVALID 0xffff
+#define HID_RPT_DSCR_HDR_LEN_1 10
+#define HID_RPT_DSCR_HDR_LEN_2 7
+
+/* Hid Atribute Mask */
+#define HID_ATTR_MASK_VIRTUAL_CABLE 0x0001
+#define HID_ATTR_MASK_NORMALLY_CONNECTABLE 0x0002
+#define HID_ATTR_MASK_RECONN_INIT 0x0004
+#define HID_ATTR_MASK_SDP_DISABLE 0x0008
+#define HID_ATTR_MASK_BATTERY_POWER 0x0010
+#define HID_ATTR_MASK_REMOTE_WAKE 0x0020
+#define HID_ATTR_MASK_SUP_TOUT_AVLBL 0x0040
+#define HID_ATTR_MASK_SSR_MAX_LATENCY 0x0080
+#define HID_ATTR_MASK_SSR_MIN_TOUT 0x0100
+#define HID_ATTR_MASK_SEC_REQUIRED 0x8000
+
using namespace tinyxml2;
struct enum_user_data
{
@@ -523,6 +558,200 @@
laddr[i] - ('a' - 'A') : laddr[i];
uaddr[i] = 0;
}
+
+static int parse_hid_attribute(const char *str, int line_size, int len)
+{
+ if (len == 0 || line_size == 0 || str == NULL || (len%2))
+ return 0;
+
+ char hex_string[len + 1], hex_bytes[len/2];
+ memcpy(hex_string, str - 1, len);
+ hex_string[len] = 0;
+ hex2bytes(hex_string, len, hex_bytes);
+ if (len == 2)
+ return hex_bytes[0];
+ else if (len == 4)
+ return hex_bytes[0] << 8 | hex_bytes[1];
+ else return 0;
+}
+
+static int parse_bluez_hid_sdp_records(const char* adapter_path, const char* bd_addr)
+{
+ //debug("in");
+ char addr[32];
+ char pattern_to_search[50];
+ upcase_addr(bd_addr, addr, sizeof(addr));
+
+ const char* map = NULL;
+ int size = 0;
+ int ret = FALSE;
+ char path[256];
+ snprintf(path, sizeof(path), "%s/%s", adapter_path, BLUEZ_SDP);
+ int fd = open_file_map(path, &map, &size);
+ //debug("in, path:%s, addr:%s, fd:%d, size:%d", path, addr, fd, size);
+ if(fd < 0 || size == 0)
+ {
+ error("open_file_map fail, fd:%d, path:%s, size:%d", fd, path, size);
+ //debug("out");
+ return FALSE;
+ }
+ int line_size = 0;
+ snprintf(pattern_to_search, sizeof(pattern_to_search), "%s#00010000", addr);
+ const char *value_line = find_value_line(map, size, pattern_to_search, &line_size);
+ int dev_sub_class = 0;
+ int app_id = 0;
+ int countrycode = 0;
+ int product = 0;
+ int vendor = 0;
+ int product_ver = 0;
+ int attr_mask = 0;
+ int ssr_max_lat = 0;
+ int ssr_min_timeout = 0;
+ int rep_desc_len = 0;
+ if(value_line && line_size)
+ {
+ char hid_sdp[line_size + 2];
+ memcpy(hid_sdp, value_line - 1, line_size);
+ hid_sdp[line_size + 1] = 0;
+ //debug("addr:%s, hid_sdp:%s", bd_addr, hid_sdp);
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_SUB_CLASS, &line_size);
+ dev_sub_class = parse_hid_attribute(value_line, line_size, 2);
+ if(dev_sub_class)
+ {
+ if ((dev_sub_class & 0x80) == 0x80)
+ app_id = HID_APP_ID_MOUSE;
+ else
+ app_id = HID_APP_ID_KYB;
+ //debug("dev_sub_class:%d", dev_sub_class);
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_COUNTRY_CODE, &line_size);
+ countrycode = parse_hid_attribute(value_line, line_size, 2);
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_VIRTUAL_CABLE, &line_size);
+ if(parse_hid_attribute(value_line, line_size, 2))
+ {
+ attr_mask |= HID_ATTR_MASK_VIRTUAL_CABLE;
+ //debug("attr_mask after Virtual Unplug:%04x", attr_mask);
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_RECON_INNITIATE, &line_size);
+ if(parse_hid_attribute(value_line, line_size, 2))
+ {
+ attr_mask |= HID_ATTR_MASK_RECONN_INIT;
+ //debug("attr_mask after Reconnect Initiate:%04x", attr_mask);
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_REP_DSC_1, &line_size);
+ if(value_line && line_size)
+ {
+ char rep_desc[line_size + 1], rd[line_size/2 + 1];
+ char rep_dsc_len[5], rd_len[2];
+ memcpy(rep_dsc_len, value_line - 1, 4);
+ rep_dsc_len[4] = 0;
+ hex2bytes(rep_dsc_len, 4, rd_len);
+ rep_desc_len = (rd_len[0] << 8 | rd_len[1]) - (HID_RPT_DSCR_HDR_LEN_1 - 2);
+ //debug("rep_desc_len:%d", rep_desc_len);
+ memcpy(rep_desc, value_line - 1 + (HID_RPT_DSCR_HDR_LEN_1 * 2), rep_desc_len * 2);
+ rep_desc[rep_desc_len * 2] = 0;
+ hex2bytes(rep_desc, rep_desc_len* 2, rd);
+ if (rep_desc_len)
+ {
+ //debug("rep_desc:%s", rep_desc);
+ btif_config_set("Remote", bd_addr, "HidDescriptor", rd, rep_desc_len,
+ BTIF_CFG_TYPE_BIN);
+ }
+ }
+ else
+ {
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_REP_DSC_2, &line_size);
+ if(value_line && line_size)
+ {
+ char rep_dsc_len[3], rd_len[1];
+ memcpy(rep_dsc_len, value_line - 1, 2);
+ rep_dsc_len[2] = 0;
+ hex2bytes(rep_dsc_len, 2, rd_len);
+ rep_desc_len = rd_len[0] - (HID_RPT_DSCR_HDR_LEN_2 - 1);
+ //debug("rep_desc_len:%d", rep_desc_len);
+ char rep_desc[(rep_desc_len * 2) + 1], rd[rep_desc_len + 1];
+ memcpy(rep_desc, value_line - 1 + (HID_RPT_DSCR_HDR_LEN_2 * 2), rep_desc_len * 2);
+ rep_desc[rep_desc_len * 2] = 0;
+ hex2bytes(rep_desc, rep_desc_len * 2, rd);
+ if (rep_desc_len)
+ {
+ //debug("rep_desc:%s", rep_desc);
+ btif_config_set("Remote", bd_addr, "HidDescriptor", rd, rep_desc_len,
+ BTIF_CFG_TYPE_BIN);
+ }
+ }
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_SDP_DISABLE, &line_size);
+ if(parse_hid_attribute(value_line, line_size, 2))
+ {
+ attr_mask |= HID_ATTR_MASK_SDP_DISABLE;
+ //debug("attr_mask after SDP Disable:%04x", attr_mask);
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_BAT_POWER, &line_size);
+ if(parse_hid_attribute(value_line, line_size, 2))
+ {
+ attr_mask |= HID_ATTR_MASK_BATTERY_POWER;
+ //debug("attr_mask after Battery Powered:%04x", attr_mask);
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_REM_WAKE, &line_size);
+ if(parse_hid_attribute(value_line, line_size, 2))
+ {
+ attr_mask |= HID_ATTR_MASK_REMOTE_WAKE;
+ //debug("attr_mask after Remote Wake:%04x", attr_mask);
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_NORM_CONN, &line_size);
+ if(parse_hid_attribute(value_line, line_size, 2))
+ {
+ attr_mask |= HID_ATTR_MASK_NORMALLY_CONNECTABLE;
+ //debug("attr_mask after Normally Conenctable:%04x", attr_mask);
+ }
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_SUP_TIME, &line_size);
+ if(value_line && line_size)
+ attr_mask |= HID_ATTR_MASK_SUP_TOUT_AVLBL;
+ //debug("attr_mask after Supervision Timeout:%04x", attr_mask);
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_SSR_MAX_LAT, &line_size);
+ ssr_max_lat = parse_hid_attribute(value_line, line_size, 4);
+ if(!ssr_max_lat)
+ ssr_max_lat = HID_SSR_PARAM_INVALID;
+ value_line = find_value_line(hid_sdp, strlen(hid_sdp), HID_SSR_MIN_TIM, &line_size);
+ ssr_min_timeout = parse_hid_attribute(value_line, line_size, 4);
+ if(!ssr_min_timeout)
+ ssr_min_timeout = HID_SSR_PARAM_INVALID;
+ snprintf(pattern_to_search, sizeof(pattern_to_search), "%s#00010001", addr);
+ value_line = find_value_line(map, size, pattern_to_search, &line_size);
+ if(value_line && line_size)
+ {
+ char did_sdp[line_size + 2];
+ memcpy(did_sdp, value_line - 1, line_size + 1);
+ did_sdp[line_size + 1] = 0;
+ //debug("addr:%s, did_sdp:%s", bd_addr, did_sdp);
+ value_line = find_value_line(did_sdp, strlen(did_sdp), HID_VENDOR_ID, &line_size);
+ vendor = parse_hid_attribute(value_line, line_size, 4);
+ value_line = find_value_line(did_sdp, strlen(did_sdp), HID_PRODUCT_ID, &line_size);
+ product = parse_hid_attribute(value_line, line_size, 4);
+ value_line = find_value_line(did_sdp, strlen(did_sdp), HID_PRODUCT_VERSION, &line_size);
+ product_ver = parse_hid_attribute(value_line, line_size, 4);
+ }
+ }
+ btif_config_set_int("Remote", bd_addr, "HidAttrMask", attr_mask);
+ btif_config_set_int("Remote", bd_addr, "HidSubClass", dev_sub_class);
+ btif_config_set_int("Remote", bd_addr, "HidAppId", app_id);
+ btif_config_set_int("Remote", bd_addr, "HidVendorId", vendor);
+ btif_config_set_int("Remote", bd_addr, "HidProductId", product);
+ btif_config_set_int("Remote", bd_addr, "HidVersion", product_ver);
+ btif_config_set_int("Remote", bd_addr, "HidCountryCode", countrycode);
+ btif_config_set_int("Remote", bd_addr, "HidSSRMinTimeout", ssr_min_timeout);
+ btif_config_set_int("Remote", bd_addr, "HidSSRMaxLatency", ssr_max_lat);
+ //debug("HidSubClass: %02x, app_id = %d, vendor = %04x, product = %04x, product_ver = %04x"
+ // "countrycode = %02x, ssr_min_timeout = %04x, ssr_max_lat = %04x",
+ // HidSubClass, app_id, vendor, product, product_ver, countrycode, ssr_min_timeout,
+ // ssr_max_lat);
+ close_file_map(fd, map, size);
+ ret = TRUE;
+ //debug("out, ret:%d", ret);
+ return ret;
+}
+
static int load_bluez_dev_value(const char* adapter_path, const char* bd_addr,
const char* file_name, const char* cfg_value_name, int type)
{
@@ -558,15 +787,15 @@
else if(type == BTIF_CFG_TYPE_INT)
{
int v = strtol(line, NULL, 16);
- //filter out unspported devices by its class
+ //parse sdp record in case remote device is hid
if(strcmp(file_name, BLUEZ_CLASSES) == 0)
{
switch((v & 0x1f00) >> 8)
{
case 0x5: //hid device
- error("skip paired hid devices");
- close_file_map(fd, map, size);
- return FALSE;
+ info("parsing sdp for hid device %s", bd_addr);
+ parse_bluez_hid_sdp_records(adapter_path, bd_addr);
+ break;
}
}
btif_config_set_int("Remote", bd_addr, cfg_value_name, v);
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c
index 5fcee4e..77381ef 100644
--- a/btif/src/btif_core.c
+++ b/btif/src/btif_core.c
@@ -50,6 +50,7 @@
#include "btif_pan.h"
#include "btif_profile_queue.h"
#include "btif_config.h"
+#include "bta_vendor_api.h"
/************************************************************************************
** Constants & Macros
************************************************************************************/
@@ -607,6 +608,12 @@
/* callback to HAL */
if (status == BTA_SUCCESS)
{
+#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE)
+ BTA_BrcmInit();
+#endif
+ /* initialize a2dp service */
+ btif_av_init();
+
/* init rfcomm & l2cap api */
btif_sock_init();
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index cd75b3e..4ef9e2c 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -84,6 +84,8 @@
UINT8 is_temp;
UINT8 pin_code_len;
UINT8 is_ssp;
+ UINT8 auth_req;
+ UINT8 io_cap;
UINT8 autopair_attempts;
UINT8 is_local_initiated;
UINT8 sdp_attempts;
@@ -283,6 +285,7 @@
sizeof(uint32_t), &remote_cod);
if (btif_storage_get_remote_device_property((bt_bdaddr_t *)remote_bdaddr, &prop_name) == BT_STATUS_SUCCESS)
{
+ BTIF_TRACE_ERROR2("%s: remote_cod = 0x%06x", __FUNCTION__, remote_cod);
if ((remote_cod & 0x7ff) == cod)
return TRUE;
}
@@ -301,6 +304,7 @@
if (btif_storage_get_remote_device_property((bt_bdaddr_t *)remote_bdaddr,
&prop_name) == BT_STATUS_SUCCESS)
{
+ BTIF_TRACE_DEBUG2("%s: remote_cod = 0x%06x", __FUNCTION__, remote_cod);
if ((remote_cod & 0x700) == cod)
return TRUE;
}
@@ -415,9 +419,18 @@
/* class of device */
cod = devclass2uint(dev_class);
+ BTIF_TRACE_DEBUG2("%s():cod is 0x%06x", __FUNCTION__, cod);
if ( cod == 0) {
- BTIF_TRACE_DEBUG1("%s():cod is 0, set as unclassified", __FUNCTION__);
- cod = COD_UNCLASSIFIED;
+ /* Try to retrieve cod from storage */
+ BTIF_TRACE_DEBUG1("%s():cod is 0, checking cod from storage", __FUNCTION__);
+ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
+ BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod);
+ status = btif_storage_get_remote_device_property(&bdaddr, &properties[num_properties]);
+ BTIF_TRACE_DEBUG2("%s():cod retreived from storage is 0x%06x", __FUNCTION__, cod);
+ if ( cod == 0) {
+ BTIF_TRACE_DEBUG1("%s():cod is again 0, set as unclassified", __FUNCTION__);
+ cod = COD_UNCLASSIFIED;
+ }
}
BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
@@ -847,6 +860,13 @@
{
BTIF_TRACE_DEBUG3("%s: Temporary key. Not storing. key_type=0x%x, is_temp=%d",
__FUNCTION__, p_auth_cmpl->key_type, pairing_cb.is_temp);
+ if(pairing_cb.is_temp)
+ {
+ BTIF_TRACE_DEBUG1("%s: sending BT_BOND_STATE_NONE for Temp pairing",
+ __FUNCTION__);
+ bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_NONE);
+ return;
+ }
}
}
if (p_auth_cmpl->success)
@@ -875,12 +895,16 @@
/* map the auth failure codes, so we can retry pairing if necessary */
case HCI_ERR_AUTH_FAILURE:
+ btif_storage_remove_bonded_device(&bd_addr);
case HCI_ERR_HOST_REJECT_SECURITY:
case HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE:
case HCI_ERR_UNIT_KEY_USED:
case HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED:
case HCI_ERR_INSUFFCIENT_SECURITY:
- BTIF_TRACE_DEBUG1(" %s() Authentication fail ", __FUNCTION__);
+ case HCI_ERR_PEER_USER:
+ case HCI_ERR_UNSPECIFIED:
+ BTIF_TRACE_DEBUG2(" %s() Authentication fail reason %d",
+ __FUNCTION__, p_auth_cmpl->fail_reason);
if (pairing_cb.autopair_attempts == 1)
{
BTIF_TRACE_DEBUG1("%s(): Adding device to blacklist ", __FUNCTION__);
@@ -912,6 +936,12 @@
default:
status = BT_STATUS_FAIL;
}
+ /* Special Handling for HID Devices */
+ if (check_cod(&bd_addr, COD_HID_POINTING)) {
+ /* Remove Device as bonded in nvram as authentication failed */
+ BTIF_TRACE_DEBUG1("%s(): removing hid pointing device from nvram", __FUNCTION__);
+ btif_storage_remove_bonded_device(&bd_addr);
+ }
bond_state_changed(status, &bd_addr, state);
}
}
@@ -1045,6 +1075,12 @@
ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote device (inquiry)", status);
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
status = btif_storage_set_remote_addr_type(&bdaddr, addr_type);
+ if (( dev_type == BT_DEVICE_TYPE_DUMO)&&
+ (p_search_data->inq_res.flag & BTA_BLE_DMT_CONTROLLER_SPT) &&
+ (p_search_data->inq_res.flag & BTA_BLE_DMT_HOST_SPT))
+ {
+ btif_storage_set_dmt_support_type (&bdaddr, TRUE);
+ }
ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote addr type (inquiry)", status);
#endif
/* Callback to notify upper layer of device */
@@ -1334,6 +1370,11 @@
btif_storage_load_autopair_device_list();
btif_enable_bluetooth_evt(p_data->enable.status, p_data->enable.bd_addr);
+
+ #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+ /* Enable local privacy */
+ BTA_DmBleConfigLocalPrivacy(TRUE);
+ #endif
}
break;
@@ -2181,6 +2222,63 @@
return;
}
+void btif_dm_proc_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap, tBTA_OOB_DATA *p_oob_data,
+ tBTA_AUTH_REQ *p_auth_req, BOOLEAN is_orig)
+{
+ UINT8 yes_no_bit = BTA_AUTH_SP_YES & *p_auth_req;
+ /* if local initiated:
+ ** 1. set DD + MITM
+ ** if remote initiated:
+ ** 1. Copy over the auth_req from peer's io_rsp
+ ** 2. Set the MITM if peer has it set or if peer has DisplayYesNo (iPhone)
+ ** as a fallback set MITM+GB if peer had MITM set
+ */
+ UNUSED (bd_addr);
+ UNUSED (p_io_cap);
+ UNUSED (p_oob_data);
+
+
+ BTIF_TRACE_DEBUG2("+%s: p_auth_req=%d", __FUNCTION__, *p_auth_req);
+ if(pairing_cb.is_local_initiated)
+ {
+ /* if initing/responding to a dedicated bonding, use dedicate bonding bit */
+ *p_auth_req = BTA_AUTH_DD_BOND | BTA_AUTH_SP_YES;
+ }
+ else if (!is_orig)
+ {
+ /* peer initiated paring. They probably know what they want.
+ ** Copy the mitm from peer device.
+ */
+ BTIF_TRACE_DEBUG2("%s: setting p_auth_req to peer's: %d",
+ __FUNCTION__, pairing_cb.auth_req);
+ *p_auth_req = (pairing_cb.auth_req & BTA_AUTH_BONDS);
+
+ /* copy over the MITM bit as well. In addition if the peer has DisplayYesNo, force MITM */
+ if ((yes_no_bit) || (pairing_cb.io_cap & BTM_IO_CAP_IO) )
+ *p_auth_req |= BTA_AUTH_SP_YES;
+ }
+ else if (yes_no_bit)
+ {
+ /* set the general bonding bit for stored device */
+ *p_auth_req = BTA_AUTH_GEN_BOND | yes_no_bit;
+ }
+ BTIF_TRACE_DEBUG2("-%s: p_auth_req=%d", __FUNCTION__, *p_auth_req);
+}
+
+void btif_dm_proc_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+ tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req)
+{
+ UNUSED (bd_addr);
+ UNUSED (oob_data);
+
+ if(auth_req & BTA_AUTH_BONDS)
+ {
+ BTIF_TRACE_DEBUG2("%s auth_req:%d", __FUNCTION__, auth_req);
+ pairing_cb.auth_req = auth_req;
+ pairing_cb.io_cap = io_cap;
+ }
+}
+
#if (BTM_OOB_INCLUDED == TRUE)
void btif_dm_set_oob_for_io_req(tBTA_OOB_DATA *p_oob_data)
{
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index c788bd8..2202e99 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -38,7 +38,7 @@
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
-#include "gki.h"
+#include "btif_gatt_multi_adv_util.h"
#include <hardware/bt_gatt.h>
#include "bta_api.h"
#include "bta_gatt_api.h"
@@ -51,12 +51,13 @@
#include "btif_dm.h"
#include "btif_storage.h"
+#include "bta_vendor_api.h"
+#include "vendor_api.h"
+
/*******************************************************************************
** Constants & Macros
********************************************************************************/
-#define ADV_FLAGS 0x02
-
#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
{\
ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
@@ -92,12 +93,21 @@
BTIF_GATTC_LISTEN,
BTIF_GATTC_SET_ADV_DATA,
BTIF_GATTC_CONFIGURE_MTU,
+ BTIF_GATTC_SCAN_FILTER_ENABLE,
+ BTIF_GATTC_SCAN_FILTER_CONFIG,
+ BTIF_GATTC_SCAN_FILTER_CLEAR,
+ BTIF_GATTC_SET_SCAN_PARAMS,
+ BTIF_GATTC_ADV_INSTANCE_ENABLE,
+ BTIF_GATTC_ADV_INSTANCE_UPDATE,
+ BTIF_GATTC_ADV_INSTANCE_SET_DATA,
+ BTIF_GATTC_ADV_INSTANCE_DISABLE
} btif_gattc_event_t;
#define BTIF_GATT_MAX_OBSERVED_DEV 40
#define BTIF_GATT_OBSERVE_EVT 0x1000
#define BTIF_GATTC_RSSI_EVT 0x1001
+#define BTIF_GATTC_SCAN_FILTER_EVT 0x1003
/*******************************************************************************
** Local type definitions
@@ -105,22 +115,20 @@
typedef struct
{
- tBTA_BLE_AD_MASK mask;
- tBTA_BLE_ADV_DATA data;
-} btgatt_adv_data;
-
-typedef struct
-{
uint8_t value[BTGATT_MAX_ATTR_LEN];
- btgatt_adv_data adv_data;
+ uint8_t inst_id;
bt_bdaddr_t bd_addr;
btgatt_srvc_id_t srvc_id;
btgatt_srvc_id_t incl_srvc_id;
btgatt_gatt_id_t char_id;
btgatt_gatt_id_t descr_id;
bt_uuid_t uuid;
+ bt_uuid_t uuid_mask;
uint16_t conn_id;
uint16_t len;
+ uint16_t mask;
+ uint16_t scan_interval;
+ uint16_t scan_window;
uint8_t client_if;
uint8_t action;
uint8_t is_direct;
@@ -130,8 +138,11 @@
uint8_t status;
uint8_t addr_type;
uint8_t start;
+ uint8_t has_mask;
int8_t rssi;
+ uint8_t flag;
tBT_DEVICE_TYPE device_type;
+ btgatt_transport_t transport;
} __attribute__((packed)) btif_gattc_cb_t;
typedef struct
@@ -143,8 +154,8 @@
typedef struct
{
btif_gattc_dev_t remote_dev[BTIF_GATT_MAX_OBSERVED_DEV];
- uint8_t addr_type;
- uint8_t next_storage_idx;
+ uint8_t addr_type;
+ uint8_t next_storage_idx;
}__attribute__((packed)) btif_gattc_dev_cb_t;
/*******************************************************************************
@@ -243,7 +254,6 @@
{
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;
@@ -472,6 +482,8 @@
btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
uint8_t remote_name_len;
uint8_t *p_eir_remote_name=NULL;
+ bt_device_type_t dev_type;
+ bt_property_t properties;
p_eir_remote_name = BTA_CheckEirData(p_btif_cb->value,
BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
@@ -496,6 +508,19 @@
}
}
+
+ if (( p_btif_cb->device_type == BT_DEVICE_TYPE_DUMO)&&
+ (p_btif_cb->flag & BTA_BLE_DMT_CONTROLLER_SPT) &&
+ (p_btif_cb->flag & BTA_BLE_DMT_HOST_SPT))
+ {
+ btif_storage_set_dmt_support_type (&(p_btif_cb->bd_addr), TRUE);
+ }
+
+ dev_type = p_btif_cb->device_type;
+ BTIF_STORAGE_FILL_PROPERTY(&properties,
+ BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type);
+ btif_storage_set_remote_device_property(&(p_btif_cb->bd_addr), &properties);
+
HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb,
&p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value);
break;
@@ -524,6 +549,64 @@
, p_data->cfg_mtu.status , p_data->cfg_mtu.mtu);
break;
}
+ case BTIF_GATTC_SCAN_FILTER_EVT:
+ {
+ btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+ HAL_CBACK(bt_gatt_callbacks, client->scan_filter_cb, p_btif_cb->action,
+ p_btif_cb->status);
+ break;
+ }
+
+ case BTA_GATTC_MULT_ADV_ENB_EVT:
+ {
+ btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+ btif_multi_adv_add_instid_map(p_btif_cb->client_if,
+ p_btif_cb->inst_id,false);
+ HAL_CBACK(bt_gatt_callbacks, client->multi_adv_enable_cb
+ , p_btif_cb->client_if
+ , p_btif_cb->status
+ );
+ break;
+ }
+
+ case BTA_GATTC_MULT_ADV_UPD_EVT:
+ {
+ btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+ HAL_CBACK(bt_gatt_callbacks, client->multi_adv_update_cb
+ , p_btif_cb->client_if
+ , p_btif_cb->status
+ );
+ break;
+ }
+
+ case BTA_GATTC_MULT_ADV_DATA_EVT:
+ {
+ btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+ btif_gattc_cleanup_inst_cb(p_btif_cb->inst_id);
+ HAL_CBACK(bt_gatt_callbacks, client->multi_adv_data_cb
+ , p_btif_cb->client_if
+ , p_btif_cb->status
+ );
+ break;
+ }
+
+ case BTA_GATTC_MULT_ADV_DIS_EVT:
+ {
+ btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+ btif_gattc_clear_clientif(p_btif_cb->client_if);
+ HAL_CBACK(bt_gatt_callbacks, client->multi_adv_disable_cb
+ , p_btif_cb->client_if
+ , p_btif_cb->status
+ );
+ break;
+ }
+
+ case BTA_GATTC_ADV_DATA_EVT:
+ {
+ btif_gattc_cleanup_inst_cb(STD_ADV_INSTID);
+ /* No HAL callback available */
+ break;
+ }
default:
ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
@@ -540,6 +623,66 @@
ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
}
+static void bta_gattc_multi_adv_cback(tBTA_BLE_MULTI_ADV_EVT event, UINT8 inst_id,
+ void *p_ref, tBTA_STATUS call_status)
+{
+ btif_gattc_cb_t btif_cb;
+ tBTA_GATTC_EVT upevt;
+ uint8_t client_if = 0;
+
+ if(NULL == p_ref)
+ {
+ BTIF_TRACE_ERROR1("%s Invalid p_ref received",__FUNCTION__);
+ return;
+ }
+
+ client_if = *(UINT8 *)p_ref;
+ BTIF_TRACE_DEBUG4("%s -Inst ID %d, Status:%x, client_if:%d",__FUNCTION__,inst_id, call_status,
+ client_if);
+
+ btif_cb.status = call_status;
+ btif_cb.client_if = client_if;
+ btif_cb.inst_id = inst_id;
+
+ switch(event)
+ {
+ case BTA_BLE_MULTI_ADV_ENB_EVT:
+ {
+ upevt = BTA_GATTC_MULT_ADV_ENB_EVT;
+ break;
+ }
+
+ case BTA_BLE_MULTI_ADV_DISABLE_EVT:
+ upevt = BTA_GATTC_MULT_ADV_DIS_EVT;
+ break;
+
+ case BTA_BLE_MULTI_ADV_PARAM_EVT:
+ upevt = BTA_GATTC_MULT_ADV_UPD_EVT;
+ break;
+
+ case BTA_BLE_MULTI_ADV_DATA_EVT:
+ upevt = BTA_GATTC_MULT_ADV_DATA_EVT;
+ break;
+
+ default:
+ return;
+ }
+
+ bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt, (uint16_t) upevt,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+ ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
+}
+
+static void bta_gattc_set_adv_data_cback(tBTA_STATUS call_status)
+{
+ UNUSED(call_status);
+ btif_gattc_cb_t btif_cb;
+ btif_cb.status = call_status;
+ btif_cb.action = 0;
+ btif_transfer_context(btif_gattc_upstreams_evt, BTA_GATTC_ADV_DATA_EVT,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
static void bta_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
{
btif_gattc_cb_t btif_cb;
@@ -553,6 +696,7 @@
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;
+ btif_cb.flag = p_data->inq_res.flag;
if (p_data->inq_res.p_eir)
{
memcpy(btif_cb.value, p_data->inq_res.p_eir, 62);
@@ -592,6 +736,15 @@
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}
+static void bta_scan_filter_cmpl_cb(tBTA_DM_BLE_PF_EVT event,
+ tBTA_DM_BLE_PF_COND_TYPE cfg_cond, tBTA_STATUS status)
+{
+ btif_gattc_cb_t btif_cb;
+ btif_cb.status = status;
+ btif_cb.action = event;
+ btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATTC_SCAN_FILTER_EVT,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
static void btgattc_handle_event(uint16_t event, char* p_param)
{
@@ -607,8 +760,24 @@
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;
+ btif_gattc_cb_t* p_cb = NULL;
+ btif_adv_data_t *p_adv_data = NULL;
+ btgatt_multi_adv_inst_cb *p_inst_cb = NULL;
+
+ if(BTIF_GATTC_ADV_INSTANCE_ENABLE == event || BTIF_GATTC_ADV_INSTANCE_DISABLE == event ||
+ BTIF_GATTC_ADV_INSTANCE_UPDATE == event)
+ {
+ p_inst_cb = (btgatt_multi_adv_inst_cb*)p_param;
+ }
+ else
+ {
+ if(BTIF_GATTC_ADV_INSTANCE_SET_DATA == event || BTIF_GATTC_SET_ADV_DATA == event)
+ p_adv_data = (btif_adv_data_t*)p_param;
+ else
+ p_cb = (btif_gattc_cb_t*)p_param;
+ }
+
+ if (!p_cb && !p_adv_data && !p_inst_cb) return;
ALOGD("%s: Event %d", __FUNCTION__, event);
@@ -616,10 +785,12 @@
{
case BTIF_GATTC_REGISTER_APP:
btif_to_bta_uuid(&uuid, &p_cb->uuid);
+ btif_gattc_init_multi_adv_cb();
BTA_GATTC_AppRegister(&uuid, bta_gattc_cback);
break;
case BTIF_GATTC_UNREGISTER_APP:
+ btif_gattc_destroy_multi_adv_cb();
BTA_GATTC_AppDeregister(p_cb->client_if);
break;
@@ -637,6 +808,7 @@
// Ensure device is in inquiry database
int addr_type = 0;
int device_type = 0;
+ tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
if (btif_get_device_type(p_cb->bd_addr.address, &addr_type, &device_type) == TRUE
&& device_type != BT_DEVICE_TYPE_BREDR)
@@ -646,8 +818,29 @@
if (!p_cb->is_direct)
BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
+ switch(device_type)
+ {
+ case BT_DEVICE_TYPE_BREDR:
+ transport = BTA_GATT_TRANSPORT_BR_EDR;
+ break;
+
+ case BT_DEVICE_TYPE_BLE:
+ transport = BTA_GATT_TRANSPORT_LE;
+ break;
+
+ case BT_DEVICE_TYPE_DUMO:
+ if ((p_cb->transport == GATT_TRANSPORT_LE) &&
+ (btif_storage_is_dmt_supported_device(&(p_cb->bd_addr)) == TRUE))
+ transport = BTA_GATT_TRANSPORT_LE;
+ else
+ transport = BTA_GATT_TRANSPORT_BR_EDR;
+ break;
+ }
+
// Connect!
- BTA_GATTC_Open(p_cb->client_if, p_cb->bd_addr.address, p_cb->is_direct);
+ BTIF_TRACE_DEBUG2 ("BTA_GATTC_Open Transport = %d, dev type = %d",
+ transport, device_type);
+ BTA_GATTC_Open(p_cb->client_if, p_cb->bd_addr.address, p_cb->is_direct, transport);
break;
}
@@ -854,6 +1047,99 @@
BTM_ReadRSSI (p_cb->bd_addr.address, (tBTM_CMPL_CB *)btm_read_rssi_cb);
break;
+ case BTIF_GATTC_SCAN_FILTER_ENABLE:
+ BTA_DmBleEnableFilterCondition(p_cb->action, NULL, bta_scan_filter_cmpl_cb);
+ break;
+
+ case BTIF_GATTC_SCAN_FILTER_CONFIG:
+ {
+ tBTA_DM_BLE_PF_COND_PARAM cond;
+ memset(&cond, 0, sizeof(cond));
+
+ switch (p_cb->action)
+ {
+ case BTA_DM_BLE_PF_ADDR_FILTER: // 0
+ bdcpy(cond.target_addr.bda, p_cb->bd_addr.address);
+ cond.target_addr.type = p_cb->addr_type;
+ BTA_DmBleCfgFilterCondition(BTA_DM_BLE_SCAN_COND_ADD,
+ p_cb->action, &cond,
+ bta_scan_filter_cmpl_cb);
+ break;
+
+ case BTA_DM_BLE_PF_SRVC_DATA: // 1
+ BTA_DmBleCfgFilterCondition(BTA_DM_BLE_SCAN_COND_ADD,
+ p_cb->action, NULL,
+ bta_scan_filter_cmpl_cb);
+ break;
+
+ case BTA_DM_BLE_PF_SRVC_UUID: // 2
+ {
+ tBTA_DM_BLE_PF_COND_MASK uuid_mask;
+
+ cond.srvc_uuid.p_target_addr = NULL;
+ cond.srvc_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND;
+ btif_to_bta_uuid(&cond.srvc_uuid.uuid, &p_cb->uuid);
+
+ cond.srvc_uuid.p_uuid_mask = NULL;
+ if (p_cb->has_mask)
+ {
+ btif_to_bta_uuid_mask(&uuid_mask, &p_cb->uuid_mask);
+ cond.srvc_uuid.p_uuid_mask = &uuid_mask;
+ }
+ BTA_DmBleCfgFilterCondition(BTA_DM_BLE_SCAN_COND_ADD,
+ p_cb->action, &cond,
+ bta_scan_filter_cmpl_cb);
+ break;
+ }
+
+ case BTA_DM_BLE_PF_SRVC_SOL_UUID: // 3
+ {
+ cond.solicitate_uuid.p_target_addr = NULL;
+ cond.solicitate_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND;
+ btif_to_bta_uuid(&cond.solicitate_uuid.uuid, &p_cb->uuid);
+ BTA_DmBleCfgFilterCondition(BTA_DM_BLE_SCAN_COND_ADD,
+ p_cb->action, &cond,
+ bta_scan_filter_cmpl_cb);
+ break;
+ }
+
+ case BTA_DM_BLE_PF_LOCAL_NAME: // 4
+ {
+ cond.local_name.data_len = p_cb->len;
+ cond.local_name.p_data = p_cb->value;
+ BTA_DmBleCfgFilterCondition(BTA_DM_BLE_SCAN_COND_ADD,
+ p_cb->action, &cond,
+ bta_scan_filter_cmpl_cb);
+ break;
+ }
+
+ case BTA_DM_BLE_PF_MANU_DATA: // 5
+ {
+ cond.manu_data.company_id = p_cb->conn_id;
+ cond.manu_data.company_id_mask = p_cb->mask;
+ cond.manu_data.data_len = p_cb->len;
+ cond.manu_data.p_pattern = p_cb->value;
+ cond.manu_data.p_pattern_mask = &p_cb->value[p_cb->len];
+ BTA_DmBleCfgFilterCondition(BTA_DM_BLE_SCAN_COND_ADD,
+ p_cb->action, &cond,
+ bta_scan_filter_cmpl_cb);
+ break;
+ }
+
+ default:
+ ALOGE("%s: Unknown filter type (%d)!", __FUNCTION__, p_cb->action);
+ break;
+ }
+ break;
+ }
+
+ case BTIF_GATTC_SCAN_FILTER_CLEAR:
+ {
+ BTA_DmBleCfgFilterCondition(BTA_DM_BLE_SCAN_COND_CLEAR, BTA_DM_BLE_PF_TYPE_ALL,
+ NULL, bta_scan_filter_cmpl_cb);
+ break;
+ }
+
case BTIF_GATTC_LISTEN:
#if (defined(BLE_PERIPHERAL_MODE_SUPPORT) && (BLE_PERIPHERAL_MODE_SUPPORT == TRUE))
BTA_GATTC_Listen(p_cb->client_if, p_cb->start, NULL);
@@ -864,43 +1150,114 @@
case BTIF_GATTC_SET_ADV_DATA:
{
- if (p_cb->start == 0)
- BTA_DmBleSetAdvConfig(p_cb->adv_data.mask, &p_cb->adv_data.data);
- else
- BTA_DmBleSetScanRsp(p_cb->adv_data.mask, &p_cb->adv_data.data);
-
- // Cleanup ...
-
- // ... manufacturer data
- if (p_cb->adv_data.data.manu.p_val != NULL)
- GKI_freebuf(p_cb->adv_data.data.manu.p_val);
-
- // ... service data
- if (p_cb->adv_data.data.p_proprietary != NULL)
+ int cbindex = CLNT_IF_IDX;
+ if(cbindex >= 0 && NULL != p_adv_data)
{
- int i = 0;
- tBTA_BLE_PROP_ELEM *p_elem = p_cb->adv_data.data.p_proprietary->p_elem;
- while (i++ != p_cb->adv_data.data.p_proprietary->num_elem && p_elem)
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+ if(!btif_gattc_copy_datacb(cbindex, p_adv_data, false))
+ return;
+
+ if (!p_adv_data->set_scan_rsp)
{
- if (p_elem->p_val != NULL)
- GKI_freebuf(p_elem->p_val);
- ++p_elem;
+ BTA_DmBleSetAdvConfig(p_multi_adv_data_cb->inst_cb[cbindex].mask,
+ &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback);
}
- if (p_cb->adv_data.data.p_proprietary->p_elem != NULL)
- GKI_freebuf(p_cb->adv_data.data.p_proprietary->p_elem);
- GKI_freebuf(p_cb->adv_data.data.p_proprietary);
+ else
+ {
+ BTA_DmBleSetScanRsp(p_multi_adv_data_cb->inst_cb[cbindex].mask,
+ &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback);
+ }
+ break;
}
+ }
- // ... service list
- if (p_cb->adv_data.data.services.p_uuid != NULL)
- GKI_freebuf(p_cb->adv_data.data.services.p_uuid);
+ case BTIF_GATTC_ADV_INSTANCE_ENABLE:
+ {
+ if(NULL == p_inst_cb)
+ return;
+ int arrindex = btif_multi_adv_add_instid_map(p_inst_cb->client_if,INVALID_ADV_INST,
+ true);
+ int cbindex = btif_gattc_obtain_idx_for_datacb(p_inst_cb->client_if, CLNT_IF_IDX);
+ if(cbindex >= 0 && arrindex >= 0)
+ {
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+ memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].param,
+ &p_inst_cb->param, sizeof(tBTA_BLE_ADV_PARAMS));
+
+ BTA_BleEnableAdvInstance(&(p_multi_adv_data_cb->inst_cb[cbindex].param),
+ bta_gattc_multi_adv_cback,
+ &(p_multi_adv_data_cb->clntif_map[arrindex][CLNT_IF_IDX]));
+ }
+ else
+ BTIF_TRACE_ERROR1("%s invalid index in BTIF_GATTC_ENABLE_ADV",__FUNCTION__);
break;
}
+
+ case BTIF_GATTC_ADV_INSTANCE_UPDATE:
+ {
+ if(NULL == p_inst_cb)
+ return;
+
+ int inst_id = btif_multi_adv_instid_for_clientif(p_inst_cb->client_if);
+ int cbindex = btif_gattc_obtain_idx_for_datacb(p_inst_cb->client_if, CLNT_IF_IDX);
+ if(inst_id >= 0 && cbindex >= 0 && NULL != p_inst_cb)
+ {
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+ memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].param, &p_inst_cb->param,
+ sizeof(tBTA_BLE_ADV_PARAMS));
+ BTA_BleUpdateAdvInstParam((UINT8)inst_id,
+ &(p_multi_adv_data_cb->inst_cb[cbindex].param));
+ }
+ else
+ BTIF_TRACE_ERROR1("%s invalid index in BTIF_GATTC_UPDATE_ADV", __FUNCTION__);
+ break;
+ }
+
+ case BTIF_GATTC_ADV_INSTANCE_SET_DATA:
+ {
+ if(NULL == p_adv_data)
+ return;
+
+ int cbindex = btif_gattc_obtain_idx_for_datacb(p_adv_data->client_if, CLNT_IF_IDX);
+ int inst_id = btif_multi_adv_instid_for_clientif(p_adv_data->client_if);
+ if(inst_id < 0 || cbindex < 0)
+ {
+ BTIF_TRACE_ERROR1("%s invalid index in BTIF_GATTC_SETADV_INST_DATA", __FUNCTION__);
+ return;
+ }
+
+ if(!btif_gattc_copy_datacb(cbindex, p_adv_data, true))
+ return;
+
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+ BTA_BleCfgAdvInstData((UINT8)inst_id, p_multi_adv_data_cb->inst_cb[cbindex].is_scan_rsp,
+ p_multi_adv_data_cb->inst_cb[cbindex].mask,
+ &p_multi_adv_data_cb->inst_cb[cbindex].data);
+ break;
+ }
+
+ case BTIF_GATTC_ADV_INSTANCE_DISABLE:
+ {
+ if(NULL == p_inst_cb)
+ return;
+
+ int inst_id = btif_multi_adv_instid_for_clientif(p_inst_cb->client_if);
+ if(inst_id >=0)
+ BTA_BleDisableAdvInstance((UINT8)inst_id);
+ else
+ BTIF_TRACE_ERROR1("%s invalid instance ID in BTIF_GATTC_DISABLE_ADV",__FUNCTION__);
+ break;
+ }
+
case BTIF_GATTC_CONFIGURE_MTU:
BTA_GATTC_ConfigureMTU(p_cb->conn_id, p_cb->len);
break;
+ case BTIF_GATTC_SET_SCAN_PARAMS:
+ BTM_BleSetScanParams(p_cb->scan_interval, p_cb->scan_window, BTM_BLE_SCAN_MODE_ACTI);
+ break;
+
default:
ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
break;
@@ -929,21 +1286,22 @@
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}
-static bt_status_t btif_gattc_scan( int client_if, bool start )
+static bt_status_t btif_gattc_scan( 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 )
+static bt_status_t btif_gattc_open(int client_if, const bt_bdaddr_t *bd_addr,
+ bool is_direct,int transport)
{
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;
+ btif_cb.transport = (btgatt_transport_t)transport;
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);
@@ -977,161 +1335,28 @@
uint16_t service_uuid_len, char* service_uuid)
{
CHECK_BTGATT_INIT();
- btif_gattc_cb_t btif_cb;
- memset(&btif_cb, 0, sizeof(btif_gattc_cb_t));
- memset(&btif_cb.adv_data, 0, sizeof(btgatt_adv_data));
+ bt_status_t status =0;
- btif_cb.client_if = (uint8_t) client_if;
- btif_cb.start = set_scan_rsp ? 1 : 0;
+ btif_adv_data_t adv_data;
- if (!set_scan_rsp)
- {
- btif_cb.adv_data.mask = BTM_BLE_AD_BIT_FLAGS;
- btif_cb.adv_data.data.flag = ADV_FLAGS;
- }
+ btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name,
+ include_txpower, min_interval, max_interval, appearance, manufacturer_len,
+ manufacturer_data, service_data_len, service_data, service_uuid_len, service_uuid,
+ &adv_data);
- if (include_name)
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_DEV_NAME;
+ status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
+ (char*) &adv_data, sizeof(btif_adv_data_t), NULL);
- if (include_txpower)
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_TX_PWR;
+ if (NULL != adv_data.p_service_data)
+ GKI_freebuf(adv_data.p_service_data);
- if (min_interval > 0 && max_interval > 0 && max_interval > min_interval)
- {
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_INT_RANGE;
- btif_cb.adv_data.data.int_range.low = min_interval;
- btif_cb.adv_data.data.int_range.hi = max_interval;
- }
+ if (NULL != adv_data.p_service_uuid)
+ GKI_freebuf(adv_data.p_service_uuid);
- if (appearance != 0)
- {
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_APPEARANCE;
- btif_cb.adv_data.data.appearance = appearance;
- }
+ if (NULL != adv_data.p_manufacturer_data)
+ GKI_freebuf(adv_data.p_manufacturer_data);
- if (manufacturer_len > 0 && manufacturer_data != NULL)
- {
- btif_cb.adv_data.data.manu.p_val = GKI_getbuf(manufacturer_len);
- if (btif_cb.adv_data.data.manu.p_val != NULL)
- {
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_MANU;
- btif_cb.adv_data.data.manu.len = manufacturer_len;
- memcpy(btif_cb.adv_data.data.manu.p_val, manufacturer_data, manufacturer_len);
- }
- }
-
- tBTA_BLE_PROP_ELEM *p_elem_service_data = NULL;
- tBTA_BLE_PROP_ELEM *p_elem_service_128 = NULL;
-
- if (service_data_len > 0 && service_data != NULL)
- {
- p_elem_service_data = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
- if (p_elem_service_data != NULL)
- {
- p_elem_service_data->p_val = GKI_getbuf(service_data_len);
- if (p_elem_service_data->p_val != NULL)
- {
- p_elem_service_data->adv_type = BTM_BLE_AD_TYPE_SERVICE_DATA;
- p_elem_service_data->len = service_data_len;
- memcpy(p_elem_service_data->p_val, service_data, service_data_len);
-
- } else {
- GKI_freebuf(p_elem_service_data);
- p_elem_service_data = NULL;
- }
- }
- }
-
- if (service_uuid_len > 0 && service_uuid != NULL)
- {
- btif_cb.adv_data.data.services.list_cmpl = FALSE;
- btif_cb.adv_data.data.services.num_service = 0;
-
- btif_cb.adv_data.data.services.p_uuid =
- GKI_getbuf(service_uuid_len / LEN_UUID_128 * LEN_UUID_16);
- if (btif_cb.adv_data.data.services.p_uuid != NULL)
- {
- UINT16 *p_uuid_out = btif_cb.adv_data.data.services.p_uuid;
- while (service_uuid_len >= LEN_UUID_128)
- {
- bt_uuid_t uuid;
- memset(&uuid, 0, sizeof(bt_uuid_t));
- memcpy(&uuid.uu, service_uuid, LEN_UUID_128);
-
- tBT_UUID bt_uuid;
- memset(&bt_uuid, 0, sizeof(tBT_UUID));
- btif_to_bta_uuid(&bt_uuid, &uuid);
-
- if (bt_uuid.len == LEN_UUID_16)
- {
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_SERVICE;
- ++btif_cb.adv_data.data.services.num_service;
- *p_uuid_out++ = bt_uuid.uu.uuid16;
-
- } else if (bt_uuid.len == LEN_UUID_128 && p_elem_service_128 == NULL) {
- /* Currently, only one 128-bit UUID is supported */
- p_elem_service_128 = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
- if (p_elem_service_128 != NULL)
- {
- p_elem_service_128->p_val = GKI_getbuf(LEN_UUID_128);
- if (p_elem_service_128->p_val != NULL)
- {
- p_elem_service_128->adv_type = BTM_BLE_AD_TYPE_128SRV_PART;
- p_elem_service_128->len = LEN_UUID_128;
- memcpy(p_elem_service_128->p_val, bt_uuid.uu.uuid128, LEN_UUID_128);
-
- } else {
- GKI_freebuf(p_elem_service_128);
- p_elem_service_128 = NULL;
- }
- }
- }
-
- service_uuid += LEN_UUID_128;
- service_uuid_len -= LEN_UUID_128;
- }
- }
- }
-
- if (p_elem_service_data != NULL || p_elem_service_128 != NULL)
- {
- btif_cb.adv_data.data.p_proprietary = GKI_getbuf(sizeof(tBTA_BLE_PROPRIETARY));
- if (btif_cb.adv_data.data.p_proprietary != NULL)
- {
- tBTA_BLE_PROPRIETARY *p_prop = btif_cb.adv_data.data.p_proprietary;
- tBTA_BLE_PROP_ELEM *p_elem = NULL;
- p_prop->num_elem = 0;
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_PROPRIETARY;
-
- if (p_elem_service_128 != NULL)
- ++p_prop->num_elem;
-
- if (p_elem_service_data != NULL)
- ++p_prop->num_elem;
-
- p_prop->p_elem = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM) * p_prop->num_elem);
- p_elem = p_prop->p_elem;
-
- if (p_elem_service_128 != NULL)
- {
- memcpy(p_elem++, p_elem_service_128, sizeof(tBTA_BLE_PROP_ELEM));
- GKI_freebuf(p_elem_service_128);
- }
-
- if (p_elem_service_data != NULL)
- {
- memcpy(p_elem++, p_elem_service_data, sizeof(tBTA_BLE_PROP_ELEM));
- GKI_freebuf(p_elem_service_data);
- }
- }
- }
-
-#if (defined(BLE_PERIPHERAL_ADV_NAME) && (BLE_PERIPHERAL_ADV_NAME == TRUE))
- btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_DEV_NAME;
-#endif
-
- return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
- (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+ return status;
}
static bt_status_t btif_gattc_refresh( int client_if, const bt_bdaddr_t *bd_addr )
@@ -1334,6 +1559,62 @@
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}
+static bt_status_t btif_gattc_scan_filter_enable(int enable )
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.action = enable;
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SCAN_FILTER_ENABLE,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_scan_filter_add(int type, int company_id, int company_mask,
+ int len, const bt_uuid_t *p_uuid, const bt_uuid_t *p_uuid_mask,
+ const bt_bdaddr_t *bd_addr, char addr_type, const char* p_value)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+
+ if (len > (BTGATT_MAX_ATTR_LEN / 2))
+ len = BTGATT_MAX_ATTR_LEN / 2;
+
+ btif_cb.action = type;
+ btif_cb.len = len;
+ btif_cb.conn_id = company_id;
+ btif_cb.mask = company_mask ? company_mask : 0xFFFF;
+ if(bd_addr)
+ bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+ btif_cb.addr_type = addr_type;
+ btif_cb.has_mask = (p_uuid_mask != NULL);
+
+ if (p_uuid != NULL)
+ memcpy(&btif_cb.uuid, p_uuid, sizeof(bt_uuid_t));
+ if (p_uuid_mask != NULL)
+ memcpy(&btif_cb.uuid_mask, p_uuid_mask, sizeof(bt_uuid_t));
+ if (p_value != NULL && len != 0)
+ memcpy(btif_cb.value, p_value, len * 2 /* PATTERN CONTAINS MASK */);
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SCAN_FILTER_CONFIG,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_scan_filter_clear()
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SCAN_FILTER_CLEAR,
+ (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_set_scan_parameters(int scan_interval, int scan_window)
+{
+ CHECK_BTGATT_INIT();
+ btif_gattc_cb_t btif_cb;
+ btif_cb.scan_interval = scan_interval;
+ btif_cb.scan_window = scan_window;
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_SCAN_PARAMS,
+ (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;
@@ -1345,6 +1626,84 @@
return 0;
}
+static bt_status_t btif_gattc_multi_adv_enable(int client_if, int min_interval, int max_interval,
+ int adv_type, int chnl_map, int tx_power)
+{
+ CHECK_BTGATT_INIT();
+ btgatt_multi_adv_inst_cb adv_cb;
+ adv_cb.client_if = (uint8_t) client_if;
+
+ adv_cb.param.adv_int_min = min_interval;
+ adv_cb.param.adv_int_max = max_interval;
+ adv_cb.param.adv_type = adv_type;
+ adv_cb.param.channel_map = chnl_map;
+ adv_cb.param.adv_filter_policy = 0;
+ adv_cb.param.tx_power = tx_power;
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_ENABLE,
+ (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
+}
+
+static bt_status_t btif_gattc_multi_adv_update(int client_if, int min_interval, int max_interval,
+ int adv_type, int chnl_map,int tx_power)
+{
+ CHECK_BTGATT_INIT();
+ btgatt_multi_adv_inst_cb adv_cb;
+ adv_cb.client_if = (uint8_t) client_if;
+
+ adv_cb.param.adv_int_min = min_interval;
+ adv_cb.param.adv_int_max = max_interval;
+ adv_cb.param.adv_type = adv_type;
+ adv_cb.param.channel_map = chnl_map;
+ adv_cb.param.adv_filter_policy = 0;
+ adv_cb.param.tx_power = tx_power;
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_UPDATE,
+ (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
+}
+
+static bt_status_t btif_gattc_multi_adv_setdata(int client_if, bool set_scan_rsp,
+ bool include_name, bool incl_txpower,
+ int appearance, uint16_t manufacturer_len,
+ char* manufacturer_data,
+ uint16_t service_data_len,
+ char* service_data, uint16_t service_uuid_len,
+ char* service_uuid)
+{
+ CHECK_BTGATT_INIT();
+
+ int min_interval = 0, max_interval = 0;
+ bt_status_t status =0;
+
+ btif_adv_data_t multi_adv_data_inst;
+
+ btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name, incl_txpower,
+ min_interval, max_interval, appearance, manufacturer_len, manufacturer_data,
+ service_data_len, service_data, service_uuid_len, service_uuid, &multi_adv_data_inst);
+
+ status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_SET_DATA,
+ (char*) &multi_adv_data_inst, sizeof(btif_adv_data_t), NULL);
+
+ if (NULL != multi_adv_data_inst.p_service_data)
+ GKI_freebuf(multi_adv_data_inst.p_service_data);
+
+ if (NULL != multi_adv_data_inst.p_service_uuid)
+ GKI_freebuf(multi_adv_data_inst.p_service_uuid);
+
+ if (NULL != multi_adv_data_inst.p_manufacturer_data)
+ GKI_freebuf(multi_adv_data_inst.p_manufacturer_data);
+
+ return status;
+}
+
+static bt_status_t btif_gattc_multi_adv_disable(int client_if)
+{
+ CHECK_BTGATT_INIT();
+ btgatt_multi_adv_inst_cb adv_cb;
+ adv_cb.client_if = (uint8_t) client_if;
+
+ return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_DISABLE,
+ (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
+}
+
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)
@@ -1373,9 +1732,17 @@
btif_gattc_reg_for_notification,
btif_gattc_dereg_for_notification,
btif_gattc_read_remote_rssi,
+ btif_gattc_scan_filter_enable,
+ btif_gattc_scan_filter_add,
+ btif_gattc_scan_filter_clear,
btif_gattc_get_device_type,
btif_gattc_set_adv_data,
btif_gattc_configure_mtu,
+ btif_gattc_set_scan_parameters,
+ btif_gattc_multi_adv_enable,
+ btif_gattc_multi_adv_update,
+ btif_gattc_multi_adv_setdata,
+ btif_gattc_multi_adv_disable,
btif_gattc_test_command
};
diff --git a/btif/src/btif_gatt_multi_adv_util.c b/btif/src/btif_gatt_multi_adv_util.c
new file mode 100644
index 0000000..58d067f
--- /dev/null
+++ b/btif/src/btif_gatt_multi_adv_util.c
@@ -0,0 +1,541 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 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_multi_adv_util.c
+ *
+ * Description: Multi ADV helper implementation
+ *
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "bt_target.h"
+
+#define LOG_TAG "BtGatt.btif"
+#if (BLE_INCLUDED == TRUE)
+
+#include "btif_gatt_multi_adv_util.h"
+#include "btif_common.h"
+#include <hardware/bt_gatt.h>
+#include "bta_gatt_api.h"
+#include "btif_gatt_util.h"
+
+/*******************************************************************************
+** Static variables
+********************************************************************************/
+static int multi_adv_enable_count = 0;
+static btgatt_multi_adv_common_data *p_multi_adv_com_data_cb = NULL;
+
+btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb()
+{
+ if(p_multi_adv_com_data_cb == NULL)
+ p_multi_adv_com_data_cb = GKI_getbuf(sizeof(btgatt_multi_adv_common_data));
+ return p_multi_adv_com_data_cb;
+}
+
+void btif_gattc_init_multi_adv_cb(void)
+{
+ int i;
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+ if(NULL == p_multi_adv_data_cb)
+ return;
+
+ if(multi_adv_enable_count == 0)
+ {
+ memset(p_multi_adv_data_cb,0,sizeof(btgatt_multi_adv_common_data));
+
+ for (i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+ {
+ p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX] = INVALID_ADV_INST;
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = INVALID_ADV_INST;
+ }
+ }
+ multi_adv_enable_count++;
+}
+
+void btif_gattc_destroy_multi_adv_cb()
+{
+ if(multi_adv_enable_count > 0)
+ multi_adv_enable_count --;
+ if(multi_adv_enable_count == 0)
+ {
+ GKI_freebuf(p_multi_adv_com_data_cb);
+ p_multi_adv_com_data_cb = NULL;
+ }
+}
+
+int btif_multi_adv_add_instid_map(int client_if, int inst_id, BOOLEAN gen_temp_instid)
+{
+ int i=0;
+
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+ if(NULL == p_multi_adv_data_cb)
+ return INVALID_ADV_INST;
+
+ for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+ {
+ if(client_if == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+ {
+ if(!gen_temp_instid)
+ {
+ // Write the final inst_id value obtained from stack layer
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = inst_id;
+ BTIF_TRACE_DEBUG3("%s -Index: %d, Found client_if: %d", __FUNCTION__,
+ i, p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX]);
+ break;
+ }
+ else
+ {
+ //Store the passed in inst_id value
+ if(inst_id != INVALID_ADV_INST)
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = inst_id;
+ else
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = (i + 1);
+ BTIF_TRACE_DEBUG3("%s - Index:%d,Found client_if: %d", __FUNCTION__,
+ i, p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX]);
+ break;
+ }
+ }
+ }
+
+ if(i < BTM_BLE_MULTI_ADV_MAX)
+ return i;
+
+ // If client ID if is not found, then write both values
+ for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+ {
+ if(INVALID_ADV_INST == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+ {
+ p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX] = client_if;
+ if(inst_id != INVALID_ADV_INST)
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = inst_id;
+ else
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = (i + 1);
+ BTIF_TRACE_DEBUG4("%s -Not found - Index:%d, client_if: %d, Inst ID: %d",
+ __FUNCTION__,i,
+ p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX],
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX]);
+ break;
+ }
+ }
+
+ if(i < BTM_BLE_MULTI_ADV_MAX)
+ return i;
+ return INVALID_ADV_INST;
+}
+
+int btif_multi_adv_instid_for_clientif(int client_if)
+{
+ int i=0, ret = INVALID_ADV_INST;
+
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+ if(NULL == p_multi_adv_data_cb)
+ return INVALID_ADV_INST;
+
+ // Retrieve the existing inst_id for the client_if value
+ for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+ {
+ if(client_if == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+ ret = p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX];
+ }
+
+ if(ret != INVALID_ADV_INST)
+ return ret;
+
+ return INVALID_ADV_INST;
+}
+
+
+int btif_gattc_obtain_idx_for_datacb(int value, int arrindex)
+{
+ int i=0;
+
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+ if(NULL == p_multi_adv_data_cb)
+ return INVALID_ADV_INST;
+
+ // Retrieve the array index for the inst_id value
+ for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+ {
+ if(value == p_multi_adv_data_cb->clntif_map[i][arrindex])
+ break;
+ }
+
+ if(i < BTM_BLE_MULTI_ADV_MAX)
+ {
+ BTIF_TRACE_DEBUG2("%s, %d",__FUNCTION__,i+1);
+ return (i + 1);
+ }
+
+ BTIF_TRACE_DEBUG1("%s Invalid instance",__FUNCTION__);
+ return INVALID_ADV_INST;
+}
+
+
+void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp,
+ bool include_name, bool include_txpower, int min_interval, int max_interval,
+ int appearance, uint16_t manufacturer_len, char* manufacturer_data,
+ uint16_t service_data_len, char* service_data, uint16_t service_uuid_len,
+ char* service_uuid, btif_adv_data_t *p_multi_adv_inst)
+{
+ memset(p_multi_adv_inst, 0 , sizeof(btif_adv_data_t));
+
+ p_multi_adv_inst->client_if = (uint8_t) client_if;
+ p_multi_adv_inst->set_scan_rsp = set_scan_rsp;
+ p_multi_adv_inst->include_name = include_name;
+ p_multi_adv_inst->include_txpower = include_txpower;
+ p_multi_adv_inst->min_interval = min_interval;
+ p_multi_adv_inst->max_interval = max_interval;
+ p_multi_adv_inst->appearance = appearance;
+ p_multi_adv_inst->manufacturer_len = manufacturer_len;
+
+ if(manufacturer_len > 0)
+ {
+ p_multi_adv_inst->p_manufacturer_data = GKI_getbuf(manufacturer_len);
+ memcpy(p_multi_adv_inst->p_manufacturer_data, manufacturer_data, manufacturer_len);
+ }
+
+ p_multi_adv_inst->service_data_len = service_data_len;
+ if(service_data_len > 0)
+ {
+ p_multi_adv_inst->p_service_data = GKI_getbuf(service_data_len);
+ memcpy(p_multi_adv_inst->p_service_data, service_data, service_data_len);
+ }
+
+ p_multi_adv_inst->service_uuid_len = service_uuid_len;
+ if(service_uuid_len > 0)
+ {
+ p_multi_adv_inst->p_service_uuid = GKI_getbuf(service_uuid_len);
+ memcpy(p_multi_adv_inst->p_service_uuid, service_uuid, service_uuid_len);
+ }
+}
+
+BOOLEAN btif_gattc_copy_datacb(int cbindex, btif_adv_data_t *p_adv_data, BOOLEAN bInstData)
+{
+ int i=0;
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+ if(NULL == p_multi_adv_data_cb || cbindex < 0)
+ return false;
+
+ BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
+ memset(&p_multi_adv_data_cb->inst_cb[cbindex],0, sizeof(btgatt_multi_adv_inst_cb));
+ memset(&p_multi_adv_data_cb->inst_cb[cbindex].data, 0, sizeof(tBTA_BLE_ADV_DATA));
+
+ if (!p_adv_data->set_scan_rsp)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].is_scan_rsp = p_adv_data->set_scan_rsp ? 1 : 0;
+ p_multi_adv_data_cb->inst_cb[cbindex].mask = BTM_BLE_AD_BIT_FLAGS;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS;
+ }
+
+ if (p_adv_data->include_name)
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_DEV_NAME;
+
+ if (p_adv_data->include_txpower)
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_TX_PWR;
+
+ if (false == bInstData && p_adv_data->min_interval > 0 && p_adv_data->max_interval > 0 &&
+ p_adv_data->max_interval > p_adv_data->min_interval)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_INT_RANGE;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low =
+ p_adv_data->min_interval;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi =
+ p_adv_data->max_interval;
+ }
+ else
+ if(true == bInstData)
+ {
+ if (p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min > 0 &&
+ p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max > 0 &&
+ p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max >
+ p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low =
+ p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi =
+ p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max;
+ }
+
+ if (p_adv_data->include_txpower)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].data.tx_power =
+ p_multi_adv_data_cb->inst_cb[cbindex].param.tx_power;
+ }
+ }
+
+ if (p_adv_data->appearance != 0)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_APPEARANCE;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.appearance = p_adv_data->appearance;
+ }
+
+ if (p_adv_data->manufacturer_len > 0 && p_adv_data->p_manufacturer_data != NULL)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu =
+ GKI_getbuf(sizeof(tBTA_BLE_MANU));
+ if(p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu != NULL)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->p_val =
+ GKI_getbuf(p_adv_data->manufacturer_len);
+ if (p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->p_val != NULL)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_MANU;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->len =
+ p_adv_data->manufacturer_len;
+ memcpy(p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->p_val,
+ p_adv_data->p_manufacturer_data, p_adv_data->manufacturer_len);
+ }
+ }
+ }
+
+ tBTA_BLE_PROP_ELEM *p_elem_service_data = NULL;
+ tBTA_BLE_PROP_ELEM *p_elem_service_128 = NULL;
+
+ if (p_adv_data->service_data_len > 0 && p_adv_data->p_service_data != NULL)
+ {
+ BTIF_TRACE_DEBUG1("%s - In service_data", __FUNCTION__);
+ p_elem_service_data = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
+ if (p_elem_service_data != NULL)
+ {
+ p_elem_service_data->p_val = GKI_getbuf(p_adv_data->service_data_len);
+ if (p_elem_service_data->p_val != NULL)
+ {
+ p_elem_service_data->adv_type = BTM_BLE_AD_TYPE_SERVICE_DATA;
+ p_elem_service_data->len = p_adv_data->service_data_len;
+ memcpy(p_elem_service_data->p_val, p_adv_data->p_service_data,
+ p_adv_data->service_data_len);
+ } else {
+ GKI_freebuf(p_elem_service_data);
+ p_elem_service_data = NULL;
+ }
+ }
+ }
+
+ if (p_adv_data->service_uuid_len > 0 && p_adv_data->p_service_uuid != NULL)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_services =
+ GKI_getbuf(sizeof(tBTA_BLE_SERVICE));
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->list_cmpl = FALSE;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->num_service = 0;
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->p_uuid =
+ GKI_getbuf(p_adv_data->service_uuid_len / LEN_UUID_128 * LEN_UUID_16);
+ if (p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->p_uuid != NULL)
+ {
+ UINT16 *p_uuid_out = p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->p_uuid;
+ while (p_adv_data->service_uuid_len >= LEN_UUID_128)
+ {
+ bt_uuid_t uuid;
+ memset(&uuid, 0, sizeof(bt_uuid_t));
+ memcpy(&uuid.uu, p_adv_data->p_service_uuid, LEN_UUID_128);
+ tBT_UUID bt_uuid;
+ memset(&bt_uuid, 0, sizeof(tBT_UUID));
+ btif_to_bta_uuid(&bt_uuid, &uuid);
+
+ if (bt_uuid.len == LEN_UUID_16)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_SERVICE;
+ ++p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->num_service;
+ *p_uuid_out++ = bt_uuid.uu.uuid16;
+ } else if (bt_uuid.len == LEN_UUID_128 && p_elem_service_128 == NULL) {
+ /* Currently, only one 128-bit UUID is supported */
+ p_elem_service_128 = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
+ if (p_elem_service_128 != NULL)
+ {
+ p_elem_service_128->p_val = GKI_getbuf(LEN_UUID_128);
+ if (p_elem_service_128->p_val != NULL)
+ {
+ p_elem_service_128->adv_type = BTM_BLE_AD_TYPE_128SRV_PART;
+ p_elem_service_128->len = LEN_UUID_128;
+ memcpy(p_elem_service_128->p_val, bt_uuid.uu.uuid128, LEN_UUID_128);
+ } else {
+ GKI_freebuf(p_elem_service_128);
+ p_elem_service_128 = NULL;
+ }
+ }
+ }
+ p_adv_data->p_service_uuid += LEN_UUID_128;
+ p_adv_data->service_uuid_len -= LEN_UUID_128;
+ }
+ }
+ }
+
+ if (p_elem_service_data != NULL || p_elem_service_128 != NULL)
+ {
+ p_multi_adv_data_cb->inst_cb[cbindex].data.p_proprietary =
+ GKI_getbuf(sizeof(tBTA_BLE_PROPRIETARY));
+ if (p_multi_adv_data_cb->inst_cb[cbindex].data.p_proprietary != NULL)
+ {
+ tBTA_BLE_PROPRIETARY *p_prop = p_multi_adv_data_cb->inst_cb[cbindex].
+ data.p_proprietary;
+ tBTA_BLE_PROP_ELEM *p_elem = NULL;
+ p_prop->num_elem = 0;
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_PROPRIETARY;
+ if (p_elem_service_128 != NULL)
+ ++p_prop->num_elem;
+ if (p_elem_service_data != NULL)
+ ++p_prop->num_elem;
+ p_prop->p_elem = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM) * p_prop->num_elem);
+ p_elem = p_prop->p_elem;
+ if (p_elem_service_128 != NULL)
+ {
+ memcpy(p_elem++, p_elem_service_128, sizeof(tBTA_BLE_PROP_ELEM));
+ GKI_freebuf(p_elem_service_128);
+ }
+ if (p_elem_service_data != NULL)
+ {
+ memcpy(p_elem++, p_elem_service_data, sizeof(tBTA_BLE_PROP_ELEM));
+ GKI_freebuf(p_elem_service_data);
+ }
+ }
+ }
+
+#if (defined(BLE_PERIPHERAL_ADV_NAME) && (BLE_PERIPHERAL_ADV_NAME == TRUE))
+ p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_DEV_NAME;
+#endif
+ return true;
+}
+
+void btif_gattc_clear_clientif(int client_if)
+{
+ int i=0;
+
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+ if(NULL == p_multi_adv_data_cb)
+ return;
+
+ // Clear both the inst_id and client_if values
+ for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+ {
+ if(client_if == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+ {
+ p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = INVALID_ADV_INST;
+ p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX] = INVALID_ADV_INST;
+ BTIF_TRACE_DEBUG2("Cleaning up index %d for clnt_if :%d,", i, client_if);
+ break;
+ }
+ }
+}
+
+void btif_gattc_cleanup_inst_cb(int inst_id)
+{
+ int cbindex = 0;
+ // Check for invalid instance id
+ if (inst_id < 0 || inst_id > BTM_BLE_MULTI_ADV_MAX)
+ return;
+
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+ if(NULL == p_multi_adv_data_cb)
+ return;
+
+ if(inst_id > 0)
+ {
+ cbindex = btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
+ if (cbindex < 0)
+ return;
+ }
+ else
+ if(STD_ADV_INSTID == inst_id)
+ cbindex = STD_ADV_INSTID;
+
+ BTIF_TRACE_DEBUG2("Cleaning up multi_inst_cb for inst_id %d, cbindex %d", inst_id, cbindex);
+ btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex]);
+}
+
+void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb)
+{
+ // Manufacturer data cleanup
+ if (p_multi_inst_cb->data.p_manu != NULL)
+ {
+ if (p_multi_inst_cb->data.p_manu->p_val != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_manu->p_val);
+ GKI_freebuf(p_multi_inst_cb->data.p_manu);
+ }
+
+ // Proprietary data cleanup
+ if (p_multi_inst_cb->data.p_proprietary != NULL)
+ {
+ int i = 0;
+ tBTA_BLE_PROP_ELEM *p_elem = p_multi_inst_cb->data.p_proprietary->p_elem;
+ while (i++ != p_multi_inst_cb->data.p_proprietary->num_elem
+ && p_elem)
+ {
+ if (p_elem->p_val != NULL)
+ GKI_freebuf(p_elem->p_val);
+ ++p_elem;
+ }
+
+ if (p_multi_inst_cb->data.p_proprietary->p_elem != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_proprietary->p_elem);
+ GKI_freebuf(p_multi_inst_cb->data.p_proprietary);
+ }
+
+ // Service list cleanup
+ if (p_multi_inst_cb->data.p_services != NULL)
+ {
+ if (p_multi_inst_cb->data.p_services->p_uuid != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_services->p_uuid);
+ GKI_freebuf(p_multi_inst_cb->data.p_services);
+ }
+
+ // Service data cleanup
+ if (p_multi_inst_cb->data.p_service_data != NULL)
+ {
+ if (p_multi_inst_cb->data.p_service_data->p_val != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_service_data->p_val);
+ GKI_freebuf(p_multi_inst_cb->data.p_service_data);
+ }
+
+ if (p_multi_inst_cb->data.p_services_128b != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_services_128b);
+
+ if (p_multi_inst_cb->data.p_service_32b != NULL)
+ {
+ if (p_multi_inst_cb->data.p_service_32b->p_uuid != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_service_32b->p_uuid);
+ GKI_freebuf(p_multi_inst_cb->data.p_service_32b);
+ }
+
+ if (p_multi_inst_cb->data.p_sol_services != NULL)
+ {
+ if (p_multi_inst_cb->data.p_sol_services->p_uuid != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_sol_services->p_uuid);
+ GKI_freebuf(p_multi_inst_cb->data.p_sol_services);
+ }
+
+ if (p_multi_inst_cb->data.p_sol_service_32b != NULL)
+ {
+ if (p_multi_inst_cb->data.p_sol_service_32b->p_uuid != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_sol_service_32b->p_uuid);
+ GKI_freebuf(p_multi_inst_cb->data.p_sol_service_32b);
+ }
+
+ if(p_multi_inst_cb->data.p_sol_service_128b != NULL)
+ GKI_freebuf(p_multi_inst_cb->data.p_sol_service_128b);
+}
+
+#endif
diff --git a/btif/src/btif_gatt_server.c b/btif/src/btif_gatt_server.c
index 9fc4fad..f5ad0f5 100644
--- a/btif/src/btif_gatt_server.c
+++ b/btif/src/btif_gatt_server.c
@@ -100,9 +100,10 @@
uint8_t is_direct;
uint8_t num_handles;
uint8_t properties;
- uint8_t transport;
uint8_t confirm;
uint8_t status;
+ btgatt_transport_t transport;
+
} __attribute__((packed)) btif_gatts_cb_t;
@@ -369,6 +370,7 @@
// Ensure device is in inquiry database
int addr_type = 0;
int device_type = 0;
+ tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
if (btif_get_device_type(p_cb->bd_addr.address, &addr_type, &device_type) == TRUE
&& device_type != BT_DEVICE_TYPE_BREDR)
@@ -378,9 +380,32 @@
if (!p_cb->is_direct)
BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
+ switch(device_type)
+ {
+ case BT_DEVICE_TYPE_BREDR:
+ transport = BTA_GATT_TRANSPORT_BR_EDR;
+ break;
+
+ case BT_DEVICE_TYPE_BLE:
+ transport = BTA_GATT_TRANSPORT_LE;
+ break;
+
+ case BT_DEVICE_TYPE_DUMO:
+ if ((p_cb->transport == GATT_TRANSPORT_LE) &&
+ (btif_storage_is_dmt_supported_device(&(p_cb->bd_addr)) == TRUE))
+ transport = BTA_GATT_TRANSPORT_LE;
+ else
+ transport = BTA_GATT_TRANSPORT_BR_EDR;
+ break;
+
+ default:
+ BTIF_TRACE_ERROR1 (" GATT Open :Invalid device type %d",device_type);
+ return;
+ }
+
// Connect!
BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
- p_cb->is_direct);
+ p_cb->is_direct, transport);
break;
}
@@ -489,12 +514,14 @@
(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 )
+static bt_status_t btif_gatts_open( int server_if, const bt_bdaddr_t *bd_addr,
+ bool is_direct, int transport )
{
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;
+ btif_cb.transport = (btgatt_transport_t)transport;
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);
diff --git a/btif/src/btif_gatt_test.c b/btif/src/btif_gatt_test.c
index a2cca6a..def2753 100644
--- a/btif/src/btif_gatt_test.c
+++ b/btif/src/btif_gatt_test.c
@@ -101,11 +101,12 @@
}
static void btif_test_connect_cback(tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
- BOOLEAN connected, tGATT_DISCONN_REASON reason)
+ BOOLEAN connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport)
{
UNUSED(gatt_if);
UNUSED(bda);
UNUSED(reason);
+ UNUSED (transport);
ALOGD("%s: conn_id=%d, connected=%d", __FUNCTION__, conn_id, connected);
test_cb.conn_id = connected ? conn_id : 0;
@@ -242,7 +243,7 @@
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) )
+ if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, TRUE, BT_TRANSPORT_LE) )
{
ALOGE("%s: GATT_Connect failed!", __FUNCTION__);
}
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
index 8a977d0..bde76ef 100644
--- a/btif/src/btif_gatt_util.c
+++ b/btif/src/btif_gatt_util.c
@@ -131,6 +131,32 @@
memcpy(p_dest->attr_value.value, p_src->attr_value.value, GATT_MAX_ATTR_LEN);
}
+void btif_to_bta_uuid_mask(tBTA_DM_BLE_PF_COND_MASK *p_mask, bt_uuid_t *p_src)
+{
+ char *p_byte = (char*)p_src;
+ int i = 0;
+
+ switch (uuidType(p_src->uu))
+ {
+ case LEN_UUID_16:
+ p_mask->uuid16_mask = (p_src->uu[13] << 8) + p_src->uu[12];
+ break;
+
+ case LEN_UUID_32:
+ p_mask->uuid32_mask = (p_src->uu[13] << 8) + p_src->uu[12];
+ p_mask->uuid32_mask += (p_src->uu[15] << 24) + (p_src->uu[14] << 16);
+ break;
+
+ case LEN_UUID_128:
+ for(i = 0; i != 16; ++i)
+ p_mask->uuid128_mask[i] = p_byte[i];
+ break;
+
+ default:
+ break;
+ }
+}
+
/*******************************************************************************
* BTA -> BTIF conversion functions
*******************************************************************************/
@@ -259,7 +285,7 @@
* Encrypted link map handling
*******************************************************************************/
-static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_STATUS result);
+static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_STATUS result);
static BOOLEAN btif_gatt_is_link_encrypted (BD_ADDR bd_addr)
{
@@ -269,8 +295,10 @@
return BTA_JvIsEncrypted(bd_addr);
}
-static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_STATUS result)
+static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_STATUS result)
{
+ UNUSED(transport);
+
if (result != BTA_SUCCESS && result != BTA_BUSY)
{
bt_bdaddr_t bda;
@@ -286,16 +314,39 @@
bt_bdaddr_t bda;
bdcpy(bda.address, bd_addr);
+ int device_type = 0;
+ int addr_type = 0;
+#if (!defined(BLE_DELAY_REQUEST_ENC) || (BLE_DELAY_REQUEST_ENC == FALSE))
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))
{
-#if (!defined(BLE_DELAY_REQUEST_ENC) || (BLE_DELAY_REQUEST_ENC == FALSE))
- BTA_DmSetEncryption(bd_addr,
+ tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
+
+ btif_get_device_type(bd_addr, &addr_type, &device_type);
+ switch(device_type)
+ {
+ case BT_DEVICE_TYPE_BREDR:
+ transport = BTA_GATT_TRANSPORT_BR_EDR;
+ break;
+
+ case BT_DEVICE_TYPE_BLE:
+ transport = BTA_GATT_TRANSPORT_LE;
+ break;
+
+ case BT_DEVICE_TYPE_DUMO:
+ transport = BTA_GATT_TRANSPORT_LE_BR_EDR;
+ break;
+
+ default:
+ BTIF_TRACE_ERROR1 (" GATT Encrypt :Invalid device type %d",device_type);
+ return;
+ }
+ BTA_DmSetEncryption(bd_addr,transport,
&btif_gatt_set_encryption_cb, BTM_BLE_SEC_ENCRYPT);
-#endif
}
+#endif
}
/*******************************************************************************
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
index b4ade0d..d2e8354 100644
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -71,10 +71,31 @@
BTA_AG_FEAT_UNAT)
#endif
-#define BTIF_HF_ID_1 0
-
#define BTIF_HF_CALL_END_TIMEOUT 6
+#define BTIF_HF_INVALID_IDX -1
+
+/* Number of BTIF-HF control blocks */
+#define BTIF_HF_NUM_CB 2
+
+/* Max HF clients supported from App */
+UINT16 btif_max_hf_clients = -1;
+
+/* HF app ids for service registration */
+typedef enum {
+ BTIF_HF_ID_1 = 0,
+ BTIF_HF_ID_2,
+#if (BTIF_HF_NUM_CB == 3)
+ BTIF_HF_ID_3
+#endif
+} bthf_hf_id_t;
+
+UINT16 bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2,
+ #if (BTIF_HF_NUM_CB == 3)
+ BTIF_HF_ID_3
+ #endif
+ };
+
/************************************************************************************
** Local type definitions
************************************************************************************/
@@ -83,6 +104,7 @@
** Static variables
************************************************************************************/
static bthf_callbacks_t *bt_hf_callbacks = NULL;
+static int hf_idx = BTIF_HF_INVALID_IDX;
#define CHECK_BTHF_INIT() if (bt_hf_callbacks == NULL)\
{\
@@ -120,10 +142,11 @@
int num_active;
int num_held;
struct timespec call_end_timestamp;
+ struct timespec connected_timestamp;
bthf_call_state_t call_setup_state;
} btif_hf_cb_t;
-static btif_hf_cb_t btif_hf_cb;
+static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
/************************************************************************************
@@ -149,15 +172,41 @@
*******************************************************************************/
static BOOLEAN is_connected(bt_bdaddr_t *bd_addr)
{
- if (((btif_hf_cb.state == BTHF_CONNECTION_STATE_CONNECTED) || (btif_hf_cb.state == BTHF_CONNECTION_STATE_SLC_CONNECTED))&&
- ((bd_addr == NULL) || (bdcmp(bd_addr->address, btif_hf_cb.connected_bda.address) == 0)))
- return TRUE;
- else
+ int i;
+ for (i = 0; i < btif_max_hf_clients; ++i)
+ {
+ if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+ (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
+ ((bd_addr == NULL) || (bdcmp(bd_addr->address,
+ btif_hf_cb[i].connected_bda.address) == 0)))
+ return TRUE;
+ }
return FALSE;
}
/*******************************************************************************
**
+** Function btif_hf_idx_by_bdaddr
+**
+** Description Internal function to get idx by bdaddr
+**
+** Returns idx
+**
+*******************************************************************************/
+static int btif_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
+{
+ int i;
+ for (i = 0; i < btif_max_hf_clients; ++i)
+ {
+ if ((bdcmp(bd_addr->address,
+ btif_hf_cb[i].connected_bda.address) == 0))
+ return i;
+ }
+ return BTIF_HF_INVALID_IDX;
+}
+
+/*******************************************************************************
+**
** Function callstate_to_callsetup
**
** Description Converts HAL call state to BTA call setup indicator value
@@ -187,7 +236,7 @@
** Returns void
**
*******************************************************************************/
-static void send_at_result(UINT8 ok_flag, UINT16 errcode)
+static void send_at_result(UINT8 ok_flag, UINT16 errcode, int idx)
{
tBTA_AG_RES_DATA ag_res;
memset (&ag_res, 0, sizeof (ag_res));
@@ -198,7 +247,7 @@
ag_res.errcode = errcode;
}
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
}
/*******************************************************************************
@@ -221,12 +270,77 @@
BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
}
-void clear_phone_state()
+void clear_phone_state_multihf(int idx)
{
- btif_hf_cb.call_setup_state = BTHF_CALL_STATE_IDLE;
- btif_hf_cb.num_active = btif_hf_cb.num_held = 0;
+ btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE;
+ btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0;
}
+/*******************************************************************************
+**
+** Function btif_hf_latest_connected_idx
+**
+** Description Returns idx for latest connected HF
+**
+** Returns int
+**
+*******************************************************************************/
+static int btif_hf_latest_connected_idx()
+{
+ struct timespec now, conn_time_delta;
+ int latest_conn_idx = BTIF_HF_INVALID_IDX, i;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ conn_time_delta.tv_sec = now.tv_sec;
+
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)
+ {
+ if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec)
+ < conn_time_delta.tv_sec)
+ {
+ conn_time_delta.tv_sec =
+ now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec;
+ latest_conn_idx = i;
+ }
+ }
+ }
+ return latest_conn_idx;
+}
+
+/*******************************************************************************
+**
+** Function btif_hf_check_if_slc_connected
+**
+** Description Returns BT_STATUS_SUCCESS if SLC is up for any HF
+**
+** Returns bt_status_t
+**
+*******************************************************************************/
+static bt_status_t btif_hf_check_if_slc_connected()
+{
+ if (bt_hf_callbacks == NULL)
+ {
+ BTIF_TRACE_WARNING1("BTHF: %s: BTHF not initialized", __FUNCTION__);
+ return BT_STATUS_NOT_READY;
+ }
+ else
+ {
+ int i;
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ if ((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED))
+ {
+ BTIF_TRACE_EVENT2("BTHF: %s: slc connected for idx = %d",
+ __FUNCTION__, i);
+ return BT_STATUS_SUCCESS;
+ }
+ }
+ BTIF_TRACE_WARNING1("BTHF: %s: No SLC connection up", __FUNCTION__);
+ return BT_STATUS_NOT_READY;
+ }
+}
/*****************************************************************************
** Section name (Group of functions)
@@ -252,6 +366,8 @@
{
tBTA_AG *p_data = (tBTA_AG *)p_param;
bdstr_t bdstr;
+ bt_bdaddr_t addr;
+ int idx = p_data->hdr.handle - 1;
BTIF_TRACE_DEBUG2("%s: event=%s", __FUNCTION__, dump_hf_event(event));
@@ -262,43 +378,54 @@
break;
case BTA_AG_REGISTER_EVT:
- btif_hf_cb.handle = p_data->reg.hdr.handle;
+ btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
+ BTIF_TRACE_DEBUG2("%s: BTA_AG_REGISTER_EVT,"
+ "btif_hf_cb.handle = %d", __FUNCTION__, btif_hf_cb[idx].handle);
break;
case BTA_AG_OPEN_EVT:
if (p_data->open.status == BTA_AG_SUCCESS)
{
- bdcpy(btif_hf_cb.connected_bda.address, p_data->open.bd_addr);
- btif_hf_cb.state = BTHF_CONNECTION_STATE_CONNECTED;
- btif_hf_cb.peer_feat = 0;
- clear_phone_state();
+ bdcpy(btif_hf_cb[idx].connected_bda.address,
+ p_data->open.bd_addr);
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
+ btif_hf_cb[idx].peer_feat = 0;
+ clear_phone_state_multihf(idx);
}
- else if (btif_hf_cb.state == BTHF_CONNECTION_STATE_CONNECTING)
+ else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING)
{
- btif_hf_cb.state = BTHF_CONNECTION_STATE_DISCONNECTED;
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
}
else
{
BTIF_TRACE_WARNING4("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s",
- __FUNCTION__, p_data->open.status, btif_hf_cb.state, bd2str(&btif_hf_cb.connected_bda, &bdstr));
+ __FUNCTION__, p_data->open.status, btif_hf_cb[idx].state,
+ bd2str(&btif_hf_cb[idx].connected_bda, &bdstr));
break;
}
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state, &btif_hf_cb.connected_bda);
+ HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
+ &btif_hf_cb[idx].connected_bda);
- if (btif_hf_cb.state == BTHF_CONNECTION_STATE_DISCONNECTED)
- bdsetany(btif_hf_cb.connected_bda.address);
+ if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
+ bdsetany(btif_hf_cb[idx].connected_bda.address);
if (p_data->open.status != BTA_AG_SUCCESS)
btif_queue_advance();
break;
case BTA_AG_CLOSE_EVT:
- btif_hf_cb.state = BTHF_CONNECTION_STATE_DISCONNECTED;
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state, &btif_hf_cb.connected_bda);
- bdsetany(btif_hf_cb.connected_bda.address);
- btif_hf_cb.peer_feat = 0;
- clear_phone_state();
+ btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
+ BTIF_TRACE_DEBUG3("%s: BTA_AG_CLOSE_EVT,"
+ "idx = %d, btif_hf_cb.handle = %d", __FUNCTION__, idx,
+ btif_hf_cb[idx].handle);
+ HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
+ &btif_hf_cb[idx].connected_bda);
+ bdsetany(btif_hf_cb[idx].connected_bda.address);
+ btif_hf_cb[idx].peer_feat = 0;
+ clear_phone_state_multihf(idx);
+ hf_idx = btif_hf_latest_connected_idx();
/* If AG_OPEN was received but SLC was not setup in a specified time (10 seconds),
** then AG_CLOSE may be received. We need to advance the queue here
*/
@@ -306,60 +433,87 @@
break;
case BTA_AG_CONN_EVT:
- btif_hf_cb.peer_feat = p_data->conn.peer_feat;
- btif_hf_cb.state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
+ clock_gettime(CLOCK_MONOTONIC,
+ &btif_hf_cb[idx].connected_timestamp);
+ BTIF_TRACE_DEBUG2("%s: BTA_AG_CONN_EVT, idx = %d ",
+ __FUNCTION__, idx);
+ btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
+ btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
+ hf_idx = btif_hf_latest_connected_idx();
- HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state,
- &btif_hf_cb.connected_bda);
+ HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
+ &btif_hf_cb[idx].connected_bda);
btif_queue_advance();
break;
case BTA_AG_AUDIO_OPEN_EVT:
- HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED, &btif_hf_cb.connected_bda);
+ hf_idx = idx;
+ HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AUDIO_CLOSE_EVT:
- HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED, &btif_hf_cb.connected_bda);
+ HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
+ &btif_hf_cb[idx].connected_bda);
break;
/* BTA auto-responds, silently discard */
case BTA_AG_SPK_EVT:
case BTA_AG_MIC_EVT:
HAL_CBACK(bt_hf_callbacks, volume_cmd_cb,
- (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK : BTHF_VOLUME_TYPE_MIC, p_data->val.num);
+ (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK :
+ BTHF_VOLUME_TYPE_MIC, p_data->val.num,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_A_EVT:
- HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb);
+ if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
+ hf_idx = idx;
+ else
+ BTIF_TRACE_DEBUG0("Donot set hf_idx for ATA since already in a call");
+
+ HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
/* Java needs to send OK/ERROR for these commands */
case BTA_AG_AT_BLDN_EVT:
case BTA_AG_AT_D_EVT:
+ if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
+ hf_idx = idx;
+ else
+ BTIF_TRACE_DEBUG0("Donot set hf_idx for BLDN/D since already in a call");
+
HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
- (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL);
+ (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CHUP_EVT:
- HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CIND_EVT:
- HAL_CBACK(bt_hf_callbacks, cind_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, cind_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_VTS_EVT:
- HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0]);
+ HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_BVRA_EVT:
HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
- (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED : BTHF_VR_STATE_STOPPED);
+ (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED :
+ BTHF_VR_STATE_STOPPED, &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_NREC_EVT:
HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
- (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP);
+ (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
+ &btif_hf_cb[idx].connected_bda);
break;
/* TODO: Add a callback for CBC */
@@ -367,35 +521,40 @@
break;
case BTA_AG_AT_CKPD_EVT:
- HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
/* Java needs to send OK/ERROR for these commands */
case BTA_AG_AT_CHLD_EVT:
- HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str));
+ HAL_CBACK(bt_hf_callbacks, chld_cmd_cb, atoi(p_data->val.str),
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CLCC_EVT:
- HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb, p_data->val.num);
+ HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_COPS_EVT:
- HAL_CBACK(bt_hf_callbacks, cops_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, cops_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_UNAT_EVT:
- HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb,
- p_data->val.str);
+ HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
+ &btif_hf_cb[idx].connected_bda);
break;
case BTA_AG_AT_CNUM_EVT:
- HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb);
+ HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb,
+ &btif_hf_cb[idx].connected_bda);
break;
/* TODO: Some of these commands may need to be sent to app. For now respond with error */
case BTA_AG_AT_BINP_EVT:
case BTA_AG_AT_BTRH_EVT:
- send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx);
break;
@@ -452,14 +611,14 @@
*******************************************************************************/
static void btif_in_hf_generic_evt(UINT16 event, char *p_param)
{
- UNUSED(p_param);
+ int idx = btif_hf_idx_by_bdaddr((bt_bdaddr_t *)p_param);
BTIF_TRACE_EVENT2("%s: event=%d", __FUNCTION__, event);
switch (event) {
case BTIF_HFP_CB_AUDIO_CONNECTING:
{
HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
- &btif_hf_cb.connected_bda);
+ &btif_hf_cb[idx].connected_bda);
} break;
default:
{
@@ -479,9 +638,10 @@
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t init( bthf_callbacks_t* callbacks )
+static bt_status_t init( bthf_callbacks_t* callbacks, int max_hf_clients)
{
BTIF_TRACE_EVENT1("%s", __FUNCTION__);
+ int i;
bt_hf_callbacks = callbacks;
@@ -495,8 +655,13 @@
btif_enable_service(BTA_HSP_SERVICE_ID);
#endif
- memset(&btif_hf_cb, 0, sizeof(btif_hf_cb_t));
- clear_phone_state();
+ memset(&btif_hf_cb, 0, sizeof(btif_hf_cb));
+ btif_max_hf_clients = max_hf_clients;
+ BTIF_TRACE_DEBUG1("btif_max_hf_clients = %d", btif_max_hf_clients);
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ clear_phone_state_multihf(i);
+ }
return BT_STATUS_SUCCESS;
}
@@ -512,12 +677,26 @@
*******************************************************************************/
static bt_status_t connect_int( bt_bdaddr_t *bd_addr )
{
+ CHECK_BTHF_INIT();
+ int i;
+ for (i = 0; i < btif_max_hf_clients;)
+ {
+ if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
+ (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)))
+ i++;
+ else
+ break;
+ }
+
+ if (i == btif_max_hf_clients)
+ return BT_STATUS_BUSY;
+
if (!is_connected(bd_addr))
{
- btif_hf_cb.state = BTHF_CONNECTION_STATE_CONNECTING;
- bdcpy(btif_hf_cb.connected_bda.address, bd_addr->address);
+ btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
+ bdcpy(btif_hf_cb[i].connected_bda.address, bd_addr->address);
- BTA_AgOpen(btif_hf_cb.handle, btif_hf_cb.connected_bda.address,
+ BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda.address,
BTIF_HF_SECURITY, BTIF_HF_SERVICES);
return BT_STATUS_SUCCESS;
}
@@ -544,9 +723,11 @@
{
CHECK_BTHF_INIT();
- if (is_connected(bd_addr))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- BTA_AgClose(btif_hf_cb.handle);
+ BTA_AgClose(btif_hf_cb[idx].handle);
return BT_STATUS_SUCCESS;
}
@@ -566,9 +747,11 @@
{
CHECK_BTHF_INIT();
- if (is_connected(bd_addr))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- BTA_AgAudioOpen(btif_hf_cb.handle);
+ BTA_AgAudioOpen(btif_hf_cb[idx].handle);
/* Inform the application that the audio connection has been initiated successfully */
btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING,
@@ -592,9 +775,11 @@
{
CHECK_BTHF_INIT();
- if (is_connected(bd_addr))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- BTA_AgAudioClose(btif_hf_cb.handle);
+ BTA_AgAudioClose(btif_hf_cb[idx].handle);
return BT_STATUS_SUCCESS;
}
@@ -610,17 +795,20 @@
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t start_voice_recognition()
+static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- if (btif_hf_cb.peer_feat & BTA_AG_PEER_FEAT_VREC)
+ if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
{
tBTA_AG_RES_DATA ag_res;
memset(&ag_res, 0, sizeof(ag_res));
ag_res.state = 1;
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -642,18 +830,20 @@
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t stop_voice_recognition()
+static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
- if (btif_hf_cb.peer_feat & BTA_AG_PEER_FEAT_VREC)
+ if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC)
{
tBTA_AG_RES_DATA ag_res;
memset(&ag_res, 0, sizeof(ag_res));
ag_res.state = 0;
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -675,16 +865,19 @@
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t volume_control(bthf_volume_type_t type, int volume)
+static bt_status_t volume_control(bthf_volume_type_t type, int volume,
+ bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
tBTA_AG_RES_DATA ag_res;
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
- if (is_connected(NULL))
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
ag_res.num = volume;
- BTA_AgResult(btif_hf_cb.handle,
+ BTA_AgResult(btif_hf_cb[idx].handle,
(type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
&ag_res);
return BT_STATUS_SUCCESS;
@@ -733,11 +926,13 @@
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t cops_response(const char *cops)
+static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
tBTA_AG_RES_DATA ag_res;
@@ -745,7 +940,7 @@
sprintf (ag_res.str, "0,0,\"%s\"", cops);
ag_res.ok_flag = BTA_AG_OK_DONE;
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_COPS_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
return BT_STATUS_FAIL;
@@ -762,11 +957,14 @@
*******************************************************************************/
static bt_status_t cind_response(int svc, int num_active, int num_held,
bthf_call_state_t call_setup_state,
- int signal, int roam, int batt_chg)
+ int signal, int roam, int batt_chg,
+ bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
tBTA_AG_RES_DATA ag_res;
@@ -783,7 +981,7 @@
batt_chg, /* Battery level */
((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_CIND_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -800,17 +998,18 @@
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t formatted_at_response(const char *rsp)
+static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
tBTA_AG_RES_DATA ag_res;
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
- if (is_connected(NULL))
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
/* Format the response and send */
memset (&ag_res, 0, sizeof (ag_res));
strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -827,14 +1026,17 @@
** Returns bt_status_t
**
*******************************************************************************/
-static bt_status_t at_response(bthf_at_response_t response_code, int error_code)
+static bt_status_t at_response(bthf_at_response_t response_code,
+ int error_code, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
- : BTA_AG_OK_ERROR, error_code);
+ : BTA_AG_OK_ERROR, error_code, idx);
return BT_STATUS_SUCCESS;
}
@@ -854,13 +1056,15 @@
**
*******************************************************************************/
static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
- bthf_call_state_t state, bthf_call_mode_t mode,
- bthf_call_mpty_type_t mpty, const char *number,
- bthf_call_addrtype_t type)
+ bthf_call_state_t state, bthf_call_mode_t mode,
+ bthf_call_mpty_type_t mpty, const char *number,
+ bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr)
{
CHECK_BTHF_INIT();
- if (is_connected(NULL))
+ int idx = btif_hf_idx_by_bdaddr(bd_addr);
+
+ if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
{
tBTA_AG_RES_DATA ag_res;
int xx;
@@ -887,7 +1091,7 @@
sprintf (&ag_res.str[xx], ",\"%s\",%d", number, type);
}
}
- BTA_AgResult (btif_hf_cb.handle, BTA_AG_CLCC_RES, &ag_res);
+ BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
return BT_STATUS_SUCCESS;
}
@@ -913,29 +1117,44 @@
tBTA_AG_RES_DATA ag_res;
bt_status_t status = BT_STATUS_SUCCESS;
BOOLEAN activeCallUpdated = FALSE;
+ int idx, i;
- CHECK_BTHF_SLC_CONNECTED();
+ /* hf_idx is index of connected HS that sent ATA/BLDN,
+ otherwise index of latest connected HS */
+ if (hf_idx != BTIF_HF_INVALID_IDX)
+ idx = hf_idx;
+ else
+ idx = btif_hf_latest_connected_idx();
- BTIF_TRACE_DEBUG6("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"\
- " call_setup=%s [prev: %s]", num_active, btif_hf_cb.num_active,
- num_held, btif_hf_cb.num_held,
- dump_hf_call_state(call_setup_state), dump_hf_call_state(btif_hf_cb.call_setup_state));
+ BTIF_TRACE_DEBUG1("phone_state_change: idx = %d", idx);
+
+ /* Check if SLC is connected */
+ if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
+ return BT_STATUS_NOT_READY;
+
+ BTIF_TRACE_DEBUG6("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"
+ " call_setup=%s [prev: %s]", num_active, btif_hf_cb[idx].num_active,
+ num_held, btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
+ dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
/* if all indicators are 0, send end call and return */
if (num_active == 0 && num_held == 0 && call_setup_state == BTHF_CALL_STATE_IDLE)
{
BTIF_TRACE_DEBUG1("%s: Phone on hook", __FUNCTION__);
- /* record call termination timestamp if there was an active/held call or callsetup state > BTHF_CALL_STATE_IDLE */
- if ((btif_hf_cb.call_setup_state != BTHF_CALL_STATE_IDLE ) || (btif_hf_cb.num_active) ||(btif_hf_cb.num_held))
+ /* record call termination timestamp if there was an active/held call or
+ callsetup state > BTHF_CALL_STATE_IDLE */
+ if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE ) ||
+ (btif_hf_cb[idx].num_active) ||(btif_hf_cb[idx].num_held))
{
BTIF_TRACE_DEBUG1("%s: Record call termination timestamp", __FUNCTION__);
- clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb.call_end_timestamp);
+ clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
}
BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
+ hf_idx = BTIF_HF_INVALID_IDX;
/* if held call was present, reset that as well */
- if (btif_hf_cb.num_held)
+ if (btif_hf_cb[idx].num_held)
send_indicator_update(BTA_AG_IND_CALLHELD, 0);
goto update_call_states;
@@ -952,24 +1171,24 @@
** force the SCO to be setup. Handle this special case here prior to
** call setup handling
*/
- if ( (num_active == 1) && (btif_hf_cb.num_active == 0) && (btif_hf_cb.num_held == 0) &&
- (btif_hf_cb.call_setup_state == BTHF_CALL_STATE_IDLE) )
+ if ( (num_active == 1) && (btif_hf_cb[idx].num_active == 0) && (btif_hf_cb[idx].num_held == 0)
+ && (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) )
{
BTIF_TRACE_DEBUG1("%s: Active call notification received without call setup update",
__FUNCTION__);
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
- ag_res.audio_handle = btif_hf_cb.handle;
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
res = BTA_AG_OUT_CALL_CONN_RES;
BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
activeCallUpdated = TRUE;
}
/* Ringing call changed? */
- if (call_setup_state != btif_hf_cb.call_setup_state)
+ if (call_setup_state != btif_hf_cb[idx].call_setup_state)
{
BTIF_TRACE_DEBUG3("%s: Call setup states changed. old: %s new: %s",
- __FUNCTION__, dump_hf_call_state(btif_hf_cb.call_setup_state),
+ __FUNCTION__, dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
dump_hf_call_state(call_setup_state));
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
@@ -977,22 +1196,22 @@
{
case BTHF_CALL_STATE_IDLE:
{
- switch (btif_hf_cb.call_setup_state)
+ switch (btif_hf_cb[idx].call_setup_state)
{
case BTHF_CALL_STATE_INCOMING:
- if (num_active > btif_hf_cb.num_active)
+ if (num_active > btif_hf_cb[idx].num_active)
{
res = BTA_AG_IN_CALL_CONN_RES;
- ag_res.audio_handle = btif_hf_cb.handle;
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
}
- else if (num_held > btif_hf_cb.num_held)
+ else if (num_held > btif_hf_cb[idx].num_held)
res = BTA_AG_IN_CALL_HELD_RES;
else
res = BTA_AG_CALL_CANCEL_RES;
break;
case BTHF_CALL_STATE_DIALING:
case BTHF_CALL_STATE_ALERTING:
- if (num_active > btif_hf_cb.num_active)
+ if (num_active > btif_hf_cb[idx].num_active)
{
ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
res = BTA_AG_OUT_CALL_CONN_RES;
@@ -1026,13 +1245,13 @@
}
break;
case BTHF_CALL_STATE_DIALING:
- ag_res.audio_handle = btif_hf_cb.handle;
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
res = BTA_AG_OUT_CALL_ORIG_RES;
break;
case BTHF_CALL_STATE_ALERTING:
/* if we went from idle->alert, force SCO setup here. dialing usually triggers it */
- if (btif_hf_cb.call_setup_state == BTHF_CALL_STATE_IDLE)
- ag_res.audio_handle = btif_hf_cb.handle;
+ if (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE)
+ ag_res.audio_handle = btif_hf_cb[idx].handle;
res = BTA_AG_OUT_CALL_ALERT_RES;
break;
default:
@@ -1061,34 +1280,38 @@
** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
** Handle call indicator change
**/
- if (!activeCallUpdated && ((num_active + num_held) != (btif_hf_cb.num_active + btif_hf_cb.num_held)) )
+ if (!activeCallUpdated && ((num_active + num_held) !=
+ (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held)) )
{
- BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_active, num_active);
+ BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb[idx].num_active, num_active);
send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
}
/* Held Changed? */
- if (num_held != btif_hf_cb.num_held)
+ if (num_held != btif_hf_cb[idx].num_held)
{
- BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_held, num_held);
+ BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d",
+ __FUNCTION__, btif_hf_cb[idx].num_held, num_held);
send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
}
/* Calls Swapped? */
- if ( (call_setup_state == btif_hf_cb.call_setup_state) &&
+ if ( (call_setup_state == btif_hf_cb[idx].call_setup_state) &&
(num_active && num_held) &&
- (num_active == btif_hf_cb.num_active) &&
- (num_held == btif_hf_cb.num_held) )
+ (num_active == btif_hf_cb[idx].num_active) &&
+ (num_held == btif_hf_cb[idx].num_held) )
{
BTIF_TRACE_DEBUG1("%s: Calls swapped", __FUNCTION__);
send_indicator_update(BTA_AG_IND_CALLHELD, 1);
}
update_call_states:
- btif_hf_cb.num_active = num_active;
- btif_hf_cb.num_held = num_held;
- btif_hf_cb.call_setup_state = call_setup_state;
-
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ btif_hf_cb[i].num_active = num_active;
+ btif_hf_cb[i].num_held = num_held;
+ btif_hf_cb[i].call_setup_state = call_setup_state;
+ }
return status;
}
@@ -1107,13 +1330,14 @@
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
- if (now.tv_sec < btif_hf_cb.call_end_timestamp.tv_sec + BTIF_HF_CALL_END_TIMEOUT)
+ if (now.tv_sec < btif_hf_cb[0].call_end_timestamp.tv_sec +
+ BTIF_HF_CALL_END_TIMEOUT)
{
return TRUE;
}
else
{
- btif_hf_cb.call_end_timestamp.tv_sec = 0;
+ btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
return FALSE;
}
}
@@ -1170,16 +1394,23 @@
bt_status_t btif_hf_execute_service(BOOLEAN b_enable)
{
char * p_service_names[] = BTIF_HF_SERVICE_NAMES;
+ int i;
if (b_enable)
{
/* Enable and register with BTA-AG */
BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt);
- BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY, BTIF_HF_FEATURES,
- p_service_names, BTIF_HF_ID_1);
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY,
+ BTIF_HF_FEATURES, p_service_names, bthf_hf_id[i]);
+ }
}
else {
/* De-register AG */
- BTA_AgDeregister(btif_hf_cb.handle);
+ for (i = 0; i < btif_max_hf_clients; i++)
+ {
+ BTA_AgDeregister(btif_hf_cb[i].handle);
+ }
/* Disable AG */
BTA_AgDisable();
}
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index 34b119d..051e746 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -587,6 +587,8 @@
dest->product_id = src->product_id;
dest->version = src->version;
dest->ctry_code = src->ctry_code;
+ dest->ssr_max_latency = src->ssr_max_latency;
+ dest->ssr_min_tout = src->ssr_min_tout;
return TRUE;
}
@@ -1634,11 +1636,18 @@
}
else {
int hex_bytes_filled;
- UINT8 hexbuf[200];
+ UINT8 *hexbuf;
UINT16 len = (strlen(report) + 1) / 2;
+ hexbuf = GKI_getbuf(len);
+ if (hexbuf == NULL) {
+ BTIF_TRACE_ERROR2("%s: Error, failed to allocate RPT buffer, len = %d",
+ __FUNCTION__, len);
+ return BT_STATUS_FAIL;
+ }
+
/* Build a SetReport data buffer */
- memset(hexbuf, 0, 200);
+ memset(hexbuf, 0, len);
//TODO
hex_bytes_filled = ascii_2_hex(report, len, hexbuf);
BTIF_TRACE_DEBUG1("Hex bytes filled, hex value: %d", hex_bytes_filled);
@@ -1647,11 +1656,15 @@
if (p_buf == NULL) {
BTIF_TRACE_ERROR2("%s: Error, failed to allocate RPT buffer, len = %d",
__FUNCTION__, hex_bytes_filled);
+ GKI_freebuf(hexbuf);
return BT_STATUS_FAIL;
}
BTA_HhSetReport(p_dev->dev_handle, reportType, p_buf);
+ GKI_freebuf(hexbuf);
+ return BT_STATUS_SUCCESS;
}
- return BT_STATUS_SUCCESS;
+ GKI_freebuf(hexbuf);
+ return BT_STATUS_FAIL;
}
}
@@ -1689,11 +1702,18 @@
else {
int hex_bytes_filled;
- UINT8 hexbuf[200];
+ UINT8 *hexbuf;
UINT16 len = (strlen(data) + 1) / 2;
- /* Build a SetReport data buffer */
- memset(hexbuf, 0, 200);
+ hexbuf = GKI_getbuf(len);
+ if (hexbuf == NULL) {
+ BTIF_TRACE_ERROR2("%s: Error, failed to allocate RPT buffer, len = %d",
+ __FUNCTION__, len);
+ return BT_STATUS_FAIL;
+ }
+
+ /* Build a SendData data buffer */
+ memset(hexbuf, 0, len);
hex_bytes_filled = ascii_2_hex(data, len, hexbuf);
BTIF_TRACE_ERROR2("Hex bytes filled, hex value: %d, %d", hex_bytes_filled, len);
@@ -1702,15 +1722,17 @@
if (p_buf == NULL) {
BTIF_TRACE_ERROR2("%s: Error, failed to allocate RPT buffer, len = %d",
__FUNCTION__, hex_bytes_filled);
+ GKI_freebuf(hexbuf);
return BT_STATUS_FAIL;
}
p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
BTA_HhSendData(p_dev->dev_handle, *bda, p_buf);
+ GKI_freebuf(hexbuf);
return BT_STATUS_SUCCESS;
}
-
+ GKI_freebuf(hexbuf);
+ return BT_STATUS_FAIL;
}
- return BT_STATUS_FAIL;
}
diff --git a/btif/src/btif_hl.c b/btif/src/btif_hl.c
index e80a0b9..efa5ca7 100644
--- a/btif/src/btif_hl.c
+++ b/btif/src/btif_hl.c
@@ -189,6 +189,9 @@
btif_hl_mcl_cb_t *p_mcb;
UINT8 i, j;
BOOLEAN found=FALSE;
+
+ *p_app_idx = 0;
+ *p_mcl_idx = 0;
for (i=0; i < BTA_HL_NUM_APPS ; i ++)
{
p_acb =BTIF_HL_GET_APP_CB_PTR(i);
@@ -1002,6 +1005,8 @@
UINT8 i,j;
int mdl_cfg_channel_id;
+ *p_app_idx = 0;
+ *p_mdl_cfg_idx =0;
for (i=0; i < BTA_HL_NUM_APPS ; i ++)
{
p_acb =BTIF_HL_GET_APP_CB_PTR(i);
@@ -1125,6 +1130,9 @@
BOOLEAN found=FALSE;
UINT8 i,j,k;
+ *p_app_idx = 0;
+ *p_mcl_idx =0;
+ *p_mdl_idx = 0;
for (i=0; i < BTA_HL_NUM_APPS ; i ++)
{
p_acb =BTIF_HL_GET_APP_CB_PTR(i);
@@ -1324,6 +1332,7 @@
btif_hl_app_cb_t *p_acb =BTIF_HL_GET_APP_CB_PTR(app_idx);
btif_hl_mcl_cb_t *p_mcb;
+ *p_mcl_idx = 0;
for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
{
p_mcb = BTIF_HL_GET_MCL_CB_PTR(app_idx, i);
@@ -1585,6 +1594,7 @@
*p = BTA_HL_MDEP_ROLE_SINK;
break;
default:
+ *p = BTA_HL_MDEP_ROLE_SOURCE;
status = FALSE;
break;
}
@@ -1744,6 +1754,7 @@
BOOLEAN found=FALSE;
UINT8 i;
+ *p_app_idx = 0;
for (i=0; i < BTA_HL_NUM_APPS ; i ++)
{
if (btif_hl_cb.acb[i].in_use &&
@@ -2026,6 +2037,7 @@
BOOLEAN found=FALSE;
UINT8 i;
+ *p_app_idx = 0;
for (i=0; i < BTA_HL_NUM_APPS ; i ++)
{
BTIF_TRACE_DEBUG1("btif_hl_find_app_idx_using_mdepId: MDEP-ID = %d",
@@ -2635,7 +2647,6 @@
BOOLEAN status = FALSE;
tBTA_HL_DCH_OPEN_PARAM dch_open;
-
BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
if (btif_hl_find_app_idx_using_app_id(p_data->cch_open_cfm.app_id, &app_idx))
@@ -4131,7 +4142,7 @@
**
*******************************************************************************/
static bt_status_t destroy_channel(int channel_id){
- UINT8 app_idx, mcl_idx, mdl_idx, mdl_cfg_idx, app_id, mdep_cfg_idx;
+ UINT8 app_idx, mcl_idx, mdl_idx, mdl_cfg_idx, app_id, mdep_cfg_idx = 0;
bt_status_t status = BT_STATUS_SUCCESS;
btif_hl_mdl_cfg_t *p_mdl;
btif_hl_mcl_cb_t *p_mcb;
@@ -5056,10 +5067,14 @@
char sig_on = btif_hl_signal_select_exit;
BTIF_TRACE_DEBUG0("btif_hl_signal_select_exit");
result = send(signal_fds[1], &sig_on, sizeof(sig_on), 0);
- /* Wait for the select_thread_id to exit */
- if (select_thread_id != -1) {
- pthread_join(select_thread_id, NULL);
- select_thread_id = -1;
+ if (btif_is_enabled())
+ {
+ /* Wait for the select_thread_id to exit if BT is still enabled
+ and only this profile getting cleaned up*/
+ if (select_thread_id != -1) {
+ pthread_join(select_thread_id, NULL);
+ select_thread_id = -1;
+ }
}
/* Cleanup signal sockets */
if(signal_fds[0] != -1)
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
old mode 100755
new mode 100644
diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c
index 5119493..b0e284f 100644
--- a/btif/src/btif_pan.c
+++ b/btif/src/btif_pan.c
@@ -26,6 +26,7 @@
***********************************************************************************/
#include <hardware/bluetooth.h>
#include <hardware/bt_pan.h>
+#include <assert.h>
#include <signal.h>
#include <ctype.h>
#include <sys/select.h>
@@ -56,7 +57,12 @@
#include "btif_sock_thread.h"
#include "btif_sock_util.h"
#include "btif_pan_internal.h"
+#include "gki.h"
+#define FORWARD_IGNORE 1
+#define FORWARD_SUCCESS 0
+#define FORWARD_FAILURE (-1)
+#define FORWARD_CONGEST (-2)
//#define PANU_DISABLED TRUE
#if (PAN_NAP_DISABLED == TRUE) && (PANU_DISABLED == TRUE)
@@ -71,6 +77,8 @@
#define asrt(s) if(!(s)) BTIF_TRACE_ERROR3("btif_pan: ## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
btpan_cb_t btpan_cb;
BD_ADDR local_addr;
@@ -85,15 +93,8 @@
static void btpan_tap_fd_signaled(int fd, int type, int flags, uint32_t user_id);
static void btpan_cleanup_conn(btpan_conn_t* conn);
static void bta_pan_callback(tBTA_PAN_EVT event, tBTA_PAN *p_data);
-/*******************************************************************************
- **
- ** Function btpan_ini
- **
- ** Description initializes the pan interface
- **
- ** Returns bt_status_t
- **
- *******************************************************************************/
+static void btu_exec_tap_fd_read(void *p_param);
+
static btpan_interface_t pan_if = {
sizeof(pan_if),
btpan_jni_init,
@@ -103,10 +104,21 @@
btpan_disconnect,
btpan_jni_cleanup
};
+
btpan_interface_t *btif_pan_get_interface()
{
return &pan_if;
}
+
+/*******************************************************************************
+ **
+ ** Function btif_pan_init
+ **
+ ** Description initializes the pan interface
+ **
+ ** Returns bt_status_t
+ **
+ *******************************************************************************/
void btif_pan_init()
{
BTIF_TRACE_DEBUG2("jni_initialized = %d, btpan_cb.enabled:%d", jni_initialized, btpan_cb.enabled);
@@ -116,6 +128,7 @@
BTIF_TRACE_DEBUG0("Enabling PAN....");
memset(&btpan_cb, 0, sizeof(btpan_cb));
btpan_cb.tap_fd = -1;
+ btpan_cb.flow = 1;
int i;
for(i = 0; i < MAX_PAN_CONNS; i++)
btpan_cleanup_conn(&btpan_cb.conns[i]);
@@ -124,6 +137,7 @@
btpan_enable(BTPAN_LOCAL_ROLE);
}
}
+
static void pan_disable()
{
if(btpan_cb.enabled)
@@ -132,12 +146,12 @@
BTA_PanDisable();
if(btpan_cb.tap_fd != -1)
{
- destroy_tap_read_thread();
btpan_tap_close(btpan_cb.tap_fd);
btpan_cb.tap_fd = -1;
}
}
}
+
void btif_pan_cleanup()
{
if(stack_initialized)
@@ -167,6 +181,7 @@
pan_disable();
jni_initialized = FALSE;
}
+
static inline int bta_role_to_btpan(int bta_pan_role)
{
int btpan_role = 0;
@@ -181,6 +196,7 @@
}
return btpan_role;
}
+
static inline int btpan_role_to_bta(int btpan_role)
{
int bta_pan_role = PAN_ROLE_INACTIVE;
@@ -195,6 +211,7 @@
}
return bta_pan_role;
}
+
static volatile int btpan_dev_local_role;
static tBTA_PAN_ROLE_INFO bta_panu_info = {PANU_SERVICE_NAME, 0, PAN_SECURITY};
static tBTA_PAN_ROLE_INFO bta_pan_nap_info = {PAN_NAP_SERVICE_NAME, 1, PAN_SECURITY};
@@ -212,11 +229,13 @@
return BT_STATUS_FAIL;
#endif
}
+
static int btpan_get_local_role()
{
BTIF_TRACE_DEBUG1("btpan_dev_local_role:%d", btpan_dev_local_role);
return btpan_dev_local_role;
}
+
static bt_status_t btpan_connect(const bt_bdaddr_t *bd_addr, int local_role, int remote_role)
{
BTIF_TRACE_DEBUG2("local_role:%d, remote_role:%d", local_role, remote_role);
@@ -226,6 +245,7 @@
BTA_PanOpen((UINT8*)bd_addr->address, bta_local_role, bta_remote_role);
return BT_STATUS_SUCCESS;
}
+
static void btif_in_pan_generic_evt(UINT16 event, char *p_param)
{
BTIF_TRACE_EVENT2("%s: event=%d", __FUNCTION__, event);
@@ -251,6 +271,7 @@
break;
}
}
+
static bt_status_t btpan_disconnect(const bt_bdaddr_t *bd_addr)
{
btpan_conn_t* conn = btpan_find_conn_addr(bd_addr->address);
@@ -264,24 +285,25 @@
}
return BT_STATUS_FAIL;
}
-static int pth = -1;
+
+static int pan_pth = -1;
void create_tap_read_thread(int tap_fd)
{
- if(pth < 0)
- {
- pth = btsock_thread_create(btpan_tap_fd_signaled, NULL);
- if(pth >= 0)
- btsock_thread_add_fd(pth, tap_fd, 0, SOCK_THREAD_FD_RD, 0);
- }
+ if(pan_pth < 0)
+ pan_pth = btsock_thread_create(btpan_tap_fd_signaled, NULL);
+ if(pan_pth >= 0)
+ btsock_thread_add_fd(pan_pth, tap_fd, 0, SOCK_THREAD_FD_RD, 0);
}
+
void destroy_tap_read_thread(void)
{
- if(pth >= 0)
+ if(pan_pth >= 0)
{
- btsock_thread_exit(pth);
- pth = -1;
+ btsock_thread_exit(pan_pth);
+ pan_pth = -1;
}
}
+
static int tap_if_up(const char *devname, BD_ADDR addr)
{
struct ifreq ifr;
@@ -354,6 +376,18 @@
return 0;
}
+
+void btpan_set_flow_control(BOOLEAN enable) {
+ if (btpan_cb.tap_fd == -1)
+ return;
+
+ btpan_cb.flow = enable;
+ if (enable) {
+ btsock_thread_add_fd(pan_pth, btpan_cb.tap_fd, 0, SOCK_THREAD_FD_RD, 0);
+ bta_dmexecutecallback(btu_exec_tap_fd_read, (void *)btpan_cb.tap_fd);
+ }
+}
+
int btpan_tap_open()
{
struct ifreq ifr;
@@ -390,6 +424,7 @@
close(fd);
return -1;
}
+
int btpan_tap_send(int tap_fd, const BD_ADDR src, const BD_ADDR dst, UINT16 proto, const char* buf,
UINT16 len, BOOLEAN ext, BOOLEAN forward)
{
@@ -423,12 +458,16 @@
return -1;
}
+
int btpan_tap_close(int fd)
{
tap_if_down(TAP_IF_NAME);
close(fd);
+ if(pan_pth >= 0)
+ btsock_thread_wakeup(pan_pth);
return 0;
}
+
btpan_conn_t * btpan_find_conn_handle(UINT16 handle)
{
int i;
@@ -437,6 +476,7 @@
return &btpan_cb.conns[i];
return NULL;
}
+
btpan_conn_t* btpan_find_conn_addr(const BD_ADDR addr)
{
int i;
@@ -445,6 +485,7 @@
return &btpan_cb.conns[i];
return NULL;
}
+
static void btpan_cleanup_conn(btpan_conn_t* conn)
{
if(conn)
@@ -456,6 +497,7 @@
conn->local_role = conn->remote_role = 0;
}
}
+
btpan_conn_t* btpan_new_conn(int handle, const BD_ADDR addr, int local_role, int remote_role )
{
int i;
@@ -485,6 +527,7 @@
p->remote_role = -1;
memset(&p->peer, 0, 6);
}
+
static inline int should_forward(tETH_HDR* hdr)
{
if(ntohs(hdr->h_proto) == ETH_P_IP || ntohs(hdr->h_proto) == ETH_P_ARP)
@@ -492,39 +535,30 @@
BTIF_TRACE_DEBUG1("unknown proto:%x", ntohs(hdr->h_proto));
return FALSE;
}
-#if BTA_PAN_INCLUDED == TRUE
-extern void bta_pan_ci_rx_write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol,
- UINT8 *p_data, UINT16 len, BOOLEAN ext);
-#else
-static void bta_pan_ci_rx_write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol,
- UINT8 *p_data, UINT16 len, BOOLEAN ext)
-{
- UNUSED(handle);
- UNUSED(dst);
- UNUSED(src);
- UNUSED(protocol);
- UNUSED(p_data);
- UNUSED(len);
- UNUSED(ext);
-}
-#endif
-static void forward_bnep(tETH_HDR* eth_hdr, char * packet, int size)
-{
+
+static int forward_bnep(tETH_HDR* eth_hdr, BT_HDR *hdr) {
int broadcast = eth_hdr->h_dest[0] & 1;
int i;
- for(i = 0; i < MAX_PAN_CONNS; i++)
- {
+
+ // Find the right connection to send this frame over.
+ for (i = 0; i < MAX_PAN_CONNS; i++) {
UINT16 handle = btpan_cb.conns[i].handle;
- if(handle != (UINT16)-1 &&
+ if (handle != (UINT16)-1 &&
(broadcast || memcmp(btpan_cb.conns[i].eth_addr, eth_hdr->h_dest, sizeof(BD_ADDR)) == 0
- || memcmp(btpan_cb.conns[i].peer, eth_hdr->h_dest, sizeof(BD_ADDR)) == 0))
- {
- BTIF_TRACE_DEBUG1("calling bta_pan_ci_rx_write, handle:%d", handle);
- bta_pan_ci_rx_write(handle, eth_hdr->h_dest, eth_hdr->h_src,
- ntohs(eth_hdr->h_proto), (UINT8*)packet, size, 0);
- break;
+ || memcmp(btpan_cb.conns[i].peer, eth_hdr->h_dest, sizeof(BD_ADDR)) == 0)) {
+ int result = PAN_WriteBuf(handle, eth_hdr->h_dest, eth_hdr->h_src, ntohs(eth_hdr->h_proto), hdr, 0);
+ switch (result) {
+ case PAN_Q_SIZE_EXCEEDED:
+ return FORWARD_CONGEST;
+ case PAN_SUCCESS:
+ return FORWARD_SUCCESS;
+ default:
+ return FORWARD_FAILURE;
+ }
}
}
+ GKI_freebuf(hdr);
+ return FORWARD_IGNORE;
}
static void bta_pan_callback_transfer(UINT16 event, char *p_param)
@@ -621,36 +655,98 @@
{
btif_transfer_context(bta_pan_callback_transfer, event, (char*)p_data, sizeof(tBTA_PAN), NULL);
}
-#define MAX_PACKET_SIZE 2000
-static void btpan_tap_fd_signaled(int fd, int type, int flags, uint32_t user_id)
-{
- char packet[MAX_PACKET_SIZE];
- tETH_HDR eth_hdr;
- UNUSED(type);
- UNUSED(user_id);
- if(flags & SOCK_THREAD_FD_EXCEPTION)
- {
- BTIF_TRACE_ERROR1("pan tap fd:%d exception", fd);
- }
- else if(flags & SOCK_THREAD_FD_RD)
- {
- /* debug("tab fd read trigged, data"); */
- int size = read(fd, packet, MAX_PACKET_SIZE);
- /* debug("tap fd read trigged, read size:%d", size); */
- memcpy(ð_hdr, &packet, sizeof(tETH_HDR));
- /* debug("eth src = %02x:%02x:%02x:%02x:%02x:%02x", */
- /* eth_hdr.h_src[0], eth_hdr.h_src[1], eth_hdr.h_src[2], eth_hdr.h_src[3], */
- /* eth_hdr.h_src[4], eth_hdr.h_src[5]); */
- /* debug("eth dest = %02x:%02x:%02x:%02x:%02x:%02x", */
- /* eth_hdr.h_dest[0], eth_hdr.h_dest[1], eth_hdr.h_dest[2], eth_hdr.h_dest[3], */
- /* eth_hdr.h_dest[4], eth_hdr.h_dest[5]); */
- //dump_bin("eth packet received", packet, size);
- if(should_forward(ð_hdr))
- {
- forward_bnep(ð_hdr, packet + sizeof(tETH_HDR), size - sizeof(tETH_HDR));
+#define IS_EXCEPTION(e) ((e) & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL))
+static void btu_exec_tap_fd_read(void *p_param) {
+ struct pollfd ufd;
+ int fd = (int)p_param;
+
+ if (fd == -1 || fd != btpan_cb.tap_fd)
+ return;
+
+ // Keep sending until someone either turns off BTIF or disables data the flow.
+ while (btif_is_enabled() && btpan_cb.flow) {
+ BT_HDR *buffer = (BT_HDR *)GKI_getpoolbuf(PAN_POOL_ID);
+ if (!buffer) {
+ BTIF_TRACE_WARNING1("%s unable to allocate buffer for packet.", __func__);
+ break;
}
- btsock_thread_add_fd(pth, fd, 0, SOCK_THREAD_FD_RD | SOCK_THREAD_ADD_FD_SYNC, 0);
+ buffer->offset = PAN_MINIMUM_OFFSET;
+ buffer->len = GKI_get_buf_size(buffer) - sizeof(BT_HDR) - buffer->offset;
+
+ UINT8 *packet = (UINT8 *)buffer + sizeof(BT_HDR) + buffer->offset;
+
+ // If we don't have an undelivered packet left over, pull one from the TAP driver.
+ // We save it in the congest_packet right away in case we can't deliver it in this
+ // attempt.
+ if (!btpan_cb.congest_packet_size) {
+ ssize_t ret = read(fd, btpan_cb.congest_packet, sizeof(btpan_cb.congest_packet));
+ switch (ret) {
+ case -1:
+ BTIF_TRACE_ERROR2("%s unable to read from driver: %s", __func__, strerror(errno));
+ GKI_freebuf(buffer);
+ return;
+ case 0:
+ BTIF_TRACE_WARNING1("%s end of file reached.", __func__);
+ GKI_freebuf(buffer);
+ return;
+ default:
+ btpan_cb.congest_packet_size = ret;
+ break;
+ }
+ }
+
+ memcpy(packet, btpan_cb.congest_packet, MIN(btpan_cb.congest_packet_size, buffer->len));
+ buffer->len = MIN(btpan_cb.congest_packet_size, buffer->len);
+
+ if (buffer->len > sizeof(tETH_HDR) && should_forward((tETH_HDR *)packet)) {
+ // Extract the ethernet header from the buffer since the PAN_WriteBuf inside
+ // forward_bnep can't handle two pointers that point inside the same GKI buffer.
+ tETH_HDR hdr;
+ memcpy(&hdr, packet, sizeof(tETH_HDR));
+
+ // Skip the ethernet header.
+ buffer->len -= sizeof(tETH_HDR);
+ buffer->offset += sizeof(tETH_HDR);
+ if (forward_bnep(&hdr, buffer) != FORWARD_CONGEST)
+ btpan_cb.congest_packet_size = 0;
+ } else {
+ BTIF_TRACE_WARNING2("%s dropping packet of length %d", __func__, buffer->len);
+ btpan_cb.congest_packet_size = 0;
+ GKI_freebuf(buffer);
+ }
+
+ // Bail out of the loop if reading from the TAP fd would block.
+ ufd.fd = fd;
+ ufd.events = POLLIN;
+ ufd.revents = 0;
+ if(poll(&ufd, 1, 0) <= 0 || IS_EXCEPTION(ufd.revents)) {
+ btsock_thread_add_fd(pan_pth, fd, 0, SOCK_THREAD_FD_RD, 0);
+ return;
+ }
}
}
+static void btif_pan_close_all_conns() {
+ int i;
+ if (!stack_initialized)
+ return;
+
+ for (i = 0; i < MAX_PAN_CONNS; ++i)
+ if (btpan_cb.conns[i].handle != -1)
+ BTA_PanClose(btpan_cb.conns[i].handle);
+}
+
+static void btpan_tap_fd_signaled(int fd, int type, int flags, uint32_t user_id) {
+ assert(btpan_cb.tap_fd == fd);
+
+ if (btpan_cb.tap_fd != fd)
+ return;
+
+ if(flags & SOCK_THREAD_FD_EXCEPTION) {
+ btpan_cb.tap_fd = -1;
+ btpan_tap_close(fd);
+ btif_pan_close_all_conns();
+ } else if(flags & SOCK_THREAD_FD_RD)
+ bta_dmexecutecallback(btu_exec_tap_fd_read, (void *)fd);
+}
diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c
old mode 100755
new mode 100644
index b2cd335..b3b6e3d
--- a/btif/src/btif_rc.c
+++ b/btif/src/btif_rc.c
@@ -180,7 +180,12 @@
static const UINT8 rc_white_addr_prefix[][3] = {
{0x94, 0xCE, 0x2C}, // Sony SBH50
- {0x30, 0x17, 0xC8} // Sony wm600
+ {0x30, 0x17, 0xC8} // Sony wm600
+};
+
+static const char* rc_white_name[] = {
+ "SBH50",
+ "MW600"
};
static void send_reject_response (UINT8 rc_handle, UINT8 label,
@@ -462,6 +467,7 @@
btif_rc_cb.rc_handle = 0;
btif_rc_cb.rc_connected = FALSE;
memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
+ memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
btif_rc_cb.rc_features = 0;
btif_rc_cb.rc_vol_label=MAX_LABEL;
btif_rc_cb.rc_volume=MAX_VOLUME;
@@ -1221,6 +1227,11 @@
tAVRC_RESPONSE avrc_rsp;
CHECK_RC_CONNECTED
BTIF_TRACE_EVENT2("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
+ if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
+ {
+ BTIF_TRACE_ERROR1("Avrcp Event id not registered: event_id = %x", event_id);
+ return BT_STATUS_NOT_READY;
+ }
memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
avrc_rsp.reg_notif.event_id = event_id;
@@ -1661,17 +1672,31 @@
static BOOLEAN dev_blacklisted_for_absolute_volume(BD_ADDR peer_dev)
{
int i;
+ char *dev_name_str = NULL;
int whitelist_size = sizeof(rc_white_addr_prefix)/sizeof(rc_white_addr_prefix[0]);
+
for (i = 0; i < whitelist_size; i++) {
if (rc_white_addr_prefix[i][0] == peer_dev[0] &&
rc_white_addr_prefix[i][1] == peer_dev[1] &&
rc_white_addr_prefix[i][2] == peer_dev[2]) {
BTIF_TRACE_DEBUG3("whitelist absolute volume for %02x:%02x:%02x",
- peer_dev[0], peer_dev[1], peer_dev[2]);
+ peer_dev[0], peer_dev[1], peer_dev[2]);
return FALSE;
}
}
- BTIF_TRACE_WARNING3("blacklist absolute volume for %02x:%02x:%02x",
- peer_dev[0], peer_dev[1], peer_dev[2]);
+
+ dev_name_str = BTM_SecReadDevName(peer_dev);
+ whitelist_size = sizeof(rc_white_name)/sizeof(char*);
+ if (dev_name_str != NULL) {
+ for (i = 0; i < whitelist_size; i++) {
+ if (strcmp(dev_name_str, rc_white_name[i]) == 0) {
+ BTIF_TRACE_DEBUG1("whitelist absolute volume for %s", dev_name_str);
+ return FALSE;
+ }
+ }
+ }
+
+ BTIF_TRACE_WARNING4("blacklist absolute volume for %02x:%02x:%02x, name = %s",
+ peer_dev[0], peer_dev[1], peer_dev[2], dev_name_str);
return TRUE;
}
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index a12c5cc..8e03c05 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -274,6 +274,8 @@
BTIF_STORAGE_PATH_REMOTE_NAME, value);
else btif_config_set_str("Local", "Adapter",
BTIF_STORAGE_KEY_ADAPTER_NAME, value);
+ /* save name immediately */
+ btif_config_save();
break;
case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
strncpy(value, (char*)prop->val, prop->len);
@@ -803,9 +805,13 @@
bdstr_t bdstr;
bd2str(remote_bd_addr, &bdstr);
BTIF_TRACE_DEBUG1("in bd addr:%s", bdstr);
- int ret = btif_config_remove("Remote", bdstr, "LinkKeyType");
- ret &= btif_config_remove("Remote", bdstr, "PinLength");
- ret &= btif_config_remove("Remote", bdstr, "LinkKey");
+ int ret = 1;
+ if(btif_config_exist("Remote", bdstr, "LinkKeyType"))
+ ret &= btif_config_remove("Remote", bdstr, "LinkKeyType");
+ if(btif_config_exist("Remote", bdstr, "PinLength"))
+ ret &= btif_config_remove("Remote", bdstr, "PinLength");
+ if(btif_config_exist("Remote", bdstr, "LinkKey"))
+ ret &= btif_config_remove("Remote", bdstr, "LinkKey");
/* write bonded info immediately */
btif_config_flush();
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
@@ -1740,8 +1746,8 @@
bd2str(remote_bd_addr, &bdstr);
- /*consider on LAP part of BDA string*/
- bdstr[8] = '\0';
+ /*consider on LAP part of BDA string*/
+ bdstr[8] = '\0';
int line_size = sizeof(linebuf);
if(btif_config_get_str("Local", BTIF_STORAGE_PATH_AUTOPAIR_BLACKLIST,
@@ -1753,3 +1759,68 @@
return FALSE;
}
+
+/*******************************************************************************
+**
+** Function btif_storage_set_dmt_support_type
+**
+** Description Sets DMT support status for a remote device
+**
+** Returns BT_STATUS_SUCCESS if config update is successful
+** BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+
+bt_status_t btif_storage_set_dmt_support_type(const bt_bdaddr_t *remote_bd_addr,
+ BOOLEAN dmt_supported)
+{
+ int ret;
+ bdstr_t bdstr = {0};
+ if(remote_bd_addr)
+ {
+ bd2str(remote_bd_addr, &bdstr);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR1("%s NULL BD Address", __FUNCTION__);
+ return BT_STATUS_FAIL;
+ }
+
+ ret = btif_config_set_int("Remote", bdstr,"DMTSupported", (int)dmt_supported);
+ return ret ? BT_STATUS_SUCCESS:BT_STATUS_FAIL;
+
+}
+
+/*******************************************************************************
+**
+** Function btif_storage_is_dmt_supported_device
+**
+** Description checks if a device supports Dual mode topology
+**
+** Returns TRUE if remote address is valid and supports DMT else FALSE
+**
+*******************************************************************************/
+
+BOOLEAN btif_storage_is_dmt_supported_device(const bt_bdaddr_t *remote_bd_addr)
+{
+ int dmt_supported = 0;
+ bdstr_t bdstr = {0};
+ if(remote_bd_addr)
+ bd2str(remote_bd_addr, &bdstr);
+
+ if(remote_bd_addr)
+ {
+ bd2str(remote_bd_addr, &bdstr);
+ }
+ else
+ {
+ BTIF_TRACE_ERROR1("%s NULL BD Address", __FUNCTION__);
+ return FALSE;
+ }
+
+ btif_config_get_int("Remote", bdstr,"DMTSupported", &dmt_supported);
+
+ return dmt_supported == 1 ? TRUE:FALSE;
+}
+
+
diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c
old mode 100755
new mode 100644
index 96685f2..12aa7a9
--- a/btif/src/btif_util.c
+++ b/btif/src/btif_util.c
@@ -85,7 +85,7 @@
{
int32_t i = 0;
for (i = 0; i < 6; i++) {
- addr->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
+ addr->address[i] = (uint8_t)strtoul(str, &str, 16);
str++;
}
return 0;
@@ -95,10 +95,10 @@
{
const uint8_t *addr = bdaddr->address;
- snprintf((char*)bdstr, sizeof(*bdstr), "%02x:%02x:%02x:%02x:%02x:%02x",
+ sprintf(*bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]);
- return (char *)bdstr;
+ return *bdstr;
}
UINT32 devclass2uint(DEV_CLASS dev_class)
diff --git a/gki/Android.mk b/gki/Android.mk
index e9ad13a..2e8ef56 100644
--- a/gki/Android.mk
+++ b/gki/Android.mk
@@ -9,7 +9,7 @@
$(LOCAL_PATH)/../utils/include \
$(bdroid_C_INCLUDES) \
-LOCAL_CFLAGS += -Werror -Wno-error=unused-parameter $(bdroid_CFLAGS)
+LOCAL_CFLAGS += -Wno-error=unused-parameter $(bdroid_CFLAGS) -std=c99
ifeq ($(BOARD_HAVE_BLUETOOTH_BCM),true)
LOCAL_CFLAGS += \
@@ -27,5 +27,6 @@
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libcutils libc
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MULTILIB := 32
include $(BUILD_STATIC_LIBRARY)
diff --git a/gki/common/gki_common.h b/gki/common/gki_common.h
index ff5a675..2fadcdc 100644
--- a/gki/common/gki_common.h
+++ b/gki/common/gki_common.h
@@ -45,6 +45,7 @@
#define GKI_ERROR_ADDR_NOT_IN_BUF 0xFFF5
#define GKI_ERROR_OUT_OF_BUFFERS 0xFFF4
#define GKI_ERROR_GETPOOLBUF_BAD_QID 0xFFF3
+#define GKI_ERROR_TIMER_LIST_CORRUPTED 0xFFF2
/********************************************************************
diff --git a/gki/common/gki_inet.h b/gki/common/gki_inet.h
deleted file mode 100644
index 6640931..0000000
--- a/gki/common/gki_inet.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2002-2012 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 GKI_INET_H
-#define GKI_INET_H
-
-#include "data_types.h"
-
-#define htons ntohs
-#define htonl ntohl
-
-#define htonets nettohs
-#define htonetl nettohl
-
-#if BIG_ENDIAN == TRUE
-#define ntohs(n) (n)
-#define ntohl(n) (n)
-#define ntoh6(n) (n)
-
-#define nettohs(n) (n)
-#define nettohl(n) (n)
-#else
-extern UINT16 ntohs(UINT16 n);
-extern UINT32 ntohl(UINT32 n);
-extern UINT8 *ntoh6(UINT8 *p);
-
-#define nettohs(n) ((UINT16)((((n) << 8) & 0xff00) | (((n) >> 8) & 0x00ff)))
-#define nettohl(n) ((((n) & 0x000000ff) << 24) | (((n) << 8) & 0x00ff0000) | \
- (((n) >> 8) & 0x0000ff00) | (((n) >> 24) & 0x000000ff))
-#endif
-
-#endif /* GKI_INET_H */
-
diff --git a/gki/common/gki_time.c b/gki/common/gki_time.c
index a9af8fa..ceda9ad 100644
--- a/gki/common/gki_time.c
+++ b/gki/common/gki_time.c
@@ -841,8 +841,19 @@
}
else /* This entry needs to be inserted before the last entry */
{
- /* Find the entry that the new one needs to be inserted in front of */
p_temp = p_timer_listq->p_first;
+
+ if (p_temp == NULL)
+ {
+ /* list is corrupted, exit to avoid crash */
+ GKI_TRACE_ERROR_0("GKI_add_to_timer_list : Timerlist Q is empty");
+ GKI_exception(GKI_ERROR_TIMER_LIST_CORRUPTED, "*** "
+ "GKI_add_to_timer_list(): timer list corrupted! ***");
+ return;
+ }
+ /* Find the entry that the new one needs to be inserted in front of
+ * as last_ticks is the expiry value of p_last, it should be inserted
+ * BEFORE p_last. otherwise list is probably corrupted! */
while (p_tle->ticks > p_temp->ticks)
{
/* Update the tick value if looking at an unexpired entry */
diff --git a/gki/ulinux/data_types.h b/gki/ulinux/data_types.h
index 33b8bb7..e9d5097 100644
--- a/gki/ulinux/data_types.h
+++ b/gki/ulinux/data_types.h
@@ -19,55 +19,46 @@
#ifndef DATA_TYPES_H
#define DATA_TYPES_H
+#include <stdint.h>
+#include <stdbool.h>
+
#ifndef NULL
-#define NULL 0
+# define NULL (void *)0
#endif
#ifndef FALSE
-#define FALSE 0
+# define FALSE false
#endif
-typedef unsigned char UINT8;
-typedef unsigned short UINT16;
-typedef unsigned long UINT32;
-typedef unsigned long long UINT64;
+#ifndef TRUE
+# define TRUE true
+#endif
-typedef signed long INT32;
-typedef signed char INT8;
-typedef signed short INT16;
-typedef unsigned char BOOLEAN;
+typedef uint8_t UINT8;
+typedef uint16_t UINT16;
+typedef uint32_t UINT32;
+typedef uint64_t UINT64;
+typedef int8_t INT8;
+typedef int16_t INT16;
+typedef int32_t INT32;
+typedef bool BOOLEAN;
typedef UINT32 TIME_STAMP;
-#ifndef TRUE
-#define TRUE (!FALSE)
-#endif
-
-typedef unsigned char UBYTE;
-
#ifdef __arm
-#define PACKED __packed
-#define INLINE __inline
+# define PACKED __packed
+# define INLINE __inline
#else
-#define PACKED
-#define INLINE
+# define PACKED
+# define INLINE
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN FALSE
#endif
-#define UINT16_LOW_BYTE(x) ((x) & 0xff)
-#define UINT16_HI_BYTE(x) ((x) >> 8)
-
-
-#define BCM_STRCAT_S(x1,x2,x3) strcat((x1),(x3))
-#define BCM_STRNCAT_S(x1,x2,x3,x4) strncat((x1),(x3),(x4))
#define BCM_STRCPY_S(x1,x2,x3) strcpy((x1),(x3))
#define BCM_STRNCPY_S(x1,x2,x3,x4) strncpy((x1),(x3),(x4))
-
-
#endif
-
diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c
old mode 100755
new mode 100644
index a66a32f..e6f45f4
--- a/gki/ulinux/gki_ulinux.c
+++ b/gki/ulinux/gki_ulinux.c
@@ -29,7 +29,6 @@
#include <stdarg.h>
#include <errno.h>
#include <sys/times.h>
-#include <hardware/bluetooth.h>
#include <pthread.h> /* must be 1st header defined */
#include <time.h>
@@ -75,6 +74,8 @@
#define UNLOCK(m) pthread_mutex_unlock(&m)
#define INIT(m) pthread_mutex_init(&m, NULL)
+#define WAKE_LOCK_ID "brcm_btld"
+#define PARTIAL_WAKE_LOCK 1
#if GKI_DYNAMIC_MEMORY == FALSE
tGKI_CB gki_cb;
@@ -96,8 +97,6 @@
** Local type definitions
******************************************************************************/
-#define pthread_cond_timedwait_monotonic pthread_cond_timedwait
-
typedef struct
{
UINT8 task_id; /* GKI task id */
@@ -112,7 +111,6 @@
int g_GkiTimerWakeLockOn = 0;
gki_pthread_info_t gki_pthread_info[GKI_MAX_TASKS];
-bt_wakelock_callback config_wakelock_callback = NULL;
/*****************************************************************************
** Static functions
@@ -122,33 +120,13 @@
** Externs
******************************************************************************/
-
+extern int acquire_wake_lock(int lock, const char* id);
+extern int release_wake_lock(const char* id);
/*****************************************************************************
** Functions
******************************************************************************/
-/* send a given byte into the wakelock pipe */
-static void wakelock_op_gki(unsigned char op)
-{
- if (!config_wakelock_callback)
- GKI_ERROR_LOG("Cannot perform wakelock operation with no callback\n");
- else
- config_wakelock_callback(op);
-}
-
-/* release a wakelock by sending a zero down the pipe */
-static void release_wake_lock_gki(void)
-{
- wakelock_op_gki(0);
-}
-
-/* acquire a wakelock by sending a one down the pipe */
-static void acquire_wake_lock_gki(void)
-{
- wakelock_op_gki(1);
-}
-
/*****************************************************************************
**
@@ -286,8 +264,12 @@
gki_cb.com.OSWaitEvt[task_id] = 0;
/* Initialize mutex and condition variable objects for events and timeouts */
+ pthread_condattr_t cond_attr;
+ pthread_condattr_init(&cond_attr);
+ pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
+
pthread_mutex_init(&gki_cb.os.thread_evt_mutex[task_id], NULL);
- pthread_cond_init (&gki_cb.os.thread_evt_cond[task_id], NULL);
+ pthread_cond_init (&gki_cb.os.thread_evt_cond[task_id], &cond_attr);
pthread_mutex_init(&gki_cb.os.thread_timeout_mutex[task_id], NULL);
pthread_cond_init (&gki_cb.os.thread_timeout_cond[task_id], NULL);
@@ -547,8 +529,8 @@
#endif
if (g_GkiTimerWakeLockOn)
{
- GKI_TRACE("GKI_shutdown : release_wake_lock_gki()");
- release_wake_lock_gki();
+ GKI_TRACE("GKI_shutdown : release_wake_lock(brcm_btld)");
+ release_wake_lock(WAKE_LOCK_ID);
g_GkiTimerWakeLockOn = 0;
}
}
@@ -589,14 +571,14 @@
GKI_TIMER_TRACE(">>> STOP GKI_timer_update(), wake_lock_count:%d", --wake_lock_count);
- release_wake_lock_gki();
+ release_wake_lock(WAKE_LOCK_ID);
g_GkiTimerWakeLockOn = 0;
}
}
else
{
/* restart GKI_timer_update() loop */
- acquire_wake_lock_gki();
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
g_GkiTimerWakeLockOn = 1;
*p_run_cond = GKI_TIMER_TICK_RUN_COND;
@@ -964,9 +946,8 @@
}
abstime.tv_sec += sec;
- pthread_cond_timedwait_monotonic(&gki_cb.os.thread_evt_cond[rtask],
+ pthread_cond_timedwait(&gki_cb.os.thread_evt_cond[rtask],
&gki_cb.os.thread_evt_mutex[rtask], &abstime);
-
}
else
{
diff --git a/hci/Android.mk b/hci/Android.mk
index 0d3d56d..bbad3e9 100644
--- a/hci/Android.mk
+++ b/hci/Android.mk
@@ -29,6 +29,8 @@
endif
+LOCAL_CFLAGS += -std=c99
+
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/../utils/include \
diff --git a/hci/src/btsnoop.c b/hci/src/btsnoop.c
old mode 100755
new mode 100644
diff --git a/hci/src/hci_mct.c b/hci/src/hci_mct.c
old mode 100755
new mode 100644
diff --git a/hci/src/utils.c b/hci/src/utils.c
index bfcf724..85304fa 100644
--- a/hci/src/utils.c
+++ b/hci/src/utils.c
@@ -65,6 +65,7 @@
*******************************************************************************/
void utils_cleanup (void)
{
+ pthread_mutex_destroy(&utils_mutex);
}
/*******************************************************************************
diff --git a/include/bt_target.h b/include/bt_target.h
index 7e77164..3510ce9 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -102,10 +102,6 @@
#define SMP_HOST_ENCRYPT_INCLUDED FALSE
#endif
-#ifndef SAP_INCLUDED
-#define SAP_INCLUDED FALSE
-#endif
-
#ifndef SBC_NO_PCM_CPY_OPTION
#define SBC_NO_PCM_CPY_OPTION FALSE
#endif
@@ -118,34 +114,6 @@
#define BTA_AG_INCLUDED TRUE
#endif
-#ifndef BTA_CT_INCLUDED
-#define BTA_CT_INCLUDED FALSE
-#endif
-
-#ifndef BTA_CG_INCLUDED
-#define BTA_CG_INCLUDED FALSE
-#endif
-
-#ifndef BTA_DG_INCLUDED
-#define BTA_DG_INCLUDED FALSE
-#endif
-
-#ifndef BTA_FT_INCLUDED
-#define BTA_FT_INCLUDED FALSE
-#endif
-
-#ifndef BTA_OP_INCLUDED
-#define BTA_OP_INCLUDED FALSE
-#endif
-
-#ifndef BTA_PR_INCLUDED
-#define BTA_PR_INCLUDED FALSE
-#endif
-
-#ifndef BTA_SS_INCLUDED
-#define BTA_SS_INCLUDED FALSE
-#endif
-
#ifndef BTA_DM_INCLUDED
#define BTA_DM_INCLUDED TRUE
#endif
@@ -171,14 +139,6 @@
#define BTA_FS_INCLUDED TRUE
#endif
-#ifndef BTA_AC_INCLUDED
-#define BTA_AC_INCLUDED FALSE
-#endif
-
-#ifndef BTA_HD_INCLUDED
-#define BTA_HD_INCLUDED FALSE
-#endif
-
#ifndef BTA_HH_INCLUDED
#define BTA_HH_INCLUDED TRUE
#endif
@@ -199,68 +159,8 @@
#define BTA_AV_INCLUDED TRUE
#endif
-#ifndef BTA_AV_VDP_INCLUDED
-#define BTA_AV_VDP_INCLUDED FALSE
-#endif
-
-#ifndef BTA_AVK_INCLUDED
-#define BTA_AVK_INCLUDED FALSE
-#endif
-
-#ifndef BTA_PBS_INCLUDED
-#define BTA_PBS_INCLUDED FALSE
-#endif
-
-#ifndef BTA_PBC_INCLUDED
-#define BTA_PBC_INCLUDED FALSE
-#endif
-
-#ifndef BTA_FM_INCLUDED
-#define BTA_FM_INCLUDED FALSE
-#endif
-
-#ifndef BTA_FM_DEBUG
-#define BTA_FM_DEBUG FALSE
-#endif
-
-#ifndef BTA_FMTX_INCLUDED
-#define BTA_FMTX_INCLUDED FALSE
-#endif
-
-#ifndef BTA_FMTX_DEBUG
-#define BTA_FMTX_DEBUG FALSE
-#endif
-
-#ifndef BTA_FMTX_FMRX_SWITCH_WORKAROUND
-#define BTA_FMTX_FMRX_SWITCH_WORKAROUND FALSE
-#endif
-
-#ifndef BTA_FMTX_US_FCC_RULES
-#define BTA_FMTX_US_FCC_RULES FALSE
-#endif
-
-#ifndef BTA_HS_INCLUDED
-#define BTA_HS_INCLUDED FALSE
-#endif
-
-#ifndef BTA_MSE_INCLUDED
-#define BTA_MSE_INCLUDED FALSE
-#endif
-
-#ifndef BTA_MCE_INCLUDED
-#define BTA_MCE_INCLUDED FALSE
-#endif
-
-#ifndef BTA_PLAYBACK_INCLUDED
-#define BTA_PLAYBACK_INCLUDED FALSE
-#endif
-
-#ifndef BTA_SSR_INCLUDED
-#define BTA_SSR_INCLUDED FALSE
-#endif
-
-#ifndef BTA_JV_INCLUDED
-#define BTA_JV_INCLUDED FALSE
+#ifndef BTA_GATT_INCLUDED
+#define BTA_GATT_INCLUDED TRUE
#endif
#ifndef BTA_DISABLE_DELAY
@@ -397,10 +297,6 @@
#define BTA_DM_SDP_DB_SIZE 8000
#endif
-#ifndef FTS_REJECT_INVALID_OBEX_SET_PATH_REQ
-#define FTS_REJECT_INVALID_OBEX_SET_PATH_REQ FALSE
-#endif
-
#ifndef HL_INCLUDED
#define HL_INCLUDED TRUE
#endif
@@ -421,8 +317,6 @@
-/* #define BYPASS_AVDATATRACE */
-
/******************************************************************************
**
** Platform-Specific
@@ -1026,7 +920,7 @@
/* The number of SCO links. */
#ifndef BTM_MAX_SCO_LINKS
-#define BTM_MAX_SCO_LINKS 2
+#define BTM_MAX_SCO_LINKS 3
#endif
/* The preferred type of SCO links (2-eSCO, 0-SCO). */
@@ -1130,16 +1024,6 @@
#define BTM_MAX_VSE_CALLBACKS 3
#endif
-/* Number of streams for dual stack */
-#ifndef BTM_SYNC_INFO_NUM_STR
-#define BTM_SYNC_INFO_NUM_STR 2
-#endif
-
-/* Number of streams for dual stack in BT Controller */
-#ifndef BTM_SYNC_INFO_NUM_STR_BTC
-#define BTM_SYNC_INFO_NUM_STR_BTC 2
-#endif
-
/******************************************
** Lisbon Features
*******************************************/
@@ -1403,12 +1287,24 @@
#define BLE_INCLUDED TRUE
#endif
+#ifndef BLE_ANDROID_CONTROLLER_SCAN_FILTER
+#define BLE_ANDROID_CONTROLLER_SCAN_FILTER TRUE
+#endif
+
#ifndef LOCAL_BLE_CONTROLLER_ID
#define LOCAL_BLE_CONTROLLER_ID (1)
#endif
-#ifndef BTM_BLE_PRIVACY_SPT
-#define BTM_BLE_PRIVACY_SPT TRUE
+#ifndef BLE_PRIVACY_SPT
+#define BLE_PRIVACY_SPT TRUE
+#endif
+
+#ifndef BLE_MULTI_ADV_INCLUDED
+#define BLE_MULTI_ADV_INCLUDED TRUE
+#endif
+
+#ifndef BLE_VND_INCLUDED
+#define BLE_VND_INCLUDED TRUE
#endif
/******************************************************************************
@@ -1428,6 +1324,12 @@
#error "can't have GATT without BLE"
#endif
+#ifndef BLE_LLT_INCLUDED
+#define BLE_LLT_INCLUDED TRUE
+#endif
+#ifndef BTM_DUMO_ADDR_CENTRAL_ENABLED
+#define BTM_DUMO_ADDR_CENTRAL_ENABLED FALSE
+#endif
#ifndef ATT_INCLUDED
#define ATT_INCLUDED TRUE
#endif
@@ -1445,7 +1347,7 @@
#endif
#ifndef BLE_PERIPHERAL_MODE_SUPPORT
-#define BLE_PERIPHERAL_MODE_SUPPORT FALSE
+#define BLE_PERIPHERAL_MODE_SUPPORT TRUE
#endif
#ifndef BLE_PERIPHERAL_DISPLAYONLY
@@ -1611,7 +1513,7 @@
/* The MTU size for the L2CAP configuration. */
#ifndef SDP_MTU_SIZE
-#define SDP_MTU_SIZE 256
+#define SDP_MTU_SIZE 672
#endif
/* The flush timeout for the L2CAP configuration. */
diff --git a/main/Android.mk b/main/Android.mk
index 5230b32..a1f0abb 100644
--- a/main/Android.mk
+++ b/main/Android.mk
@@ -38,6 +38,7 @@
../btif/src/btif_sock_util.c \
../btif/src/btif_pan.c \
../btif/src/btif_gatt.c \
+ ../btif/src/btif_gatt_multi_adv_util.c \
../btif/src/btif_gatt_client.c \
../btif/src/btif_gatt_server.c \
../btif/src/btif_gatt_util.c \
@@ -92,7 +93,7 @@
$(LOCAL_PATH)/../btif/include \
$(LOCAL_PATH)/../btif/co \
$(LOCAL_PATH)/../hci/include\
- $(LOCAL_PATH)/../brcm/include \
+ $(LOCAL_PATH)/../vnd/include \
$(LOCAL_PATH)/../embdrv/sbc/encoder/include \
$(LOCAL_PATH)/../audio_a2dp_hw \
$(LOCAL_PATH)/../utils/include \
@@ -100,6 +101,7 @@
external/tinyxml2
LOCAL_CFLAGS += -DBUILDCFG $(bdroid_CFLAGS) -Werror -Wno-error=maybe-uninitialized -Wno-error=uninitialized -Wno-error=unused-parameter
+LOCAL_CONLYFLAGS := -std=c99
ifeq ($(TARGET_PRODUCT), full_crespo)
LOCAL_CFLAGS += -DTARGET_CRESPO
@@ -133,5 +135,6 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_REQUIRED_MODULES := libbt-hci libbt-vendor bt_stack.conf bt_did.conf auto_pair_devlist.conf
+LOCAL_MULTILIB := 32
include $(BUILD_SHARED_LIBRARY)
diff --git a/main/bte_main.c b/main/bte_main.c
index cf21456..7395481 100644
--- a/main/bte_main.c
+++ b/main/bte_main.c
@@ -198,12 +198,12 @@
lpm_enabled = FALSE;
- bte_hci_enable();
-
GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,
(UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),
sizeof(bte_btu_stack));
+ bte_hci_enable();
+
GKI_run(0);
}
@@ -641,11 +641,19 @@
APPL_TRACE_DEBUG1("HC alloc size=%d", size);
*/
+ /* Requested buffer size cannot exceed GKI_MAX_BUF_SIZE. */
+ if (size > GKI_MAX_BUF_SIZE)
+ {
+ APPL_TRACE_ERROR2("HCI DATA SIZE %d greater than MAX %d",
+ size, GKI_MAX_BUF_SIZE);
+ return NULL;
+ }
+
p_hdr = (BT_HDR *) GKI_getbuf ((UINT16) size);
if (p_hdr == NULL)
{
- APPL_TRACE_WARNING0("alloc returns NO BUFFER!");
+ APPL_TRACE_WARNING1("alloc returns NO BUFFER! (sz %d)", size);
}
return ((char *) p_hdr);
diff --git a/stack/Android.mk b/stack/Android.mk
old mode 100755
new mode 100644
index f00daff..fd76ed8
--- a/stack/Android.mk
+++ b/stack/Android.mk
@@ -17,6 +17,8 @@
$(LOCAL_PATH)/sdp \
$(LOCAL_PATH)/smp \
$(LOCAL_PATH)/srvc \
+ $(LOCAL_PATH)/../vnd/include \
+ $(LOCAL_PATH)/../vnd/ble \
$(LOCAL_PATH)/../include \
$(LOCAL_PATH)/../gki/common \
$(LOCAL_PATH)/../gki/ulinux \
@@ -26,11 +28,10 @@
$(LOCAL_PATH)/../ctrlr/include \
$(LOCAL_PATH)/../bta/include \
$(LOCAL_PATH)/../bta/sys \
- $(LOCAL_PATH)/../brcm/include \
$(LOCAL_PATH)/../utils/include \
$(bdroid_C_INCLUDES) \
-LOCAL_CFLAGS += $(bdroid_CFLAGS)
+LOCAL_CFLAGS += $(bdroid_CFLAGS) -std=c99
ifeq ($(BOARD_HAVE_BLUETOOTH_BCM),true)
LOCAL_CFLAGS += \
@@ -64,6 +65,7 @@
./btm/btm_main.c \
./btm/btm_dev.c \
./btm/btm_ble_gap.c \
+ ./btm/btm_ble_multi_adv.c \
./btm/btm_acl.c \
./btm/btm_sco.c \
./btm/btm_pm.c \
@@ -143,11 +145,13 @@
./gap/gap_api.c \
./gap/gap_ble.c \
./gap/gap_conn.c \
- ./gap/gap_utils.c
+ ./gap/gap_utils.c \
+ ../vnd/ble/vendor_ble.c
LOCAL_MODULE := libbt-brcm_stack
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_SHARED_LIBRARIES := libcutils libc
+LOCAL_MULTILIB := 32
include $(BUILD_STATIC_LIBRARY)
diff --git a/stack/avdt/avdt_l2c.c b/stack/avdt/avdt_l2c.c
index 2256a90..943a3cf 100644
--- a/stack/avdt/avdt_l2c.c
+++ b/stack/avdt/avdt_l2c.c
@@ -70,7 +70,8 @@
** Returns void
**
*******************************************************************************/
-static void avdt_sec_check_complete_term (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+ void *p_ref_data, UINT8 res)
{
tAVDT_CCB *p_ccb = NULL;
tL2CAP_CFG_INFO cfg;
@@ -92,7 +93,7 @@
if (res == BTM_SUCCESS)
{
- /* Send response to the L2CAP layer. */
+ /* Send response to the L2CAP layer. */
L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK);
/* store idx in LCID table, store LCID in routing table */
@@ -127,7 +128,8 @@
** Returns void
**
*******************************************************************************/
-static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
+ void *p_ref_data, UINT8 res)
{
tAVDT_CCB *p_ccb = NULL;
tL2CAP_CFG_INFO cfg;
diff --git a/stack/avrc/avrc_api.c b/stack/avrc/avrc_api.c
old mode 100755
new mode 100644
index c572f94..09f167a
--- a/stack/avrc/avrc_api.c
+++ b/stack/avrc/avrc_api.c
@@ -528,7 +528,7 @@
tAVRC_MSG msg;
UINT8 *p_data;
UINT8 *p_begin;
- BOOLEAN drop = FALSE;
+ UINT8 drop = 0;
BOOLEAN free = TRUE;
BT_HDR *p_rsp = NULL;
UINT8 *p_rsp_data;
diff --git a/stack/avrc/avrc_bld_tg.c b/stack/avrc/avrc_bld_tg.c
old mode 100755
new mode 100644
diff --git a/stack/avrc/avrc_int.h b/stack/avrc/avrc_int.h
old mode 100755
new mode 100644
diff --git a/stack/avrc/avrc_opt.c b/stack/avrc/avrc_opt.c
old mode 100755
new mode 100644
diff --git a/stack/avrc/avrc_pars_ct.c b/stack/avrc/avrc_pars_ct.c
old mode 100755
new mode 100644
diff --git a/stack/avrc/avrc_pars_tg.c b/stack/avrc/avrc_pars_tg.c
old mode 100755
new mode 100644
diff --git a/stack/avrc/avrc_sdp.c b/stack/avrc/avrc_sdp.c
old mode 100755
new mode 100644
diff --git a/stack/avrc/avrc_utils.c b/stack/avrc/avrc_utils.c
old mode 100755
new mode 100644
diff --git a/stack/bnep/bnep_int.h b/stack/bnep/bnep_int.h
index 528c809..0c435ef 100644
--- a/stack/bnep/bnep_int.h
+++ b/stack/bnep/bnep_int.h
@@ -234,9 +234,12 @@
extern void bnep_send_conn_responce (tBNEP_CONN *p_bcb, UINT16 resp_code);
extern void bnep_process_setup_conn_req (tBNEP_CONN *p_bcb, UINT8 *p_setup, UINT8 len);
extern void bnep_process_setup_conn_responce (tBNEP_CONN *p_bcb, UINT8 *p_setup);
-extern UINT8 *bnep_process_control_packet (tBNEP_CONN *p_bcb, UINT8 *p, UINT16 *len, BOOLEAN is_ext);
-extern void bnep_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 result);
-extern tBNEP_RESULT bnep_is_packet_allowed (tBNEP_CONN *p_bcb, BD_ADDR p_dest_addr, UINT16 protocol, BOOLEAN fw_ext_present, UINT8 *p_data);
+extern UINT8 *bnep_process_control_packet (tBNEP_CONN *p_bcb, UINT8 *p, UINT16 *len,
+ BOOLEAN is_ext);
+extern void bnep_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
+ void *p_ref_data, UINT8 result);
+extern tBNEP_RESULT bnep_is_packet_allowed (tBNEP_CONN *p_bcb, BD_ADDR p_dest_addr, UINT16 protocol,
+ BOOLEAN fw_ext_present, UINT8 *p_data);
extern UINT32 bnep_get_uuid32 (tBT_UUID *src_uuid);
extern void bnep_dump_status (void);
diff --git a/stack/bnep/bnep_utils.c b/stack/bnep/bnep_utils.c
index 0a8fd6d..faf808b 100644
--- a/stack/bnep/bnep_utils.c
+++ b/stack/bnep/bnep_utils.c
@@ -1209,12 +1209,14 @@
** Returns void
**
*******************************************************************************/
-void bnep_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 result)
+void bnep_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
+ void *p_ref_data, UINT8 result)
{
tBNEP_CONN *p_bcb = (tBNEP_CONN *)p_ref_data;
UINT16 resp_code = BNEP_SETUP_CONN_OK;
BOOLEAN is_role_change;
UNUSED(bd_addr);
+ UNUSED(trasnport);
BNEP_TRACE_EVENT1 ("BNEP security callback returned result %d", result);
if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index 49ace6e..026330c 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -131,11 +131,14 @@
**
** Description This function returns the FIRST acl_db entry for the passed BDA.
**
+** Parameters bda : BD address of the remote device
+** transport : Physical transport used for ACL connection (BR/EDR or LE)
+**
** Returns Returns pointer to the ACL DB for the requested BDA if found.
** NULL if not found.
**
*******************************************************************************/
-tACL_CONN *btm_bda_to_acl (BD_ADDR bda)
+tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport)
{
tACL_CONN *p = &btm_cb.acl_db[0];
UINT16 xx;
@@ -143,7 +146,11 @@
{
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++)
{
- if ((p->in_use) && (!memcmp (p->remote_addr, bda, BD_ADDR_LEN)))
+ if ((p->in_use) && (!memcmp (p->remote_addr, bda, BD_ADDR_LEN))
+#if BLE_INCLUDED == TRUE
+ && p->transport == transport
+#endif
+ )
{
BTM_TRACE_DEBUG0 ("btm_bda_to_acl found");
return(p);
@@ -181,7 +188,7 @@
return(xx);
}
-#if BTM_BLE_PRIVACY_SPT == TRUE
+#if BLE_PRIVACY_SPT == TRUE
/*******************************************************************************
**
** Function btm_ble_get_acl_remote_addr
@@ -247,24 +254,24 @@
**
*******************************************************************************/
void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
- UINT16 hci_handle, UINT8 link_role, UINT8 is_le_link)
+ UINT16 hci_handle, UINT8 link_role, tBT_TRANSPORT transport)
{
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
UINT8 yy;
tACL_CONN *p;
UINT8 xx;
- BTM_TRACE_DEBUG3 ("btm_acl_created hci_handle=%d link_role=%d is_le_link=%d",
- hci_handle,link_role, is_le_link);
+ BTM_TRACE_DEBUG3 ("btm_acl_created hci_handle=%d link_role=%d transport=%d",
+ hci_handle,link_role, transport);
/* Ensure we don't have duplicates */
- p = btm_bda_to_acl(bda);
+ p = btm_bda_to_acl(bda, transport);
if (p != (tACL_CONN *)NULL)
{
p->hci_handle = hci_handle;
p->link_role = link_role;
btm_save_remote_device_role(bda, link_role);
#if BLE_INCLUDED == TRUE
- p->is_le_link = is_le_link;
+ p->transport = transport;
#endif
BTM_TRACE_DEBUG6 ("Duplicate btm_acl_created: RemBdAddr: %02x%02x%02x%02x%02x%02x",
bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
@@ -284,14 +291,23 @@
p->link_up_issued = FALSE;
#if BLE_INCLUDED == TRUE
- p->is_le_link = is_le_link;
-
- if (is_le_link)
+ p->transport = transport;
+ if (transport == BT_TRANSPORT_LE)
{
- p->conn_addr_type = BLE_ADDR_PUBLIC;
- BTM_GetLocalDeviceAddr(p->conn_addr);
+#if ( BLE_PRIVACY_SPT == TRUE )
+ /*allow central device to use random address for now by skipping the role check */
+ if (btm_cb.ble_ctr_cb.privacy /* && p->link_role == HCI_ROLE_SLAVE */)
+ {
+ p->conn_addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
+ memcpy(p->conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
+ }
+ else
+#endif
+ {
+ 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;
@@ -311,7 +327,7 @@
memcpy (p->remote_name, bdn, BTM_MAX_REM_BD_NAME_LEN);
/* if BR/EDR do something more */
- if (!is_le_link)
+ if (transport == BT_TRANSPORT_BR_EDR)
{
btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
btsnd_hcic_rmt_ver_req (p->hci_handle);
@@ -325,7 +341,7 @@
}
#endif
- if (p_dev_rec && !is_le_link)
+ if (p_dev_rec && !(transport == BT_TRANSPORT_LE))
{
/* If remote features already known, copy them and continue connection setup */
if ((p_dev_rec->num_read_pages) &&
@@ -353,9 +369,9 @@
#if (BLE_INCLUDED == TRUE)
/* If here, features are not known yet */
- if (p_dev_rec && is_le_link)
+ if (p_dev_rec && transport == BT_TRANSPORT_LE)
{
-#if BTM_BLE_PRIVACY_SPT == TRUE
+#if BLE_PRIVACY_SPT == TRUE
btm_ble_get_acl_remote_addr (p_dev_rec, p->active_remote_addr,
&p->active_remote_addr_type);
#endif
@@ -417,7 +433,7 @@
** Returns void
**
*******************************************************************************/
-void btm_acl_removed (BD_ADDR bda)
+void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport)
{
tACL_CONN *p;
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
@@ -428,7 +444,7 @@
#endif
BTM_TRACE_DEBUG0 ("btm_acl_removed");
- p = btm_bda_to_acl(bda);
+ p = btm_bda_to_acl(bda, transport);
if (p != (tACL_CONN *)NULL)
{
p->in_use = FALSE;
@@ -447,22 +463,29 @@
{
evt_data.event = BTM_BL_DISCN_EVT;
evt_data.discn.p_bda = bda;
-
+#if BLE_INCLUDED == TRUE
+ evt_data.discn.handle = p->hci_handle;
+ evt_data.discn.transport = p->transport;
+#endif
(*btm_cb.p_bl_changed_cb)(&evt_data);
}
btm_acl_update_busy_level (BTM_BLI_ACL_DOWN_EVT);
#else
if (btm_cb.p_acl_changed_cb)
+#if BLE_INCLUDED == TRUE
+ (*btm_cb.p_acl_changed_cb) (bda, NULL, NULL, NULL, FALSE, p->hci_handle, p->transport);
+#else
(*btm_cb.p_acl_changed_cb) (bda, NULL, NULL, NULL, FALSE);
#endif
+#endif
}
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
- BTM_TRACE_DEBUG4 ("acl hci_handle=%d is_le_link=%d connectable_mode=0x%0x link_role=%d",
+ BTM_TRACE_DEBUG4 ("acl hci_handle=%d transport=%d connectable_mode=0x%0x link_role=%d",
p->hci_handle,
- p->is_le_link,
+ p->transport,
btm_cb.ble_ctr_cb.inq_var.connectable_mode,
p->link_role);
@@ -470,14 +493,14 @@
if ( p_dev_rec)
{
BTM_TRACE_DEBUG1("before update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
- if (p->is_le_link)
+ if (p->transport == BT_TRANSPORT_LE)
{
BTM_TRACE_DEBUG0("LE link down");
- p_dev_rec->sec_flags &= ~(BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
- if ( (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) == 0)
+ p_dev_rec->sec_flags &= ~(BTM_SEC_LE_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
+ if ( (p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_KNOWN) == 0)
{
BTM_TRACE_DEBUG0("Not Bonded");
- p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHENTICATED | BTM_SEC_LINK_KEY_AUTHED);
+ p_dev_rec->sec_flags &= ~(BTM_SEC_LE_LINK_KEY_AUTHED | BTM_SEC_LE_AUTHENTICATED);
}
else
{
@@ -545,6 +568,7 @@
tBTM_BL_UPDATE_DATA evt;
UINT8 busy_level;
BTM_TRACE_DEBUG0 ("btm_acl_update_busy_level");
+ BOOLEAN old_inquiry_state = btm_cb.is_inquiry;
switch (event)
{
case BTM_BLI_ACL_UP_EVT:
@@ -594,7 +618,7 @@
else
busy_level = (UINT8)btm_cb.num_acl;
- if (busy_level != btm_cb.busy_level)
+ if ((busy_level != btm_cb.busy_level) ||(old_inquiry_state != btm_cb.is_inquiry))
{
evt.event = BTM_BL_UPDATE_EVT;
evt.busy_level = busy_level;
@@ -623,7 +647,7 @@
{
tACL_CONN *p;
BTM_TRACE_DEBUG0 ("BTM_GetRole");
- if ((p = btm_bda_to_acl(remote_bd_addr)) == NULL)
+ if ((p = btm_bda_to_acl(remote_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
*p_role = BTM_ROLE_UNDEFINED;
return(BTM_UNKNOWN_ADDR);
@@ -686,7 +710,7 @@
return(BTM_BUSY);
}
- if ((p = btm_bda_to_acl(remote_bd_addr)) == NULL)
+ if ((p = btm_bda_to_acl(remote_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
return(BTM_UNKNOWN_ADDR);
/* Finished if already in desired role */
@@ -811,7 +835,7 @@
tBTM_PM_PWR_MD settings;
#endif
BTM_TRACE_DEBUG0 ("BTM_ChangeLinkKey");
- if ((p = btm_bda_to_acl(remote_bd_addr)) == NULL)
+ if ((p = btm_bda_to_acl(remote_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
return(BTM_UNKNOWN_ADDR);
/* Ignore change link key request if the previsous request has not completed */
@@ -1123,9 +1147,8 @@
}
}
- if ((p = btm_bda_to_acl(remote_bda)) != NULL)
- return(btsnd_hcic_write_policy_set (p->hci_handle, *settings) ?
- BTM_CMD_STARTED : BTM_NO_RESOURCES);
+ if ((p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR)) != NULL)
+ return(btsnd_hcic_write_policy_set (p->hci_handle, *settings) ? BTM_CMD_STARTED : BTM_NO_RESOURCES);
/* If here, no BD Addr found */
return(BTM_UNKNOWN_ADDR);
@@ -1199,7 +1222,7 @@
if (btm_cb.devcb.p_rlinkp_cmpl_cb)
return(BTM_BUSY);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
btu_start_timer (&btm_cb.devcb.rlinkp_timer, BTU_TTYPE_BTM_ACL, BTM_DEV_REPLY_TIMEOUT);
@@ -1638,47 +1661,62 @@
static void btm_establish_continue (tACL_CONN *p_acl_cb)
{
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
- tBTM_BL_EVENT_DATA evt_data;
+ tBTM_BL_EVENT_DATA evt_data;
#endif
- BTM_TRACE_DEBUG0 ("btm_establish_continue");
+ BTM_TRACE_DEBUG0 ("btm_establish_continue");
#if (!defined(BTM_BYPASS_EXTRA_ACL_SETUP) || BTM_BYPASS_EXTRA_ACL_SETUP == FALSE)
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
- if (!p_acl_cb->is_le_link)
+ if (p_acl_cb->transport == BT_TRANSPORT_BR_EDR)
#endif
- {
- /* For now there are a some devices that do not like sending */
- /* commands events and data at the same time. */
- /* Set the packet types to the default allowed by the device */
- btm_set_packet_types (p_acl_cb, btm_cb.btm_acl_pkt_types_supported);
+ {
+ /* For now there are a some devices that do not like sending */
+ /* commands events and data at the same time. */
+ /* Set the packet types to the default allowed by the device */
+ btm_set_packet_types (p_acl_cb, btm_cb.btm_acl_pkt_types_supported);
- if (btm_cb.btm_def_link_policy)
- BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
- }
+ if (btm_cb.btm_def_link_policy)
+ BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
+ }
#endif
- p_acl_cb->link_up_issued = TRUE;
+ p_acl_cb->link_up_issued = TRUE;
- /* If anyone cares, tell him database changed */
+ /* If anyone cares, tell him database changed */
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
- if (btm_cb.p_bl_changed_cb)
- {
- evt_data.event = BTM_BL_CONN_EVT;
- evt_data.conn.p_bda = p_acl_cb->remote_addr;
- evt_data.conn.p_bdn = p_acl_cb->remote_name;
- evt_data.conn.p_dc = p_acl_cb->remote_dc;
- evt_data.conn.p_features = p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0];
-
-
- (*btm_cb.p_bl_changed_cb)(&evt_data);
- }
- btm_acl_update_busy_level (BTM_BLI_ACL_UP_EVT);
-#else
- if (btm_cb.p_acl_changed_cb)
- (*btm_cb.p_acl_changed_cb) (p_acl_cb->remote_addr,
- p_acl_cb->remote_dc,
- p_acl_cb->remote_name,
- p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0],
- TRUE);
+ if (btm_cb.p_bl_changed_cb)
+ {
+ evt_data.event = BTM_BL_CONN_EVT;
+ evt_data.conn.p_bda = p_acl_cb->remote_addr;
+ evt_data.conn.p_bdn = p_acl_cb->remote_name;
+ evt_data.conn.p_dc = p_acl_cb->remote_dc;
+ evt_data.conn.p_features = p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0];
+#if BLE_INCLUDED == TRUE
+ evt_data.conn.handle = p_acl_cb->hci_handle;
+ evt_data.conn.transport = p_acl_cb->transport;
#endif
+
+ (*btm_cb.p_bl_changed_cb)(&evt_data);
+ }
+ btm_acl_update_busy_level (BTM_BLI_ACL_UP_EVT);
+#else
+ if (btm_cb.p_acl_changed_cb)
+#if BLE_INCLUDED == TRUE
+ (*btm_cb.p_acl_changed_cb) (p_acl_cb->remote_addr,
+ p_acl_cb->remote_dc,
+ p_acl_cb->remote_name,
+ p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0],
+ TRUE,
+ p_acl_cb->hci_handle,
+ p_acl_cb->transport);
+#else
+ (*btm_cb.p_acl_changed_cb) (p_acl_cb->remote_addr,
+ p_acl_cb->remote_dc,
+ p_acl_cb->remote_name,
+ p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0],
+ TRUE);
+#endif
+
+#endif
+
}
@@ -1709,7 +1747,7 @@
*******************************************************************************/
tBTM_STATUS BTM_GetLinkSuperTout (BD_ADDR remote_bda, UINT16 *p_timeout)
{
- tACL_CONN *p = btm_bda_to_acl(remote_bda);
+ tACL_CONN *p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_GetLinkSuperTout");
if (p != (tACL_CONN *)NULL)
@@ -1733,7 +1771,7 @@
*******************************************************************************/
tBTM_STATUS BTM_SetLinkSuperTout (BD_ADDR remote_bda, UINT16 timeout)
{
- tACL_CONN *p = btm_bda_to_acl(remote_bda);
+ tACL_CONN *p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_SetLinkSuperTout");
if (p != (tACL_CONN *)NULL)
@@ -1820,7 +1858,7 @@
if (!HCI_HOLD_MODE_SUPPORTED(BTM_ReadLocalFeatures()))
return(BTM_MODE_UNSUPPORTED);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
/* If the connection is in park or sniff mode, forget about holding it */
@@ -1858,7 +1896,7 @@
if (!HCI_SNIFF_MODE_SUPPORTED(BTM_ReadLocalFeatures()))
return(BTM_MODE_UNSUPPORTED);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
/* If the connection is in park mode, forget about sniffing it */
@@ -1892,7 +1930,7 @@
*******************************************************************************/
tBTM_STATUS BTM_CancelSniffMode (BD_ADDR remote_bda)
{
- tACL_CONN *p = btm_bda_to_acl(remote_bda);
+ tACL_CONN *p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_CancelSniffMode ");
if (p == (tACL_CONN *)NULL)
return(BTM_UNKNOWN_ADDR);
@@ -1928,7 +1966,7 @@
if (!HCI_PARK_MODE_SUPPORTED(BTM_ReadLocalFeatures()))
return(BTM_MODE_UNSUPPORTED);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
/* If the connection is in sniff mode, forget about parking it */
@@ -1966,7 +2004,7 @@
tACL_CONN *p;
BTM_TRACE_DEBUG0 ("BTM_CancelParkMode");
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
/* If the connection is not in park mode, cannot cancel */
@@ -2000,7 +2038,7 @@
tACL_CONN *p;
BTM_TRACE_DEBUG0 ("BTM_SetPacketTypes");
- if ((p = btm_bda_to_acl(remote_bda)) != NULL)
+ if ((p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR)) != NULL)
return(btm_set_packet_types (p, pkt_types));
/* If here, no BD Addr found */
@@ -2023,7 +2061,7 @@
tACL_CONN *p;
BTM_TRACE_DEBUG0 ("BTM_ReadPacketTypes");
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
return(p->pkt_types_mask);
@@ -2063,7 +2101,7 @@
remote_bda[0], remote_bda[1], remote_bda[2],
remote_bda[3], remote_bda[4], remote_bda[5]);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
*p_mode = p->mode;
@@ -2095,7 +2133,7 @@
remote_bda[0], remote_bda[1], remote_bda[2],
remote_bda[3], remote_bda[4], remote_bda[5]);
- if ( (p = btm_bda_to_acl(remote_bda)) != NULL)
+ if ( (p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR)) != NULL)
return(p->clock_offset);
/* If here, no BD Addr found */
@@ -2112,7 +2150,7 @@
** Returns TRUE if connection is up, else FALSE.
**
*******************************************************************************/
-BOOLEAN BTM_IsAclConnectionUp (BD_ADDR remote_bda)
+BOOLEAN BTM_IsAclConnectionUp (BD_ADDR remote_bda, tBT_TRANSPORT transport)
{
tACL_CONN *p;
@@ -2120,7 +2158,7 @@
remote_bda[0], remote_bda[1], remote_bda[2],
remote_bda[3], remote_bda[4], remote_bda[5]);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, transport);
if (p != (tACL_CONN *)NULL)
{
return(TRUE);
@@ -2160,6 +2198,34 @@
/*******************************************************************************
**
+** Function BTM_GetNumLeLinks
+**
+** Description This function is called to count the number of
+** LE ACL links that are active.
+**
+** Returns UINT16 Number of active LE links
+**
+*******************************************************************************/
+UINT16 BTM_GetNumLeLinks (void)
+{
+ UINT16 yy = 0;
+
+#if BLE_INCLUDED == TRUE
+ tACL_CONN *p = &btm_cb.acl_db[0];
+ UINT16 xx;
+ BTM_TRACE_DEBUG0 ("BTM_GetNumLeLinks");
+ for (xx = yy = 0; xx < MAX_L2CAP_LINKS; xx++, p++)
+ {
+ if ((p->in_use) &&(p->transport == BT_TRANSPORT_LE))
+ yy++;
+ }
+#endif
+
+ return(yy);
+}
+
+/*******************************************************************************
+**
** Function btm_get_acl_disc_reason_code
**
** Description This function is called to get the disconnection reason code
@@ -2186,11 +2252,11 @@
** Returns the handle of the connection, or 0xFFFF if none.
**
*******************************************************************************/
-UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda)
+UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda, tBT_TRANSPORT transport)
{
tACL_CONN *p;
BTM_TRACE_DEBUG0 ("BTM_GetHCIConnHandle");
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, transport);
if (p != (tACL_CONN *)NULL)
{
return(p->hci_handle);
@@ -2280,7 +2346,7 @@
{
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);
+ tACL_CONN *p = btm_bda_to_acl(p_bda, BT_TRANSPORT_BR_EDR);
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)
@@ -2567,7 +2633,7 @@
*******************************************************************************/
UINT16 btm_get_max_packet_size (BD_ADDR addr)
{
- tACL_CONN *p = btm_bda_to_acl(addr);
+ tACL_CONN *p = btm_bda_to_acl(addr, BT_TRANSPORT_BR_EDR);
UINT16 pkt_types = 0;
UINT16 pkt_size = 0;
BTM_TRACE_DEBUG0 ("btm_get_max_packet_size");
@@ -2625,7 +2691,7 @@
tBTM_STATUS BTM_ReadRemoteVersion (BD_ADDR addr, UINT8 *lmp_version,
UINT16 *manufacturer, UINT16 *lmp_sub_version)
{
- tACL_CONN *p = btm_bda_to_acl(addr);
+ tACL_CONN *p = btm_bda_to_acl(addr, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_ReadRemoteVersion");
if (p == NULL)
return(BTM_UNKNOWN_ADDR);
@@ -2651,7 +2717,7 @@
*******************************************************************************/
UINT8 *BTM_ReadRemoteFeatures (BD_ADDR addr)
{
- tACL_CONN *p = btm_bda_to_acl(addr);
+ tACL_CONN *p = btm_bda_to_acl(addr, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_ReadRemoteFeatures");
if (p == NULL)
{
@@ -2671,7 +2737,7 @@
*******************************************************************************/
UINT8 *BTM_ReadRemoteExtendedFeatures (BD_ADDR addr, UINT8 page_number)
{
- tACL_CONN *p = btm_bda_to_acl(addr);
+ tACL_CONN *p = btm_bda_to_acl(addr, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_ReadRemoteExtendedFeatures");
if (p == NULL)
{
@@ -2696,7 +2762,7 @@
*******************************************************************************/
UINT8 BTM_ReadNumberRemoteFeaturesPages (BD_ADDR addr)
{
- tACL_CONN *p = btm_bda_to_acl(addr);
+ tACL_CONN *p = btm_bda_to_acl(addr, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_ReadNumberRemoteFeaturesPages");
if (p == NULL)
{
@@ -2715,7 +2781,7 @@
*******************************************************************************/
UINT8 *BTM_ReadAllRemoteFeatures (BD_ADDR addr)
{
- tACL_CONN *p = btm_bda_to_acl(addr);
+ tACL_CONN *p = btm_bda_to_acl(addr, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG0 ("BTM_ReadAllRemoteFeatures");
if (p == NULL)
{
@@ -2798,7 +2864,7 @@
if (btm_cb.devcb.p_qossu_cmpl_cb)
return(BTM_BUSY);
- if ( (p = btm_bda_to_acl(bd)) != NULL)
+ if ( (p = btm_bda_to_acl(bd, BT_TRANSPORT_BR_EDR)) != NULL)
{
btu_start_timer (&btm_cb.devcb.qossu_timer, BTU_TTYPE_BTM_ACL, BTM_DEV_REPLY_TIMEOUT);
btm_cb.devcb.p_qossu_cmpl_cb = p_cb;
@@ -2882,7 +2948,7 @@
if (btm_cb.devcb.p_rssi_cmpl_cb)
return(BTM_BUSY);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
btu_start_timer (&btm_cb.devcb.rssi_timer, BTU_TTYPE_BTM_ACL,
@@ -2927,7 +2993,7 @@
if (btm_cb.devcb.p_lnk_qual_cmpl_cb)
return(BTM_BUSY);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p != (tACL_CONN *)NULL)
{
btu_start_timer (&btm_cb.devcb.lnk_quality_timer, BTU_TTYPE_BTM_ACL,
@@ -2960,7 +3026,7 @@
** Returns BTM_CMD_STARTED if successfully initiated or error code
**
*******************************************************************************/
-tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb)
+tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb)
{
tACL_CONN *p;
BOOLEAN ret;
@@ -2975,7 +3041,7 @@
if (btm_cb.devcb.p_tx_power_cmpl_cb)
return(BTM_BUSY);
- p = btm_bda_to_acl(remote_bda);
+ p = btm_bda_to_acl(remote_bda, transport);
if (p != (tACL_CONN *)NULL)
{
btu_start_timer (&btm_cb.devcb.tx_power_timer, BTU_TTYPE_BTM_ACL,
@@ -2984,7 +3050,7 @@
btm_cb.devcb.p_tx_power_cmpl_cb = p_cb;
#if BLE_INCLUDED == TRUE
- if (p->is_le_link)
+ if (p->transport == BT_TRANSPORT_LE)
{
memcpy(btm_cb.devcb.read_tx_pwr_addr, remote_bda, BD_ADDR_LEN);
ret = btsnd_hcic_ble_read_adv_chnl_tx_power();
@@ -3187,9 +3253,9 @@
** Returns BTM_SUCCESS if successfully initiated, otherwise BTM_NO_RESOURCES.
**
*******************************************************************************/
-tBTM_STATUS btm_remove_acl (BD_ADDR bd_addr)
+tBTM_STATUS btm_remove_acl (BD_ADDR bd_addr, tBT_TRANSPORT transport)
{
- UINT16 hci_handle = BTM_GetHCIConnHandle(bd_addr);
+ UINT16 hci_handle = BTM_GetHCIConnHandle(bd_addr, transport);
tBTM_STATUS status = BTM_SUCCESS;
BTM_TRACE_DEBUG0 ("btm_remove_acl");
@@ -3463,6 +3529,11 @@
evt_data.event = BTM_BL_COLLISION_EVT;
evt_data.conn.p_bda = bda;
+
+#if BLE_INCLUDED == TRUE
+ evt_data.conn.transport = BT_TRANSPORT_BR_EDR;
+ evt_data.conn.handle = BTM_INVALID_HCI_HANDLE;
+#endif
(*btm_cb.p_bl_changed_cb)(&evt_data);
return TRUE;
}
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 5b61b76..c5f6bb8 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -35,12 +35,13 @@
#include "btm_ble_api.h"
#include "smp_api.h"
#include "l2c_int.h"
-#if (defined BLE_BRCM_INCLUDED && BLE_BRCM_INCLUDED == TRUE)
-#include "brcm_ble.h"
-#endif
#include "gap_api.h"
#include "bt_utils.h"
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#include "vendor_ble.h"
+#endif
+
#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);
@@ -94,7 +95,8 @@
memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
p_dev_rec->sec_flags = BTM_SEC_IN_USE;
memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
- p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr);
+ p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
+ p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_LE);
/* update conn params, use default value for background connection params */
p_dev_rec->conn_params.min_conn_int =
@@ -102,7 +104,7 @@
p_dev_rec->conn_params.supervision_tout =
p_dev_rec->conn_params.slave_latency = BTM_BLE_CONN_PARAM_UNDEF;
- BTM_TRACE_DEBUG1 ("hci_handl=0x%x ", p_dev_rec->hci_handle );
+ BTM_TRACE_DEBUG1 ("hci_handl=0x%x ", p_dev_rec->ble_hci_handle );
break;
}
}
@@ -290,7 +292,7 @@
*******************************************************************************/
void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr, tBLE_ADDR_TYPE *p_addr_type)
{
- tACL_CONN *p_acl = btm_bda_to_acl(remote_bda);
+ tACL_CONN *p_acl = btm_bda_to_acl(remote_bda, BT_TRANSPORT_LE);
if (p_acl == NULL)
{
@@ -316,6 +318,7 @@
*******************************************************************************/
BOOLEAN BTM_IsBleConnection (UINT16 conn_handle)
{
+#if (BLE_INCLUDED == TRUE)
UINT8 xx;
tACL_CONN *p;
@@ -327,7 +330,10 @@
p = &btm_cb.acl_db[xx];
- return(p->is_le_link);
+ return (p->transport == BT_TRANSPORT_LE);
+#else
+ return FALSE;
+#endif
}
/*******************************************************************************
@@ -335,27 +341,33 @@
** Function BTM_ReadRemoteConnectionAddr
**
** Description This function is read the remote device address currently used
-** .
**
-** Returns void
+** Parameters pseudo_addr: pseudo random address available
+** conn_addr:connection address used
+** p_addr_type : BD Address type, Public or Random of the address used
+**
+** Returns BOOLEAN , TRUE if connection to remote device exists, else FALSE
**
*******************************************************************************/
-BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr, BD_ADDR conn_addr, tBLE_ADDR_TYPE *p_addr_type)
+BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr, BD_ADDR conn_addr,
+ tBLE_ADDR_TYPE *p_addr_type)
{
- BOOLEAN st = TRUE;
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_addr);
-#if BTM_BLE_PRIVACY_SPT == TRUE
- tACL_CONN *p = btm_bda_to_acl (pseudo_addr);
+ BOOLEAN st = TRUE;
+#if (BLE_PRIVACY_SPT == TRUE)
+ tACL_CONN *p = btm_bda_to_acl (pseudo_addr, BT_TRANSPORT_LE);
if (p == NULL)
{
- BTM_TRACE_ERROR0("BTM_ReadRemoteConnectionAddr can not find matching address");
+ BTM_TRACE_ERROR0("BTM_ReadRemoteConnectionAddr can not find connection"
+ " with matching address");
return FALSE;
}
memcpy(conn_addr, p->active_remote_addr, BD_ADDR_LEN);
*p_addr_type = p->active_remote_addr_type;
#else
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_addr);
+
memcpy(conn_addr, pseudo_addr, BD_ADDR_LEN);
if (p_dev_rec != NULL)
{
@@ -363,6 +375,7 @@
}
#endif
return st;
+
}
/*******************************************************************************
**
@@ -412,7 +425,7 @@
return;
}
- p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
+ p_dev_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
BTM_TRACE_DEBUG0 ("BTM_BlePasskeyReply");
SMP_PasskeyReply(bd_addr, res_smp, passkey);
#endif
@@ -444,7 +457,7 @@
return;
}
- p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
+ p_dev_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
SMP_OobDataReply(bd_addr, res_smp, len, p_data);
#endif
}
@@ -694,24 +707,6 @@
/*******************************************************************************
**
-** Function BTM_IsBleLink
-**
-** Description This function is to check the link type is BLE or BR/EDR.
-**
-** Returns TRUE if BLE link; FALSE if BR/EDR.
-**
-*******************************************************************************/
-BOOLEAN BTM_IsBleLink (BD_ADDR bd_addr)
-{
- tACL_CONN *p;
- BTM_TRACE_DEBUG0 ("BTM_IsBleLink");
- if ((p = btm_bda_to_acl(bd_addr)) != NULL)
- return p->is_le_link;
- else
- return FALSE;
-}
-/*******************************************************************************
-**
** Function BTM_UseLeLink
**
** Description This function is to select the underneath physical link to use.
@@ -726,9 +721,13 @@
tBLE_ADDR_TYPE addr_type;
BOOLEAN use_le = FALSE;
- if ((p = btm_bda_to_acl(bd_addr)) != NULL)
+ if ((p = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR)) != NULL)
{
- use_le = (p->is_le_link);
+ return use_le;
+ }
+ else if ((p = btm_bda_to_acl(bd_addr, BT_TRANSPORT_LE)) != NULL)
+ {
+ use_le = TRUE;
}
else
{
@@ -852,6 +851,7 @@
bd_addr[2],bd_addr[3],
bd_addr[4],bd_addr[5]);
+ *p_div = 0;
p_dev_rec = btm_find_dev (bd_addr);
if (p_dev_rec && p_dev_rec->ble.keys.div)
@@ -902,11 +902,11 @@
p_rec->ble.keys.ediv = p_keys->penc_key.ediv;
p_rec->ble.keys.key_size = p_keys->penc_key.key_size;
p_rec->ble.key_type |= BTM_LE_KEY_PENC;
- p_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
+ p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_KNOWN;
if (p_keys->penc_key.sec_level == SMP_SEC_AUTHENTICATED)
- p_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
+ p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
else
- p_rec->sec_flags &= ~BTM_SEC_LINK_KEY_AUTHED;
+ p_rec->sec_flags &= ~BTM_SEC_LE_LINK_KEY_AUTHED;
BTM_TRACE_DEBUG3("BTM_LE_KEY_PENC key_type=0x%x sec_flags=0x%x sec_leve=0x%x",
p_rec->ble.key_type,
p_rec->sec_flags,
@@ -931,11 +931,11 @@
p_rec->ble.keys.srk_sec_level = p_keys->pcsrk_key.sec_level;
p_rec->ble.keys.counter = p_keys->pcsrk_key.counter;
p_rec->ble.key_type |= BTM_LE_KEY_PCSRK;
- p_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
+ p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_KNOWN;
if ( p_keys->pcsrk_key.sec_level== SMP_SEC_AUTHENTICATED)
- p_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
+ p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
else
- p_rec->sec_flags &= ~BTM_SEC_LINK_KEY_AUTHED;
+ p_rec->sec_flags &= ~BTM_SEC_LE_LINK_KEY_AUTHED;
BTM_TRACE_DEBUG4("BTM_LE_KEY_PCSRK key_type=0x%x sec_flags=0x%x sec_level=0x%x peer_counter=%d",
p_rec->ble.key_type,
@@ -1081,9 +1081,9 @@
BTM_TRACE_DEBUG1 ("dev_rec sec_flags=0x%x", p_dev_rec->sec_flags);
/* currently encrpted */
- if (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)
+ if (p_dev_rec->sec_flags & BTM_SEC_LE_ENCRYPTED)
{
- if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED)
+ if (p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
cur_sec_level = BTM_LE_SEC_AUTHENTICATED;
else
cur_sec_level = BTM_LE_SEC_UNAUTHENTICATE;
@@ -1191,7 +1191,7 @@
break;
default:
- cmd = BTM_SUCCESS;
+ cmd = BTM_WRONG_MODE;
break;
}
return cmd;
@@ -1235,40 +1235,48 @@
** Description This function is called to start LE encryption.
**
**
-** Returns void
+** Returns BTM_SUCCESS if encryption was started successfully
**
*******************************************************************************/
-BOOLEAN btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk)
+tBTM_STATUS btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk)
{
tBTM_CB *p_cb = &btm_cb;
tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bda);
BT_OCTET8 dummy_rand = {0};
- BOOLEAN rt = FALSE;
+ tBTM_STATUS rt = BTM_NO_RESOURCES;
BTM_TRACE_DEBUG0 ("btm_ble_start_encrypt");
- if (!p_rec ||
- (p_rec && p_rec->sec_state == BTM_SEC_STATE_ENCRYPTING))
- return FALSE;
+ if (!p_rec )
+ {
+ BTM_TRACE_ERROR0("Link is not active, can not encrypt!");
+ return BTM_WRONG_MODE;
+ }
- p_cb->enc_handle = p_rec->hci_handle;
+ if (p_rec->sec_state == BTM_SEC_STATE_ENCRYPTING)
+ {
+ BTM_TRACE_WARNING0("Link Encryption is active, Busy!");
+ return BTM_BUSY;
+ }
+
+ p_cb->enc_handle = p_rec->ble_hci_handle;
if (use_stk)
{
- if (btsnd_hcic_ble_start_enc(p_rec->hci_handle, dummy_rand, 0, stk))
- rt = TRUE;
+ if (btsnd_hcic_ble_start_enc(p_rec->ble_hci_handle, dummy_rand, 0, stk))
+ rt = BTM_CMD_STARTED;
}
else if (p_rec->ble.key_type & BTM_LE_KEY_PENC)
{
- if (btsnd_hcic_ble_start_enc(p_rec->hci_handle, p_rec->ble.keys.rand,
+ if (btsnd_hcic_ble_start_enc(p_rec->ble_hci_handle, p_rec->ble.keys.rand,
p_rec->ble.keys.ediv, p_rec->ble.keys.ltk))
- rt = TRUE;
+ rt = BTM_CMD_STARTED;
}
else
{
BTM_TRACE_ERROR0("No key available to encrypt the link");
}
- if (rt)
+ if (rt == BTM_CMD_STARTED)
{
if (p_rec->sec_state == BTM_SEC_STATE_IDLE)
p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
@@ -1312,9 +1320,9 @@
if (p_dev_rec->p_callback && enc_cback)
{
if (encr_enable)
- btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS);
+ btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS, TRUE);
else if (p_dev_rec->role_master)
- btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING);
+ btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING, TRUE);
}
/* to notify GATT to send data if any request is pending */
@@ -1399,7 +1407,7 @@
}
BTM_TRACE_DEBUG0 ("btm_ble_ltk_request_reply");
- p_cb->enc_handle = p_rec->hci_handle;
+ p_cb->enc_handle = p_rec->ble_hci_handle;
p_cb->key_size = p_rec->ble.keys.key_size;
BTM_TRACE_ERROR1("key size = %d", p_rec->ble.keys.key_size);
@@ -1440,7 +1448,21 @@
if (callback_rc == BTM_SUCCESS)
#endif
{
+#if BTM_BLE_CONFORMANCE_TESTING == TRUE
+ if (btm_cb.devcb.keep_rfu_in_auth_req)
+ {
+ BTM_TRACE_DEBUG1 ("btm_ble_io_capabilities_req keep_rfu_in_auth_req = %u",
+ btm_cb.devcb.keep_rfu_in_auth_req);
+ p_data->auth_req &= BTM_LE_AUTH_REQ_MASK_KEEP_RFU;
+ btm_cb.devcb.keep_rfu_in_auth_req = FALSE;
+ }
+ else
+ { /* default */
+ p_data->auth_req &= BTM_LE_AUTH_REQ_MASK;
+ }
+#else
p_data->auth_req &= BTM_LE_AUTH_REQ_MASK;
+#endif
BTM_TRACE_DEBUG2 ("btm_ble_io_capabilities_req 1: p_dev_rec->security_required = %d auth_req:%d",
p_dev_rec->security_required, p_data->auth_req);
@@ -1477,7 +1499,7 @@
return callback_rc;
}
-#if (BTM_BLE_PRIVACY_SPT == TRUE )
+#if (BLE_PRIVACY_SPT == TRUE )
/*******************************************************************************
**
** Function btm_ble_resolve_random_addr_on_conn_cmpl
@@ -1556,7 +1578,7 @@
#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",
+ BTM_TRACE_EVENT4 ("Security Manager: btm_ble_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);
@@ -1565,7 +1587,7 @@
}
else
{
- BTM_TRACE_EVENT3 ("Security Manager: btm_sec_connected: handle:%d enc_mode:%d bda:%x ",
+ BTM_TRACE_EVENT3 ("Security Manager: btm_ble_connected: handle:%d enc_mode:%d bda:%x ",
handle, enc_mode,
(bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5]);
}
@@ -1583,19 +1605,23 @@
/* update device information */
p_dev_rec->device_type |= BT_DEVICE_TYPE_BLE;
- p_dev_rec->hci_handle = handle;
+ p_dev_rec->ble_hci_handle = handle;
p_dev_rec->ble.ble_addr_type = addr_type;
p_dev_rec->role_master = FALSE;
if (role == HCI_ROLE_MASTER)
p_dev_rec->role_master = TRUE;
-#if (defined BTM_BLE_PRIVACY_SPT && BTM_BLE_PRIVACY_SPT == TRUE)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
if (!addr_matched)
p_dev_rec->ble.active_addr_type = BTM_BLE_ADDR_PSEUDO;
if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM && !addr_matched)
memcpy(p_dev_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
+
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+ btm_ble_vendor_disable_irk_list();
+#endif
#endif
if (role == HCI_ROLE_SLAVE)
@@ -1613,7 +1639,7 @@
******************************************************************************/
void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
{
-#if (BTM_BLE_PRIVACY_SPT == TRUE )
+#if (BLE_PRIVACY_SPT == TRUE )
UINT8 *p_data = p;
#endif
UINT8 role, status, bda_type;
@@ -1631,10 +1657,13 @@
if (status == 0)
{
-#if (BTM_BLE_PRIVACY_SPT == TRUE )
+#if (BLE_PRIVACY_SPT == TRUE )
+#if (BLE_VND_INCLUDED == TRUE)
+ match = btm_public_addr_to_random_pseudo (bda, &bda_type);
+#endif
/* possiblly receive connection complete with resolvable random on
slave role while the device has been paired */
- if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
+ if (!match && role == HCI_ROLE_SLAVE && BTM_BLE_IS_RESOLVE_BDA(bda))
{
btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_conn_cmpl, p_data);
}
@@ -1655,9 +1684,9 @@
{
role = HCI_ROLE_UNKNOWN;
- if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+ if (status != HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
{
- btm_ble_dir_adv_tout();
+ btm_ble_set_conn_st(BLE_CONN_IDLE);
}
/* this is to work around broadcom firmware problem to handle
* unsolicited command complete event for HCI_LE_Create_Connection_Cancel
@@ -1679,9 +1708,7 @@
}
}
}
-
btm_ble_set_conn_st(BLE_CONN_IDLE);
-
btm_ble_update_mode_operation(role, bda, TRUE);
}
@@ -1709,10 +1736,12 @@
case SMP_PASSKEY_REQ_EVT:
case SMP_PASSKEY_NOTIF_EVT:
case SMP_OOB_REQ_EVT:
- p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
+ p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
+
case SMP_SEC_REQUEST_EVT:
memcpy (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN);
p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
+ btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
/* fall through */
case SMP_COMPLT_EVT:
if (btm_cb.api.p_le_callback)
@@ -1731,7 +1760,7 @@
BTM_TRACE_DEBUG3 ("after update result=%d sec_level=0x%x sec_flags=0x%x",
res, p_data->cmplt.sec_level , p_dev_rec->sec_flags );
- btm_sec_dev_rec_cback_event(p_dev_rec, res);
+ btm_sec_dev_rec_cback_event(p_dev_rec, res, TRUE);
if (p_data->cmplt.is_pair_cancel && btm_cb.api.p_bond_cancel_cmpl_callback )
{
@@ -1744,7 +1773,7 @@
if (!btm_cb.devcb.no_disc_if_pair_fail && p_data->cmplt.reason != SMP_CONN_TOUT)
{
BTM_TRACE_DEBUG0 ("Pairing failed - Remove ACL");
- btm_remove_acl(bd_addr);
+ btm_remove_acl(bd_addr, BT_TRANSPORT_LE);
}
else
{
@@ -1754,7 +1783,7 @@
}
#else
if (res != BTM_SUCCESS && p_data->cmplt.reason != SMP_CONN_TOUT)
- btm_remove_acl(bd_addr);
+ btm_remove_acl(bd_addr, BT_TRANSPORT_LE);
#endif
BTM_TRACE_DEBUG3 ("btm_cb pairing_state=%x pairing_flags=%x pin_code_len=%x",
@@ -2299,6 +2328,23 @@
}
+
+/*******************************************************************************
+**
+** Function btm_ble_set_keep_rfu_in_auth_req
+**
+** Description This function indicates if RFU bits have to be kept as is
+** (by default they have to be set to 0 by the sender).
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_set_keep_rfu_in_auth_req(BOOLEAN keep_rfu)
+{
+ BTM_TRACE_DEBUG1 ("btm_ble_set_keep_rfu_in_auth_req keep_rfus=%d", keep_rfu);
+ btm_cb.devcb.keep_rfu_in_auth_req = keep_rfu;
+}
+
#endif /* BTM_BLE_CONFORMANCE_TESTING */
#endif /* BLE_INCLUDED */
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index 3c646e9..79c0a5d 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -33,8 +33,10 @@
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
#include "btm_ble_int.h"
#include "smp_api.h"
-#define BTM_BLE_PRIVATE_ADDR_INT 900 /* 15 minutes minimum for
- random address refreshing */
+
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#include "vendor_ble.h"
+#endif
/*******************************************************************************
**
@@ -64,9 +66,13 @@
/* start a periodical timer to refresh random addr */
btu_stop_timer(&p_cb->raddr_timer_ent);
+#if (BTM_BLE_CONFORMANCE_TESTING == TRUE)
+ btu_start_timer (&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
+ btm_cb.ble_ctr_cb.rpa_tout);
+#else
btu_start_timer (&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
BTM_BLE_PRIVATE_ADDR_INT);
-
+#endif
}
else
{
@@ -84,7 +90,7 @@
** Returns void
**
*******************************************************************************/
-static void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p)
+void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p)
{
#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
@@ -121,11 +127,11 @@
** Returns void
**
*******************************************************************************/
-void btm_gen_resolvable_private_addr (void)
+void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback)
{
BTM_TRACE_EVENT0 ("btm_gen_resolvable_private_addr");
/* generate 3B rand as BD LSB, SRK with it, get BD MSB */
- if (!btsnd_hcic_ble_rand((void *)btm_gen_resolve_paddr_low))
+ if (!btsnd_hcic_ble_rand((void *)p_cmd_cplt_cback))
btm_gen_resolve_paddr_cmpl(NULL);
}
/*******************************************************************************
@@ -376,6 +382,148 @@
return BLE_ADDR_PUBLIC;
}
+#if BLE_PRIVACY_SPT == TRUE
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function btm_find_dev_by_public_static_addr
+**
+** Description find the security record whose LE static address is matching
+**
+*******************************************************************************/
+tBTM_SEC_DEV_REC* btm_find_dev_by_public_static_addr(BD_ADDR bd_addr)
+{
+ UINT8 i;
+ tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+
+ for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++)
+ {
+ if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
+ BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
+ {
+ if ( memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) == 0)
+ {
+ p_dev_rec->ble.active_addr_type = BTM_BLE_ADDR_RRA;
+ /* found the match */
+ return p_dev_rec;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function btm_public_addr_to_random_pseudo
+**
+** Description This function map a static BD address to a pseudo random address
+** in security database.
+**
+*******************************************************************************/
+BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_public_static_addr(bd_addr);
+
+ BTM_TRACE_EVENT0 ("btm_public_addr_to_random_pseudo");
+
+ /* evt reported on static address, map static address to random pseudo */
+ if (p_dev_rec != NULL &&
+ /* static address is not static address */
+ memcmp(p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN) != 0)
+ /* update current random */
+ btm_ble_read_irk_entry(p_dev_rec->ble.static_addr);
+ if (p_dev_rec != NULL)
+ {
+ /* assign the orginal random to be the current report address */
+ memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+ /* always be a resolvable random if a match is found */
+ *p_addr_type = BLE_ADDR_RANDOM;
+
+ BTM_TRACE_ERROR0("matched a public/reconnect address and map to random pseudo");
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_random_pseudo_to_public
+**
+** Description This function map a random pseudo address to a public address
+** random_pseudo is input and output parameter
+**
+*******************************************************************************/
+BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_type)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (random_pseudo);
+
+ if (p_dev_rec != NULL)
+ {
+ if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
+ BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr) &&
+ (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0)
+ {
+ BTM_TRACE_EVENT0 ("btm_random_pseudo_to_public found the puclic static address!");
+ * p_static_addr_type = p_dev_rec->ble.static_addr_type;
+ memcpy(random_pseudo, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_refresh_rra
+**
+** Description This function refresh the currently used RRA into security
+** database and set active connection address.
+**
+*******************************************************************************/
+void btm_ble_refresh_rra(BD_ADDR static_bda, BD_ADDR rra)
+{
+ tBTM_SEC_DEV_REC *p_sec_rec = btm_find_dev_by_public_static_addr(static_bda);
+ tACL_CONN *p_acl = btm_bda_to_acl (p_sec_rec->bd_addr, BT_TRANSPORT_LE);
+ UINT8 rra_dummy = FALSE;
+ BD_ADDR dummy_bda = {0};
+
+ BTM_TRACE_ERROR0("btm_ble_refresh_rra");
+
+ if (memcmp(dummy_bda, rra, BD_ADDR_LEN) == 0)
+ rra_dummy = TRUE;
+
+ /* connection refresh RRA */
+ if (p_acl != NULL /* && memcmp(p_acl->active_remote_addr, dummy_bda, BD_ADDR_LEN) == 0 */)
+ {
+ /* use static address, rra is empty */
+ if (rra_dummy)
+ {
+ p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
+ memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
+ }
+ else
+ {
+ p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
+ memcpy(p_acl->active_remote_addr, rra, BD_ADDR_LEN);
+ }
+ }
+ /* update security record here, in adv event or connection complete process */
+ if (p_sec_rec != NULL)
+ {
+ memcpy(p_sec_rec->ble.cur_rand_addr, rra, BD_ADDR_LEN);
+ p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC: BTM_BLE_ADDR_RRA;
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("No matching known device in record");
+ }
+
+}
+#endif /* CS support */
+#endif /* privacy support */
#endif
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index 96d35c4..967f90b 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -30,6 +30,9 @@
#include "l2c_int.h"
#include "hcimsgs.h"
#include "bt_utils.h"
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#include "vendor_ble.h"
+#endif
#ifndef BTM_BLE_SCAN_PARAM_TOUT
#define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */
@@ -57,7 +60,7 @@
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,
+ btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
scan_policy);
}
/*******************************************************************************
@@ -83,17 +86,24 @@
{
if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
{
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ /* add device into IRK list */
+ btm_ble_vendor_irk_list_load_dev(p_dev_rec);
+#endif
+#endif
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);
+ started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type,
+ p_dev_rec->ble.static_addr);
}
}
else
{
- if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
+ if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
{
started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
}
@@ -255,9 +265,9 @@
}
/*******************************************************************************
**
-** Function btm_ble_add_2_white_list_complete
+** Function btm_ble_remove_from_white_list_complete
**
-** Description This function read the current white list size.
+** Description This function remove the white list element complete.
*******************************************************************************/
void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len)
{
@@ -284,7 +294,7 @@
for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++)
{
if (p_cb->bg_dev_list[i].in_use &&
- !BTM_IsAclConnectionUp(p_cb->bg_dev_list[i].bd_addr))
+ !BTM_IsAclConnectionUp(p_cb->bg_dev_list[i].bd_addr, BT_TRANSPORT_LE))
{
count ++;
}
@@ -363,12 +373,12 @@
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;
if (start)
{
- if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
+ if ((p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
+ && btm_ble_topology_check(BTM_BLE_STATE_INIT))
{
btm_execute_wl_dev_operation();
@@ -380,7 +390,9 @@
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 */
+ p_cb->addr_mgnt_cb.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 */
@@ -407,8 +419,13 @@
if (p_cb->conn_state == BLE_BG_CONN)
{
btsnd_hcic_ble_create_conn_cancel();
- btm_ble_set_conn_st (BLE_CONN_CANCEL);
+ btm_ble_set_conn_st (BLE_CONN_CANCEL);
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ btm_ble_vendor_disable_irk_list();
+#endif
+#endif
}
else
{
@@ -446,26 +463,27 @@
if (start)
{
- if (btm_cb.btm_inq_vars.inq_active == BTM_INQUIRY_INACTIVE)
+ if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
{
if (p_select_cback != NULL)
btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
+ btm_execute_wl_dev_operation();
+
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 */
scan_win, /* scan window */
- BLE_ADDR_PUBLIC, /* own device, DUMO always use public */
+ p_cb->addr_mgnt_cb.own_addr_type,
SP_ADV_WL) /* process advertising packets only from devices in the White List */
)
return FALSE;
- if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE
- )
+ if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN))
{
- BTM_TRACE_ERROR0("peripheral device cannot initiate a selective connection");
+ BTM_TRACE_ERROR0("peripheral device cannot initiate passive scan for a selective connection");
return FALSE;
}
else if (p_cb->bg_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
@@ -475,9 +493,7 @@
return FALSE;
/* mark up inquiry status flag */
- 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;
+ p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
}
}
else
@@ -488,13 +504,18 @@
}
else /* disable selective connection mode */
{
- 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;
+ p_cb->scan_activity &= ~BTM_LE_SELECT_CONN_ACTIVE;
+ p_cb->p_select_cback = NULL;
- btm_update_scanner_filter_policy(SP_ADV_ALL);
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+ btm_ble_vendor_disable_irk_list();
+#endif
+#endif
+
/* stop scanning */
- if (!btsnd_hcic_ble_set_scan_enable(FALSE, TRUE)) /* duplicate filtering enabled */
- return FALSE;
+ if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
+ btm_ble_stop_scan(); /* duplicate filtering enabled */
btm_update_scanner_filter_policy(SP_ADV_ALL);
}
return TRUE;
@@ -569,7 +590,7 @@
}
if (wl_state & BTM_BLE_WL_ADV)
{
- btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_DISABLE);
+ btm_ble_stop_adv();
}
}
@@ -588,7 +609,7 @@
if (wl_state & BTM_BLE_WL_ADV)
{
- btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_ENABLE);
+ btm_ble_start_adv();
}
}
@@ -645,6 +666,10 @@
void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
{
btm_cb.ble_ctr_cb.conn_state = new_st;
+ if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN)
+ btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT);
+ else
+ btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
}
/*******************************************************************************
@@ -689,6 +714,7 @@
return rt;
}
+
#endif
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 54f1b55..e94bcad 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright (C) 2008-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,8 +35,13 @@
#include "gap_api.h"
#endif
#if (BLE_INCLUDED == TRUE)
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#include "vendor_ble.h"
+#endif
#include "gattdefs.h"
+#include "btm_ble_int.h"
+
#define BTM_BLE_NAME_SHORT 0x01
#define BTM_BLE_NAME_CMPL 0x02
@@ -44,37 +49,171 @@
#define BTM_BLE_POLICY_UNKNOWN 0xff
#define BTM_EXT_BLE_RMT_NAME_TIMEOUT 30
+#define MIN_ADV_LENGTH 2
+
+extern tBTM_BLE_MULTI_ADV_CB btm_multi_adv_cb;
/*******************************************************************************
** Local functions
*******************************************************************************/
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);
+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);
+static void btm_ble_stop_observe(void);
+#define BTM_BLE_INQ_RESULT 0x01
+#define BTM_BLE_OBS_RESULT 0x02
+#define BTM_BLE_SEL_CONN_RESULT 0x04
-
-/*******************************************************************************
-**
-** Function BTM_BleReset
-**
-** Description This function is called to reset ULP controller.
-**
-** Parameters None.
-**
-** Returns void
-**
-*******************************************************************************/
-void BTM_BleReset(void)
+/* LE states combo bit to check */
+const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] =
{
- btsnd_hcic_ble_reset();
-}
+ {/* single state support */
+ {HCI_SUPP_LE_STATES_CONN_ADV_MASK, HCI_SUPP_LE_STATES_CONN_ADV_OFF}, /* conn_adv */
+ {HCI_SUPP_LE_STATES_INIT_MASK, HCI_SUPP_LE_STATES_INIT_OFF}, /* init */
+ {HCI_SUPP_LE_STATES_INIT_MASK, HCI_SUPP_LE_STATES_INIT_OFF}, /* master */
+ {HCI_SUPP_LE_STATES_SLAVE_MASK, HCI_SUPP_LE_STATES_SLAVE_OFF}, /* slave */
+ {0, 0}, /* todo: lo du dir adv, not covered ? */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_OFF}, /* hi duty dir adv */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_OFF}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_OFF}, /* active scan */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_MASK, HCI_SUPP_LE_STATESSCAN_ADV_OFF} /* scanable adv */
+ },
+ { /* conn_adv =0 */
+ {0, 0}, /* conn_adv */
+ {HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF}, /* init: 32 */
+ {HCI_SUPP_LE_STATES_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_CONN_ADV_MASTER_OFF}, /* master: 35 */
+ {HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF}, /* slave: 38,*/
+ {0, 0}, /* lo du dir adv */
+ {0, 0}, /* hi duty dir adv */
+ {0, 0}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_OFF}, /* active scan */
+ {0, 0} /* scanable adv */
+ },
+ { /* init */
+ {HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF}, /* conn_adv: 32 */
+ {0, 0}, /* init */
+ {HCI_SUPP_LE_STATES_INIT_MASTER_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_OFF}, /* master 28 */
+ {HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF}, /* slave 41 */
+ {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_OFF} ,/* lo du dir adv 34 */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_OFF}, /* hi duty dir adv 33 */
+ {HCI_SUPP_LE_STATES_NON_CONN_INIT_MASK, HCI_SUPP_LE_STATES_NON_CONN_INIT_OFF}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_PASS_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_INIT_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_OFF}, /* active scan */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_INIT_OFF} /* scanable adv */
+
+ },
+ { /* master */
+ {HCI_SUPP_LE_STATES_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_CONN_ADV_MASTER_OFF}, /* conn_adv: 35 */
+ {HCI_SUPP_LE_STATES_INIT_MASTER_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_OFF}, /* init 28 */
+ {HCI_SUPP_LE_STATES_INIT_MASTER_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_OFF}, /* master 28 */
+ {HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF}, /* slave: 32 */
+ {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_OFF}, /* lo duty cycle adv 37 */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_OFF}, /* hi duty cycle adv 36 */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_OFF}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_OFF}, /* active scan */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_OFF} /* scanable adv */
+
+ },
+ { /* slave */
+ {HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF}, /* conn_adv: 38,*/
+ {HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF}, /* init 41 */
+ {HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF}, /* master 41 */
+ {HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF}, /* slave: 38,*/
+ {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_OFF}, /* lo duty cycle adv 40 */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_OFF}, /* hi duty cycle adv 39 */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_OFF}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_OFF}, /* active scan */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_OFF} /* scanable adv */
+
+ },
+ { /* lo duty cycle adv */
+ {0, 0}, /* conn_adv: 38,*/
+ {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_OFF} ,/* init 34 */
+ {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_OFF}, /* master 37 */
+ {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_OFF}, /* slave: 40 */
+ {0, 0}, /* lo duty cycle adv 40 */
+ {0, 0}, /* hi duty cycle adv 39 */
+ {0, 0}, /* non connectable adv */
+ {0, 0}, /* TODO: passive scan, not covered? */
+ {0, 0}, /* TODO: active scan, not covered? */
+ {0, 0} /* scanable adv */
+ },
+ { /* hi duty cycle adv */
+ {0, 0}, /* conn_adv: 38,*/
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_OFF}, /* init 33 */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_OFF}, /* master 36 */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_OFF}, /* slave: 39*/
+ {0, 0}, /* lo duty cycle adv 40 */
+ {0, 0}, /* hi duty cycle adv 39 */
+ {0, 0}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_OFF}, /* active scan */
+ {0, 0} /* scanable adv */
+ },
+ { /* non connectable adv */
+ {0, 0}, /* conn_adv: */
+ {HCI_SUPP_LE_STATES_NON_CONN_INIT_MASK, HCI_SUPP_LE_STATES_NON_CONN_INIT_OFF}, /* init */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_OFF}, /* master */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_OFF}, /* slave: */
+ {0, 0}, /* lo duty cycle adv */
+ {0, 0}, /* hi duty cycle adv */
+ {0, 0}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_OFF}, /* active scan */
+ {0, 0} /* scanable adv */
+ },
+ { /* passive scan */
+ {HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_OFF}, /* conn_adv: */
+ {HCI_SUPP_LE_STATES_PASS_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_INIT_OFF}, /* init */
+ {HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_OFF}, /* master */
+ {HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_OFF}, /* slave: */
+ {0, 0}, /* lo duty cycle adv */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_OFF}, /* hi duty cycle adv */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_OFF}, /* non connectable adv */
+ {0, 0}, /* passive scan */
+ {0, 0}, /* active scan */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_OFF} /* scanable adv */
+ },
+ { /* active scan */
+ {HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_OFF}, /* conn_adv: */
+ {HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_OFF}, /* init */
+ {HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_OFF}, /* master */
+ {HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_OFF}, /* slave: */
+ {0, 0}, /* lo duty cycle adv */
+ {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_OFF}, /* hi duty cycle adv */
+ {HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_OFF}, /* non connectable adv */
+ {0, 0}, /* TODO: passive scan */
+ {0, 0}, /* TODO: active scan */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_OFF} /* scanable adv */
+ },
+ { /* scanable adv */
+ {0, 0}, /* conn_adv: */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_INIT_OFF}, /* init */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_OFF}, /* master */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_OFF}, /* slave: */
+ {0, 0}, /* lo duty cycle adv */
+ {0, 0}, /* hi duty cycle adv */
+ {0, 0}, /* non connectable adv */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_OFF}, /* passive scan */
+ {HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_OFF}, /* active scan */
+ {0, 0} /* scanable adv */
+ }
+
+};
+/* check LE combo state supported */
+#define BTM_LE_STATES_SUPPORTED(x, y, z) ((x)[(z)] & (y))
+
+
/*******************************************************************************
**
** Function BTM_BleUpdateAdvWhitelist
@@ -122,10 +261,13 @@
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);
+ 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,
+ btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min :
+ BTM_BLE_GAP_ADV_SLOW_INT),
+ (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max :
+ BTM_BLE_GAP_ADV_SLOW_INT),
p_cb->evt_type,
p_cb->adv_addr_type,
init_addr_type,
@@ -155,7 +297,7 @@
tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb)
{
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
- tBTM_STATUS status = BTM_NO_RESOURCES;
+ tBTM_STATUS status = BTM_WRONG_MODE;
BTM_TRACE_EVENT1 ("BTM_BleObserve : scan_type:%d",btm_cb.btm_inq_vars.scan_type);
@@ -165,63 +307,56 @@
if (start)
{
/* 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)
+ if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
{
- /*check if an interleave scan is already in progress*/
- if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL
- && btm_cb.btm_inq_vars.p_inq_results_cb != NULL)
- {
- BTM_TRACE_EVENT0 ("BTM_BleObserve general inq in progress, redirecting the results");
- btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb;
- btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb;
- return BTM_SUCCESS;
- }
- else
- return BTM_BUSY;
+ BTM_TRACE_ERROR0("Observe Already Active");
+ return status;
}
- btm_cb.btm_inq_vars.scan_type = INQ_LE_OBSERVE;
- btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb;
- btm_cb.btm_inq_vars.p_inq_ble_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 (p_inq->scan_type,
+ btm_cb.ble_ctr_cb.p_obs_results_cb = p_results_cb;
+ btm_cb.ble_ctr_cb.p_obs_cmpl_cb = p_cmpl_cb;
+ status = BTM_CMD_STARTED;
+
+ /* scan is not started */
+ if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
+ {
+ 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 */
+ 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,
- BTM_BLE_DEFAULT_SFP)) /* assume observe always not using white list */
- {
- /* start scan, disable duplicate filtering */
- if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE))
- {
- status = BTM_SUCCESS;
- p_inq->proc_mode = BTM_BLE_OBSERVE;
- btm_cb.btm_inq_vars.inq_active |= BTM_LE_OBSERVE_ACTIVE;
+ btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
+ BTM_BLE_DEFAULT_SFP); /* assume observe always not using white list */
- if (duration != 0)
- {
- /* start inquiry timer */
- btu_start_timer (&p_inq->inq_timer_ent, BTU_TTYPE_BLE_INQUIRY, duration);
- }
- }
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ /* enable IRK list */
+ btm_ble_vendor_irk_list_known_dev (TRUE);
+#endif
+#endif
+ status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
+ }
+ if (status == BTM_CMD_STARTED)
+ {
+ btm_cb.ble_ctr_cb.scan_activity |= BTM_LE_OBSERVE_ACTIVE;
+
+ if (duration != 0)
+ /* start observer timer */
+ btu_start_timer (&btm_cb.ble_ctr_cb.obs_timer_ent, BTU_TTYPE_BLE_OBSERVE, duration);
}
}
- else/*start = 0*/
+ else if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
{
- if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL)
- {
- //Dont stop the scan. Just nullify the cbs
- btm_cb.btm_inq_vars.p_inq_ble_results_cb = NULL;
- btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = NULL;
- }
- else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
- {
- btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
- btm_ble_stop_scan();
- }
+ status = BTM_CMD_STARTED;
+ btm_ble_stop_observe();
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("Observe not active");
}
return status;
+
}
/*******************************************************************************
@@ -255,8 +390,10 @@
if (start && p_cb->adv_mode == BTM_BLE_ADV_DISABLE)
{
/* 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),
+ 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_addr_cb->own_addr_type,
p_cb->direct_bda.type,
@@ -270,7 +407,7 @@
status = btm_ble_start_adv ();
}
- else if (!start && p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
+ else if (!start)
{
status = btm_ble_stop_adv();
}
@@ -278,13 +415,75 @@
{
status = BTM_WRONG_MODE;
BTM_TRACE_ERROR2("Can not %s Broadcast, device %s in Broadcast mode",
- (start ? "Start" : "Stop"), (start ? "alerady" :"not"));
+ (start ? "Start" : "Stop"), (start ? "already" :"not"));
}
return status;
}
/*******************************************************************************
**
+** Function btm_vsc_brcm_features_complete
+**
+** Description Command Complete callback for HCI_BLE_VENDOR_CAP_OCF
+**
+** Returns void
+**
+*******************************************************************************/
+static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_params)
+{
+ BTM_TRACE_EVENT0 ("btm_ble_vendor_capability_vsc_cmpl_cback");
+ UINT8 status = 0xFF, *p;
+ UINT8 rpa_offloading, max_irk_list_sz, filtering_support, max_filter;
+ UINT16 scan_result_storage;
+ tBTM_BLE_VENDOR_CB *p_vcb = &btm_ble_vendor_cb;
+ max_irk_list_sz = 0;
+ /* Check status of command complete event */
+ if((p_vcs_cplt_params->opcode == HCI_BLE_VENDOR_CAP_OCF)
+ &&(p_vcs_cplt_params->param_len > 0 ))
+ {
+ p = p_vcs_cplt_params->p_param_buf;
+ STREAM_TO_UINT8 (status, p);
+ }
+
+ if(status == HCI_SUCCESS)
+ {
+ STREAM_TO_UINT8 (btm_multi_adv_cb.adv_inst_max, p);
+ STREAM_TO_UINT8 (rpa_offloading, p);
+ STREAM_TO_UINT16 (scan_result_storage, p);
+ STREAM_TO_UINT8 (max_irk_list_sz, p);
+ STREAM_TO_UINT8 (filtering_support, p);
+ STREAM_TO_UINT8 (max_filter, p);
+ }
+ p_vcb->irk_avail_size = max_irk_list_sz;
+ BTM_TRACE_EVENT3 ("btm_ble_vendor_capability_vsc_cmpl_cback:%d, status=%d, max_irk_size=%d", btm_multi_adv_cb.adv_inst_max, status,btm_ble_vendor_cb.irk_avail_size);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_vendor_capability_init
+**
+** Description LE Get_Vendor Capabilities
+**
+** Returns None.
+**
+*******************************************************************************/
+void btm_ble_vendor_capability_init(void)
+{
+ BTM_TRACE_ERROR0("btm_ble_vendor_capability_init");
+ memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB));
+ if ( BTM_VendorSpecificCommand (HCI_BLE_VENDOR_CAP_OCF,
+ 0,
+ NULL,
+ btm_ble_vendor_capability_vsc_cmpl_cback)
+ != BTM_CMD_STARTED)
+ {
+ BTM_TRACE_ERROR0("LE Get_Vendor Capabilities Command Failed.");
+ }
+ return ;
+}
+
+/*******************************************************************************
+**
** Function BTM_RegisterScanReqEvt
**
** Description This function is called to register a scan request callback
@@ -309,7 +508,43 @@
#endif
}
-#if BTM_BLE_PRIVACY_SPT == TRUE
+#if BLE_PRIVACY_SPT == TRUE
+/*******************************************************************************
+**
+** Function BTM_BleConfigPrivacy
+**
+** Description This function is called to enable or disable the privacy in
+** LE channel of 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");
+
+ if (p_cb->privacy != enable)
+ {
+ p_cb->privacy = enable;
+
+ if (p_cb->privacy)
+ {
+ /* generate resolvable private address */
+ btm_gen_resolvable_private_addr(NULL);
+ }
+ else /* if privacy disabled, always use public address */
+ {
+ p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
+ }
+ btm_ble_multi_adv_enb_privacy(p_cb->privacy);
+ }
+}
+
+
/*******************************************************************************
**
** Function btm_ble_resolve_random_addr_on_adv
@@ -486,11 +721,13 @@
{
UINT8 evt_type;
+ UNUSED(p_own_addr_type);
+
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;
+ is not enabled or no reconn addr config */
+
*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;
@@ -498,6 +735,16 @@
else /* undirect adv mode */
{
evt_type = BTM_BLE_CONNECT_EVT;
+
+#if BLE_PRIVACY_SPT == TRUE
+ /* may need to reset random address if privacy is enabled */
+ if (btm_cb.ble_ctr_cb.privacy && /* own addr_type is random */
+ !BTM_BLE_IS_RESOLVE_BDA(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr))
+ {
+ /* need to generate RRA and update random addresss in controller */
+ btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
+ }
+#endif
}
return evt_type;
@@ -704,7 +951,7 @@
{
tBTM_BLE_LOCAL_ADV_DATA *p_cb_data = &btm_cb.ble_ctr_cb.inq_var.adv_data;
UINT8 *p;
- UINT16 mask = data_mask;
+ tBTM_BLE_AD_MASK mask = data_mask;
BTM_TRACE_EVENT0 ("BTM_BleWriteAdvData ");
@@ -719,7 +966,7 @@
p_cb_data->p_pad = p;
- if (data_mask != 0)
+ if (mask != 0)
{
BTM_TRACE_ERROR0("Partial data write into ADV");
}
@@ -780,9 +1027,10 @@
**
** Description This function is called build the adv data and rsp data.
*******************************************************************************/
-static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data)
+UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
+ tBTM_BLE_ADV_DATA *p_data)
{
- UINT16 data_mask = *p_data_mask;
+ UINT32 data_mask = *p_data_mask;
UINT8 *p = *p_dst,
*p_flag = NULL;
UINT16 len = BTM_BLE_AD_DATA_LEN, cp_len = 0;
@@ -797,7 +1045,7 @@
/* flags */
if (data_mask & BTM_BLE_AD_BIT_FLAGS)
{
- *p++ = 2;
+ *p++ = MIN_ADV_LENGTH;
*p++ = BTM_BLE_AD_TYPE_FLAG;
p_flag = p;
if (p_data)
@@ -821,13 +1069,13 @@
}
/* device name */
#if BTM_MAX_LOC_BD_NAME_LEN > 0
- if (len > 2 && data_mask & BTM_BLE_AD_BIT_DEV_NAME)
+ if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_DEV_NAME)
{
- if (strlen(btm_cb.cfg.bd_name) > (UINT16)(len - 2))
+ if (strlen(btm_cb.cfg.bd_name) > (UINT16)(len - MIN_ADV_LENGTH))
{
- *p++ = len - 2 + 1;
+ *p++ = len - MIN_ADV_LENGTH + 1;
*p++ = BTM_BLE_AD_TYPE_NAME_SHORT;
- ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, len - 2);
+ ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, len - MIN_ADV_LENGTH);
}
else
{
@@ -836,61 +1084,180 @@
*p++ = BTM_BLE_AD_TYPE_NAME_CMPL;
ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, cp_len);
}
- len -= (cp_len + 2);
+ len -= (cp_len + MIN_ADV_LENGTH);
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)
+ if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_MANU &&
+ p_data && p_data->p_manu &&
+ p_data->p_manu->len != 0 && p_data->p_manu->p_val)
{
- if (p_data->manu.len > (len - 2))
- cp_len = len - 2;
+ if (p_data->p_manu->len > (len - MIN_ADV_LENGTH))
+ cp_len = len - MIN_ADV_LENGTH;
else
- cp_len = p_data->manu.len;
+ cp_len = p_data->p_manu->len;
*p++ = cp_len + 1;
*p++ = BTM_BLE_AD_TYPE_MANU;
- ARRAY_TO_STREAM(p, p_data->manu.p_val, cp_len);
+ ARRAY_TO_STREAM(p, p_data->p_manu->p_val, cp_len);
- len -= (cp_len + 2);
+ len -= (cp_len + MIN_ADV_LENGTH);
data_mask &= ~BTM_BLE_AD_BIT_MANU;
}
/* TX power */
- if (len > 2 && data_mask & BTM_BLE_AD_BIT_TX_PWR)
+ if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_TX_PWR)
{
- *p++ = 2;
+ *p++ = MIN_ADV_LENGTH;
*p++ = BTM_BLE_AD_TYPE_TX_PWR;
- *p++ = btm_cb.ble_ctr_cb.inq_var.tx_power;
+ *p++ = p_data->tx_power;
len -= 3;
data_mask &= ~BTM_BLE_AD_BIT_TX_PWR;
}
- /* services */
- if (len > 2 && data_mask & BTM_BLE_AD_BIT_SERVICE &&
- p_data && p_data->services.num_service != 0 &&
- p_data->services.p_uuid)
+ /* 16 bits services */
+ if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE &&
+ p_data && p_data->p_services &&
+ p_data->p_services->num_service != 0 &&
+ p_data->p_services->p_uuid)
{
- if (p_data->services.num_service * 2 > (len - 2))
+ if (p_data->p_services->num_service * LEN_UUID_16 > (len - MIN_ADV_LENGTH))
{
- cp_len = (len - 2)/2;
- *p ++ = 1 + cp_len * 2;
+ cp_len = (len - MIN_ADV_LENGTH)/LEN_UUID_16;
+ *p ++ = 1 + cp_len * LEN_UUID_16;
*p++ = BTM_BLE_AD_TYPE_16SRV_PART;
}
else
{
- cp_len = p_data->services.num_service;
- *p++ = 1 + cp_len * 2;
+ cp_len = p_data->p_services->num_service;
+ *p++ = 1 + cp_len * LEN_UUID_16;
*p++ = BTM_BLE_AD_TYPE_16SRV_CMPL;
}
for (i = 0; i < cp_len; i ++)
{
- UINT16_TO_STREAM(p, *(p_data->services.p_uuid + i));
+ UINT16_TO_STREAM(p, *(p_data->p_services->p_uuid + i));
}
- len -= (cp_len * 2 + 2);
+ len -= (cp_len * MIN_ADV_LENGTH + MIN_ADV_LENGTH);
data_mask &= ~BTM_BLE_AD_BIT_SERVICE;
}
+ /* 32 bits service uuid */
+ if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE_32 &&
+ p_data && p_data->p_service_32b &&
+ p_data->p_service_32b->num_service != 0 &&
+ p_data->p_service_32b->p_uuid)
+ {
+ if ((p_data->p_service_32b->num_service * LEN_UUID_32) > (len - MIN_ADV_LENGTH))
+ {
+ cp_len = (len - MIN_ADV_LENGTH)/LEN_UUID_32;
+ *p ++ = 1 + cp_len * LEN_UUID_32;
+ *p++ = BTM_BLE_AD_TYPE_32SRV_PART;
+ }
+ else
+ {
+ cp_len = p_data->p_service_32b->num_service;
+ *p++ = 1 + cp_len * LEN_UUID_32;
+ *p++ = BTM_BLE_AD_TYPE_32SRV_CMPL;
+ }
+ for (i = 0; i < cp_len; i ++)
+ {
+ UINT32_TO_STREAM(p, *(p_data->p_service_32b->p_uuid + i));
+ }
+
+ len -= (cp_len * LEN_UUID_32 + MIN_ADV_LENGTH);
+ data_mask &= ~BTM_BLE_AD_BIT_SERVICE_32;
+ }
+ /* 128 bits services */
+ if (len >= (MAX_UUID_SIZE + 2) && data_mask & BTM_BLE_AD_BIT_SERVICE_128 &&
+ p_data && p_data->p_services_128b)
+ {
+ *p ++ = 1 + MAX_UUID_SIZE;
+ if (!p_data->p_services_128b->list_cmpl)
+ *p++ = BTM_BLE_AD_TYPE_128SRV_PART;
+ else
+ *p++ = BTM_BLE_AD_TYPE_128SRV_CMPL;
+
+ ARRAY_TO_STREAM(p, p_data->p_services_128b->uuid128, MAX_UUID_SIZE);
+
+ len -= (MAX_UUID_SIZE + MIN_ADV_LENGTH);
+ data_mask &= ~BTM_BLE_AD_BIT_SERVICE_128;
+ }
+ /* 32 bits Service Solicitation UUIDs */
+ if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE_32SOL &&
+ p_data && p_data->p_sol_service_32b &&
+ p_data->p_sol_service_32b->num_service != 0 &&
+ p_data->p_sol_service_32b->p_uuid)
+ {
+ if ((p_data->p_sol_service_32b->num_service * LEN_UUID_32) > (len - MIN_ADV_LENGTH))
+ {
+ cp_len = (len - MIN_ADV_LENGTH)/LEN_UUID_32;
+ *p ++ = 1 + cp_len * LEN_UUID_32;
+ }
+ else
+ {
+ cp_len = p_data->p_sol_service_32b->num_service;
+ *p++ = 1 + cp_len * LEN_UUID_32;
+ }
+
+ *p++ = BTM_BLE_AD_TYPE_32SOL_SRV_UUID;
+ for (i = 0; i < cp_len; i ++)
+ {
+ UINT32_TO_STREAM(p, *(p_data->p_sol_service_32b->p_uuid + i));
+ }
+
+ len -= (cp_len * LEN_UUID_32 + MIN_ADV_LENGTH);
+ data_mask &= ~BTM_BLE_AD_BIT_SERVICE_32SOL;
+ }
+ /* 128 bits Solicitation services UUID */
+ if (len >= (MAX_UUID_SIZE + MIN_ADV_LENGTH) && data_mask & BTM_BLE_AD_BIT_SERVICE_128SOL &&
+ p_data && p_data->p_sol_service_128b)
+ {
+ *p ++ = 1 + MAX_UUID_SIZE;
+ *p++ = BTM_BLE_AD_TYPE_128SOL_SRV_UUID;
+ ARRAY_TO_STREAM(p, p_data->p_sol_service_128b->uuid128, MAX_UUID_SIZE);
+ len -= (MAX_UUID_SIZE + MIN_ADV_LENGTH);
+ data_mask &= ~BTM_BLE_AD_BIT_SERVICE_128SOL;
+ }
+ /* 16bits/32bits/128bits Service Data */
+ if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE_DATA &&
+ p_data && p_data->p_service_data->len != 0 && p_data->p_service_data->p_val)
+ {
+ if (len > (p_data->p_service_data->service_uuid.len + MIN_ADV_LENGTH))
+ {
+ if (p_data->p_service_data->len > (len - MIN_ADV_LENGTH))
+ cp_len = len - MIN_ADV_LENGTH- p_data->p_service_data->service_uuid.len;
+ else
+ cp_len = p_data->p_service_data->len;
+
+ *p++ = cp_len + 1 + p_data->p_service_data->service_uuid.len;
+ if (p_data->p_service_data->service_uuid.len == LEN_UUID_16)
+ {
+ *p++ = BTM_BLE_AD_TYPE_SERVICE_DATA;
+ UINT16_TO_STREAM(p, p_data->p_service_data->service_uuid.uu.uuid16);
+ }
+ else if (p_data->p_service_data->service_uuid.len == LEN_UUID_32)
+ {
+ *p++ = BTM_BLE_AD_TYPE_32SERVICE_DATA;
+ UINT32_TO_STREAM(p, p_data->p_service_data->service_uuid.uu.uuid32);
+ }
+ else
+ {
+ *p++ = BTM_BLE_AD_TYPE_128SERVICE_DATA;
+ ARRAY_TO_STREAM(p, p_data->p_service_data->service_uuid.uu.uuid128,
+ LEN_UUID_128);
+ }
+
+ ARRAY_TO_STREAM(p, p_data->p_service_data->p_val, cp_len);
+
+ len -= (cp_len + MIN_ADV_LENGTH + p_data->p_service_data->service_uuid.len);
+ data_mask &= ~BTM_BLE_AD_BIT_SERVICE_DATA;
+ }
+ else
+ {
+ BTM_TRACE_WARNING0("service data does not fit");
+ }
+ }
+
if (len >= 6 && data_mask & BTM_BLE_AD_BIT_INT_RANGE &&
p_data)
{
@@ -907,13 +1274,14 @@
{
p_elem = p_data->p_proprietary->p_elem + i;
- if (len >= (2 + p_elem->len))/* len byte(1) + ATTR type(1) + Uuid len(2) + value length */
+ if (len >= (MIN_ADV_LENGTH + p_elem->len))/* len byte(1) + ATTR type(1) + Uuid len(2)
+ + value length */
{
*p ++ = p_elem->len + 1; /* Uuid len + value length */
*p ++ = p_elem->adv_type;
ARRAY_TO_STREAM(p, p_elem->p_val, p_elem->len);
- len -= (2 + p_elem->len);
+ len -= (MIN_ADV_LENGTH + p_elem->len);
}
else
{
@@ -930,16 +1298,108 @@
return p_flag;
}
+/*******************************************************************************
+**
+** Function btm_ble_select_adv_interval
+**
+** Description select adv interval based on device mode
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 *p_adv_int_min, UINT16 *p_adv_int_max)
+{
+ if (p_cb->adv_interval_min && p_cb->adv_interval_max)
+ {
+ *p_adv_int_min = p_cb->adv_interval_min;
+ *p_adv_int_max = p_cb->adv_interval_max;
+ }
+ else
+ {
+ switch (evt_type)
+ {
+ case BTM_BLE_CONNECT_EVT:
+ *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_1;
+ break;
+ case BTM_BLE_NON_CONNECT_EVT:
+ case BTM_BLE_DISCOVER_EVT:
+ *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_2;
+ break;
+ /* connectable directed event */
+ case BTM_BLE_CONNECT_DIR_EVT:
+ *p_adv_int_min = BTM_BLE_GAP_ADV_DIR_MIN_INT;
+ *p_adv_int_max = BTM_BLE_GAP_ADV_DIR_MAX_INT;
+ break;
+
+ default:
+ *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_SLOW_INT;
+ break;
+ }
+ }
+ return;
+}
+/*******************************************************************************
+**
+** Function btm_ble_set_adv_flag
+**
+** Description Set adv flag in adv data.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_set_adv_flag(UINT16 connect_mode, UINT16 disc_mode)
+{
+ UINT8 flag = 0, old_flag = 0;
+ tBTM_BLE_LOCAL_ADV_DATA *p_adv_data = &btm_cb.ble_ctr_cb.inq_var.adv_data;
+
+ if (p_adv_data->p_flags != NULL)
+ flag = old_flag = *(p_adv_data->p_flags);
+
+ /* BR/EDR non-discoverable , non-connectable */
+ if ((disc_mode & BTM_DISCOVERABLE_MASK) == 0 &&
+ (connect_mode & BTM_CONNECTABLE_MASK) == 0)
+ flag |= BTM_BLE_BREDR_NOT_SPT;
+ else
+ flag &= ~BTM_BLE_BREDR_NOT_SPT;
+
+ /* if local controller support, mark both controller and host support in flag */
+ if (HCI_SIMUL_LE_BREDR_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
+ flag |= (BTM_BLE_DMT_CONTROLLER_SPT|BTM_BLE_DMT_HOST_SPT);
+ else
+ flag &= ~(BTM_BLE_DMT_CONTROLLER_SPT|BTM_BLE_DMT_HOST_SPT);
+
+ BTM_TRACE_ERROR1("disc_mode %04x", disc_mode);
+ /* update discoverable flag */
+ if (disc_mode & BTM_BLE_LIMITED_DISCOVERABLE)
+ {
+ flag &= ~BTM_BLE_GEN_DISC_FLAG;
+ flag |= BTM_BLE_LIMIT_DISC_FLAG ;
+ }
+ else if (disc_mode & BTM_BLE_GENERAL_DISCOVERABLE)
+ {
+ flag |= BTM_BLE_GEN_DISC_FLAG;
+ flag &= ~BTM_BLE_LIMIT_DISC_FLAG;
+ }
+ else /* remove all discoverable flags */
+ {
+ flag &= ~(BTM_BLE_LIMIT_DISC_FLAG|BTM_BLE_GEN_DISC_FLAG);
+ }
+
+ if (flag != old_flag)
+ {
+ btm_ble_update_adv_flag(flag);
+ }
+}
/*******************************************************************************
**
** Function btm_ble_set_discoverability
**
** Description This function is called to set BLE discoverable mode.
**
-** Parameters: mode: discoverability mode.
+** Parameters: combined_mode: discoverability mode.
**
-** Returns void
+** Returns BTM_SUCCESS is status set successfully; otherwise failure.
**
*******************************************************************************/
tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
@@ -947,7 +1407,6 @@
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;
UINT8 new_mode = BTM_BLE_ADV_ENABLE;
UINT8 evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \
((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
@@ -955,7 +1414,8 @@
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;;
+ own_addr_type = p_addr_cb->own_addr_type;
+ UINT16 adv_int_min, adv_int_max;
BTM_TRACE_EVENT2 ("btm_ble_set_discoverability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
@@ -963,56 +1423,28 @@
if (mode > BTM_BLE_MAX_DISCOVERABLE)
return(BTM_ILLEGAL_VALUE);
- p_cb->br_edr_supported_flag |= (combined_mode & BTM_DISCOVERABLE_MASK);
- p_cb->discoverable_mode = mode;
+ btm_ble_set_adv_flag (btm_cb.btm_inq_vars.connectable_mode, combined_mode);
- if (!p_cb->br_edr_supported_flag)
- {
- flag = BTM_BLE_BREDR_NOT_SPT;
- BTM_TRACE_DEBUG1("btm_ble_set_discoverability (BREDR not sup)flag=0x%x",flag);
- }
+ evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
- BTM_TRACE_DEBUG1 ("br_edr_supported=0x%x", p_cb->br_edr_supported_flag);
+ if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE && mode == BTM_BLE_NON_DISCOVERABLE)
+ new_mode = BTM_BLE_ADV_DISABLE;
- if (mode == BTM_BLE_LIMITED_DISCOVERABLE || mode == BTM_BLE_GENERAL_DISCOVERABLE)
- {
- BTM_TRACE_EVENT0 ("mode == BTM_BLE_LIMITED_DISCOVERABLE ");
- /* write ADV data with limited disc flag */
- if (mode == BTM_BLE_LIMITED_DISCOVERABLE)
- flag |= BTM_BLE_LIMIT_DISC_FLAG ;
- else
- flag |= BTM_BLE_GEN_DISC_FLAG;
- }
- else /* non-discoverable */
- {
- BTM_TRACE_EVENT0 ("mode == BTM_BLE_NON_DISCOVERABLE ");
+ btm_ble_select_adv_interval(p_cb, evt_type, &adv_int_min, &adv_int_max);
- if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE)
- {
- p_cb->br_edr_supported_flag = 0;
-
- 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
- {
- 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);
+ btu_stop_timer(&p_cb->fast_adv_timer);
/* 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 ||p_cb->adv_addr_type != own_addr_type))
+ (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type || !p_cb->fast_adv_on))
{
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),
+ if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
+ adv_int_max,
evt_type,
own_addr_type,
init_addr_type,
@@ -1036,11 +1468,18 @@
else
status = btm_ble_stop_adv();
}
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
+ {
+ p_cb->fast_adv_on = TRUE;
+ /* start initial GAP mode adv timer */
+ btu_start_timer (&p_cb->fast_adv_timer, BTU_TTYPE_BLE_GAP_FAST_ADV,
+ BTM_BLE_GAP_FAST_ADV_TOUT);
+ }
/* set up stop advertising timer */
if (status == BTM_SUCCESS && mode == BTM_BLE_LIMITED_DISCOVERABLE)
{
- BTM_TRACE_EVENT1 ("start timer for limited disc mode duration=%d (30 secs)", BTM_BLE_GAP_LIM_TOUT);
+ BTM_TRACE_EVENT1 ("start timer for limited disc mode duration=%d (180 secs)", BTM_BLE_GAP_LIM_TOUT);
/* start Tgap(lim_timeout) */
btu_start_timer (&p_cb->inq_timer_ent, BTU_TTYPE_BLE_GAP_LIM_DISC,
BTM_BLE_GAP_LIM_TOUT);
@@ -1054,9 +1493,9 @@
**
** Description This function is called to set BLE connectability mode.
**
-** Parameters: mode: connectability mode.
+** Parameters: combined_mode: connectability mode.
**
-** Returns void
+** Returns BTM_SUCCESS is status set successfully; otherwise failure.
**
*******************************************************************************/
tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
@@ -1064,57 +1503,39 @@
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;
- UINT8 cur_br_edr_not_sup_flag;
- UINT8 new_flag;
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;
+ UINT16 adv_int_min, adv_int_max;
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);
- if (btm_cb.ble_ctr_cb.inq_var.adv_data.p_flags)
- cur_flag = *btm_cb.ble_ctr_cb.inq_var.adv_data.p_flags ;
- cur_br_edr_not_sup_flag = (cur_flag & ((UINT8) BTM_BLE_BREDR_NOT_SPT));
- p_cb->br_edr_supported_flag |= ((combined_mode & BTM_CONNECTABLE_MASK) << 4);
- if (p_cb->br_edr_supported_flag && cur_br_edr_not_sup_flag)
- {
- new_flag = cur_flag & ((UINT8) (~BTM_BLE_BREDR_NOT_SPT));
- BTM_TRACE_EVENT2 ("new flag=0x%x cur flag=0x%x",new_flag, cur_flag);
- btm_ble_update_adv_flag(new_flag);
- }
p_cb->connectable_mode = mode;
- if (mode == BTM_BLE_NON_CONNECTABLE)
- {
- if (p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE)
- {
- p_cb->br_edr_supported_flag = 0;
- 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;
+ btm_ble_set_adv_flag (combined_mode, btm_cb.btm_inq_vars.discoverable_mode);
- }
- }
- else /* connectable */
- {
- evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
- }
+ evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
+ if (mode == BTM_BLE_NON_CONNECTABLE && p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE)
+ new_mode = BTM_BLE_ADV_DISABLE;
+
+ btm_ble_select_adv_interval(p_cb, evt_type, &adv_int_min, &adv_int_max);
+
+ btu_stop_timer(&p_cb->fast_adv_timer);
/* update adv params if needed */
- 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->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type || !p_cb->fast_adv_on))
{
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),
+ if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
+ adv_int_max,
evt_type,
own_addr_type,
init_addr_type,
@@ -1132,24 +1553,22 @@
/* update advertising mode */
if (status == BTM_SUCCESS && new_mode != p_cb->adv_mode)
{
- if (btsnd_hcic_ble_set_adv_enable (new_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;
-
- }
+ if (new_mode == BTM_BLE_ADV_ENABLE)
+ status = btm_ble_start_adv();
+ else
+ status = btm_ble_stop_adv();
}
-
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
+ {
+ p_cb->fast_adv_on = TRUE;
+ /* start initial GAP mode adv timer */
+ btu_start_timer (&p_cb->fast_adv_timer, BTU_TTYPE_BLE_GAP_FAST_ADV,
+ BTM_BLE_GAP_FAST_ADV_TOUT);
+ }
return status;
}
+
/*******************************************************************************
**
** Function btm_ble_start_inquiry
@@ -1171,24 +1590,39 @@
*******************************************************************************/
tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration)
{
- tBTM_STATUS status = BTM_NO_RESOURCES;
- tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
+ tBTM_STATUS status = BTM_CMD_STARTED;
+ tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb;
+ tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
- BTM_TRACE_DEBUG2("btm_ble_start_inquiry: mode = %02x inq_active = %d", mode, btm_cb.btm_inq_vars.inq_active);
+ BTM_TRACE_DEBUG2("btm_ble_start_inquiry: mode = %02x inq_active = 0x%02x", mode, btm_cb.btm_inq_vars.inq_active);
- if (p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
+ /* if selective connection is active, or inquiry is already active, reject it */
+ if (BTM_BLE_IS_INQ_ACTIVE(p_ble_cb->scan_activity) ||
+ BTM_BLE_IS_SEL_CONN_ACTIVE (p_ble_cb->scan_activity))
{
- BTM_TRACE_ERROR0("LE scan is active, can not start inquiry");
+ BTM_TRACE_ERROR0("LE Inquiry is active, can not start inquiry");
return(BTM_BUSY);
}
- btm_update_scanner_filter_policy(SP_ADV_ALL);
-
- /* start scan, already enable duplicate filtering */
- if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE))
+ if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
{
- status = BTM_CMD_STARTED;
- p_inq->proc_mode = mode;
+ btm_update_scanner_filter_policy(SP_ADV_ALL);
+
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+ /* enable IRK list */
+ btm_ble_vendor_irk_list_known_dev (TRUE);
+#endif
+#endif
+ status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
+ }
+
+ if (status == BTM_CMD_STARTED)
+ {
+ p_inq->inq_active |= mode;
+ p_ble_cb->scan_activity |= mode;
+
+ BTM_TRACE_DEBUG1("btm_ble_start_inquiry inq_active = 0x%02x", p_inq->inq_active);
if (duration != 0)
{
@@ -1198,6 +1632,7 @@
}
return status;
+
}
/*******************************************************************************
@@ -1215,6 +1650,10 @@
BD_NAME bd_name;
memset(bd_name, 0, (BD_NAME_LEN + 1));
+ if (length > BD_NAME_LEN)
+ {
+ length = BD_NAME_LEN;
+ }
memcpy((UINT8*)bd_name, p_name, length);
if ((!status) || (length==0))
@@ -1504,68 +1943,181 @@
** Returns void
**
*******************************************************************************/
-BOOLEAN btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p)
+UINT8 btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p)
{
- BOOLEAN is_discoverable = FALSE;
- UINT8 *p_flag, flag = 0;
+ UINT8 *p_flag, flag = 0, rt = 0;
UINT8 data_len;
tBTM_INQ_PARMS *p_cond = &btm_cb.btm_inq_vars.inqparms;
+ tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
- STREAM_TO_UINT8 (data_len, p);
+ UNUSED(p);
/* for observer, always "discoverable */
- if (btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_OBSERVE ||
- (btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_SELECT_SCAN &&
- btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE))
- return TRUE;
+ if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
+ rt |= BTM_BLE_OBS_RESULT;
+
+ if (BTM_BLE_IS_SEL_CONN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity) &&
+ (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT))
+ rt |= BTM_BLE_SEL_CONN_RESULT;
/* does not match filter condition */
if (p_cond->filter_cond_type == BTM_FILTER_COND_BD_ADDR &&
memcmp(bda, p_cond->filter_cond.bdaddr_cond, BD_ADDR_LEN) != 0)
{
BTM_TRACE_DEBUG0("BD ADDR does not meet filter condition");
- return FALSE;
+ return rt;
}
- /* scan response does not include the flag */
- if (evt_type == BTM_BLE_SCAN_RSP_EVT)
- return FALSE;
-
- if (data_len > BTM_BLE_ADV_DATA_LEN_MAX)
+ if (p_le_inq_cb->adv_len != 0)
{
- BTM_TRACE_WARNING1("ADV data too long %d. discard", data_len);
- return FALSE;
- }
-
- if (data_len != 0)
- {
- if ((p_flag = BTM_CheckAdvData(p, BTM_BLE_AD_TYPE_FLAG, &data_len)) != NULL)
+ if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache,
+ BTM_BLE_AD_TYPE_FLAG, &data_len)) != NULL)
{
flag = * p_flag;
- if ((btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_GENERAL_INQUIRY) &&
+ if ((btm_cb.btm_inq_vars.inq_active & BTM_BLE_GENERAL_INQUIRY) &&
(flag & (BTM_BLE_LIMIT_DISC_FLAG|BTM_BLE_GEN_DISC_FLAG)) != 0)
{
BTM_TRACE_DEBUG0("Find Generable Discoverable device");
- is_discoverable = TRUE;
+ rt |= BTM_BLE_INQ_RESULT;
}
- else if (btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_LIMITED_INQUIRY &&
+ else if (btm_cb.btm_inq_vars.inq_active & BTM_BLE_LIMITED_INQUIRY &&
(flag & BTM_BLE_LIMIT_DISC_FLAG) != 0)
{
BTM_TRACE_DEBUG0("Find limited discoverable device");
- is_discoverable = TRUE;
+ rt |= BTM_BLE_INQ_RESULT;
}
-
}
}
+ return rt;
+}
- if (!is_discoverable)
+static void btm_ble_appearance_to_cod(UINT16 appearance, UINT8 *dev_class)
+{
+ dev_class[0] = 0;
+
+ switch (appearance)
{
- BTM_TRACE_ERROR1("discoverable flag not desired: %d", flag);
- }
-
- return is_discoverable;
+ case BTM_BLE_APPEARANCE_GENERIC_PHONE:
+ dev_class[1] = BTM_COD_MAJOR_PHONE;
+ dev_class[2] = BTM_COD_MINOR_UNCLASSIFIED;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_COMPUTER:
+ dev_class[1] = BTM_COD_MAJOR_COMPUTER;
+ dev_class[2] = BTM_COD_MINOR_UNCLASSIFIED;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_REMOTE:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_REMOTE_CONTROL;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_THERMOMETER:
+ case BTM_BLE_APPEARANCE_THERMOMETER_EAR:
+ dev_class[1] = BTM_COD_MAJOR_HEALTH;
+ dev_class[2] = BTM_COD_MINOR_THERMOMETER;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_HEART_RATE:
+ case BTM_BLE_APPEARANCE_HEART_RATE_BELT:
+ dev_class[1] = BTM_COD_MAJOR_HEALTH;
+ dev_class[2] = BTM_COD_MINOR_HEART_PULSE_MONITOR;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE:
+ case BTM_BLE_APPEARANCE_BLOOD_PRESSURE_ARM:
+ case BTM_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST:
+ dev_class[1] = BTM_COD_MAJOR_HEALTH;
+ dev_class[2] = BTM_COD_MINOR_BLOOD_MONITOR;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER:
+ case BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP:
+ case BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST:
+ dev_class[1] = BTM_COD_MAJOR_HEALTH;
+ dev_class[2] = BTM_COD_MINOR_PULSE_OXIMETER;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_GLUCOSE:
+ dev_class[1] = BTM_COD_MAJOR_HEALTH;
+ dev_class[2] = BTM_COD_MINOR_GLUCOSE_METER;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_WEIGHT:
+ dev_class[1] = BTM_COD_MAJOR_HEALTH;
+ dev_class[2] = BTM_COD_MINOR_WEIGHING_SCALE;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_WALKING:
+ case BTM_BLE_APPEARANCE_WALKING_IN_SHOE:
+ case BTM_BLE_APPEARANCE_WALKING_ON_SHOE:
+ case BTM_BLE_APPEARANCE_WALKING_ON_HIP:
+ dev_class[1] = BTM_COD_MAJOR_HEALTH;
+ dev_class[2] = BTM_COD_MINOR_STEP_COUNTER;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_WATCH:
+ case BTM_BLE_APPEARANCE_SPORTS_WATCH:
+ dev_class[1] = BTM_COD_MAJOR_WEARABLE;
+ dev_class[2] = BTM_COD_MINOR_WRIST_WATCH;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_EYEGLASSES:
+ dev_class[1] = BTM_COD_MAJOR_WEARABLE;
+ dev_class[2] = BTM_COD_MINOR_GLASSES;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_DISPLAY:
+ dev_class[1] = BTM_COD_MAJOR_IMAGING;
+ dev_class[2] = BTM_COD_MINOR_DISPLAY;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER:
+ dev_class[1] = BTM_COD_MAJOR_AUDIO;
+ dev_class[2] = BTM_COD_MINOR_UNCLASSIFIED;
+ break;
+ case BTM_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER:
+ case BTM_BLE_APPEARANCE_HID_BARCODE_SCANNER:
+ case BTM_BLE_APPEARANCE_GENERIC_HID:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_UNCLASSIFIED;
+ break;
+ case BTM_BLE_APPEARANCE_HID_KEYBOARD:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_KEYBOARD;
+ break;
+ case BTM_BLE_APPEARANCE_HID_MOUSE:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_POINTING;
+ break;
+ case BTM_BLE_APPEARANCE_HID_JOYSTICK:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_JOYSTICK;
+ break;
+ case BTM_BLE_APPEARANCE_HID_GAMEPAD:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_GAMEPAD;
+ break;
+ case BTM_BLE_APPEARANCE_HID_DIGITIZER_TABLET:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_DIGITIZING_TABLET;
+ break;
+ case BTM_BLE_APPEARANCE_HID_CARD_READER:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_CARD_READER;
+ break;
+ case BTM_BLE_APPEARANCE_HID_DIGITAL_PEN:
+ dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ dev_class[2] = BTM_COD_MINOR_DIGITAL_PAN;
+ break;
+ case BTM_BLE_APPEARANCE_UKNOWN:
+ case BTM_BLE_APPEARANCE_GENERIC_CLOCK:
+ case BTM_BLE_APPEARANCE_GENERIC_TAG:
+ case BTM_BLE_APPEARANCE_GENERIC_KEYRING:
+ case BTM_BLE_APPEARANCE_GENERIC_CYCLING:
+ case BTM_BLE_APPEARANCE_CYCLING_COMPUTER:
+ case BTM_BLE_APPEARANCE_CYCLING_SPEED:
+ case BTM_BLE_APPEARANCE_CYCLING_CADENCE:
+ case BTM_BLE_APPEARANCE_CYCLING_POWER:
+ case BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE:
+ case BTM_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS:
+ case BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION:
+ case BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV:
+ case BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD:
+ case BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV:
+ default:
+ dev_class[1] = BTM_COD_MAJOR_UNCLASSIFIED;
+ dev_class[2] = BTM_COD_MINOR_UNCLASSIFIED;
+ };
}
/*******************************************************************************
@@ -1638,19 +2190,31 @@
if (p_le_inq_cb->adv_len != 0)
{
- if ((p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache,
- BTM_BLE_AD_TYPE_16SRV_CMPL, &len)) != NULL)
+ /* Check to see the BLE device has the Appearance UUID in the advertising data. If it does
+ * then try to convert the appearance value to a class of device value Bluedroid can use.
+ * Otherwise fall back to trying to infer if it is a HID device based on the service class.
+ */
+ p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_APPEARANCE, &len);
+ if (p_uuid16 && len == 2)
{
- UINT8 i;
- for (i = 0; i + 2 <= len; i = i + 2)
+ btm_ble_appearance_to_cod((UINT16)p_uuid16[0] | (p_uuid16[1] << 8), p_cur->dev_class);
+ }
+ else
+ {
+ if ((p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache,
+ BTM_BLE_AD_TYPE_16SRV_CMPL, &len)) != NULL)
{
- /* if this BLE device support HID over LE, set HID Major in class of device */
- if ((p_uuid16[i] | (p_uuid16[i+1] << 8)) == UUID_SERVCLASS_LE_HID)
+ UINT8 i;
+ for (i = 0; i + 2 <= len; i = i + 2)
{
- p_cur->dev_class[0] = 0;
- p_cur->dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
- p_cur->dev_class[2] = 0;
- break;
+ /* if this BLE device support HID over LE, set HID Major in class of device */
+ if ((p_uuid16[i] | (p_uuid16[i+1] << 8)) == UUID_SERVCLASS_LE_HID)
+ {
+ p_cur->dev_class[0] = 0;
+ p_cur->dev_class[1] = BTM_COD_MAJOR_PERIPHERAL;
+ p_cur->dev_class[2] = 0;
+ break;
+ }
}
}
}
@@ -1738,49 +2302,63 @@
BD_ADDR bda;
UINT8 evt_type = 0, *p = p_data;
UINT8 addr_type = 0;
-#if (defined BTM_BLE_PRIVACY_SPT && BTM_BLE_PRIVACY_SPT == TRUE)
+ UINT8 num_reports;
+ UINT8 data_len;
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
BOOLEAN match = FALSE;
#endif
- /* always get one device at a time */
- p ++;
+ /* Extract the number of reports in this event. */
+ STREAM_TO_UINT8(num_reports, p);
- /* Extract inquiry results */
- STREAM_TO_UINT8 (evt_type, p);
- STREAM_TO_UINT8 (addr_type, p);
- STREAM_TO_BDADDR (bda, p);
+ while (num_reports--)
+ {
+ /* Extract inquiry results */
+ STREAM_TO_UINT8 (evt_type, p);
+ 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 */
- {
- if (btm_cb.ble_ctr_cb.p_scan_req_cback)
- (*btm_cb.ble_ctr_cb.p_scan_req_cback)(bda, addr_type, evt_type);
- }
+ 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
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+ /* map address to security record */
+ btm_public_addr_to_random_pseudo(bda, &addr_type);
+ BTM_TRACE_ERROR6("new address: %02x:%02x:%02x:%02x:%02x:%02x",
+ bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+#endif
+#endif
+ /* Only process the results if the inquiry is still active */
+ if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
+ return;
- /* Only process the results if the inquiry is still 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;
-
- BTM_TRACE_DEBUG6("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
+ BTM_TRACE_DEBUG6("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
-#if (defined BTM_BLE_PRIVACY_SPT && BTM_BLE_PRIVACY_SPT == TRUE)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
#if SMP_INCLUDED == TRUE
- /* always do RRA resolution on host */
- if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
- {
- btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_adv, p_data);
- }
- else
+ /* always do RRA resolution on host */
+ if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
+ {
+ btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_adv, p_data);
+ }
+ else
#endif
#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);
+ }
+
+ STREAM_TO_UINT8(data_len, p);
+
+ /* Advance to the next event data_len + rssi byte */
+ p += data_len + 1;
}
}
@@ -1799,13 +2377,12 @@
static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
{
tINQ_DB_ENT *p_i;
- BOOLEAN to_report = FALSE;
- BOOLEAN to_report_LE = TRUE; //var for reporting to LE observe
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
- tBTM_INQ_RESULTS_CB *p_inq_ble_results_cb = p_inq->p_inq_ble_results_cb;
+ tBTM_INQ_RESULTS_CB *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb;
tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
- BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: addr_type: %d, evt_type: %d", addr_type, evt_type);
+ BOOLEAN update = TRUE;
+ UINT8 result = 0;
p_i = btm_inq_db_find (bda);
@@ -1813,26 +2390,23 @@
if (btm_inq_find_bdaddr(bda))
{
/* never been report as an LE device */
- if ((p_i &&
+ if (p_i &&
(!(p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BLE) ||
/* scan repsonse to be updated */
(!p_i->scan_rsp)))
- ||
- btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_OBSERVE)
{
- BTM_TRACE_DEBUG0("update new BLE information ");
- to_report = TRUE;
+ update = TRUE;
+ }
+ else if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
+ {
+ update = FALSE;
}
else
{
- to_report = FALSE;
+ /* if yes, skip it */
+ return; /* assumption: one result per event */
}
}
- else /* not been processed in this round */
- {
- to_report = TRUE;
- }
-
/* If existing entry, use that, else get a new one (possibly reusing the oldest) */
if (p_i == NULL)
{
@@ -1842,25 +2416,22 @@
}
else
return;
-
- if (to_report && btm_ble_is_discoverable(bda, evt_type, p))
- {
- to_report = TRUE;
- }
- else
- {
- BTM_TRACE_ERROR0("discard adv pkt");
- to_report = FALSE;
- }
}
else if (p_i->inq_count != p_inq->inq_counter) /* first time seen in this inquiry */
{
p_inq->inq_cmpl_info.num_resp++;
}
/* update the LE device information in inquiry database */
- to_report_LE = btm_ble_update_inq_result(p_i, addr_type, evt_type, p);
- if (to_report)
- to_report = to_report_LE;
+ if (!btm_ble_update_inq_result(p_i, addr_type, evt_type, p))
+ return;
+
+ if ((result = btm_ble_is_discoverable(bda, evt_type, p)) == 0)
+ {
+ BTM_TRACE_ERROR0("discard adv pkt");
+ return;
+ }
+ if (!update)
+ result &= ~BTM_BLE_INQ_RESULT;
#if BTM_USE_INQ_RESULTS_FILTER == TRUE
/* If the number of responses found and limited, issue a cancel inquiry */
if (p_inq->inqparms.max_resps &&
@@ -1878,8 +2449,7 @@
(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) == 0)
btsnd_hcic_inq_cancel();
- /* stop LE scan now */
- btm_ble_stop_scan();
+ btm_ble_stop_inquiry();
#if BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE
btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT);
@@ -1887,32 +2457,58 @@
}
}
#endif
-
- BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: to_report =%d, to_report_le=%d",
- to_report, to_report_LE);
/* background connection in selective connection mode */
if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)
{
- 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))
+ if (result & BTM_BLE_SEL_CONN_RESULT)
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 (to_report || to_report_LE)
+ else
{
- if(p_inq_results_cb && to_report)
+ if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT))
+ {
(p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
- if(p_inq_ble_results_cb && to_report_LE)
- (p_inq_ble_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results,
- p_le_inq_cb->adv_data_cache);
+ }
+ if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT))
+ {
+ (p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+ }
}
}
/*******************************************************************************
**
+** Function btm_ble_start_scan
+**
+** Description Start the BLE scan.
+**
+** Returns void
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_start_scan (UINT8 filter_enable)
+{
+ tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
+ tBTM_STATUS status = BTM_CMD_STARTED;
+
+ /* start scan, disable duplicate filtering */
+ if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, filter_enable))
+ status = BTM_NO_RESOURCES;
+ else
+ {
+ if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI)
+ btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
+ else
+ btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT);
+ }
+ return status;
+}
+
+/*******************************************************************************
+**
** Function btm_ble_stop_scan
**
** Description Stop the BLE scan.
@@ -1922,44 +2518,135 @@
*******************************************************************************/
void btm_ble_stop_scan(void)
{
- tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
- tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
-
BTM_TRACE_EVENT0 ("btm_ble_stop_scan ");
- btu_stop_timer (&p_cb->inq_timer_ent);
-
/* Clear the inquiry callback if set */
- p_cb->scan_type = BTM_BLE_SCAN_MODE_NONE;
- p_cb->proc_mode = BTM_BLE_INQUIRY_NONE;
+ btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
/* stop discovery now */
btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+ btm_update_scanner_filter_policy(SP_ADV_ALL);
+}
+/*******************************************************************************
+**
+** Function btm_ble_stop_inquiry
+**
+** Description Stop the BLE Inquiry.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_stop_inquiry(void)
+{
+ tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
+ tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb;
+
+ btu_stop_timer (&p_ble_cb->inq_var.inq_timer_ent);
+
+ p_ble_cb->scan_activity &= ~BTM_BLE_INQUIRY_MASK;
+
+ /* If no more scan activity, stop LE scan now */
+ if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
+ btm_ble_stop_scan();
+
/* If we have a callback registered for inquiry complete, call it */
BTM_TRACE_DEBUG2 ("BTM Inq Compl Callback: status 0x%02x, num results %d",
p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp);
- btm_update_scanner_filter_policy(SP_ADV_ALL);
-
btm_process_inq_complete(HCI_SUCCESS, (UINT8)(p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK));
-
}
/*******************************************************************************
**
+** Function btm_ble_stop_observe
+**
+** Description Stop the BLE Observe.
+**
+** Returns void
+**
+*******************************************************************************/
+static void btm_ble_stop_observe(void)
+{
+ tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
+ tBTM_CMPL_CB *p_obs_cb = p_ble_cb->p_obs_cmpl_cb;
+
+ btu_stop_timer (&p_ble_cb->obs_timer_ent);
+
+ p_ble_cb->scan_activity &= ~BTM_LE_OBSERVE_ACTIVE;
+
+ p_ble_cb->p_obs_results_cb = NULL;
+ p_ble_cb->p_obs_cmpl_cb = NULL;
+
+ if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
+ btm_ble_stop_scan();
+
+ if (p_obs_cb)
+ (p_obs_cb)((tBTM_INQUIRY_CMPL *) &btm_cb.btm_inq_vars.inq_cmpl_info);
+}
+/*******************************************************************************
+**
+** Function btm_ble_adv_states_operation
+**
+** Description Set or clear adv states in topology mask
+**
+** Returns operation status. TRUE if sucessful, FALSE otherwise.
+**
+*******************************************************************************/
+typedef BOOLEAN (BTM_TOPOLOGY_FUNC_PTR)(tBTM_BLE_STATE_MASK);
+static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UINT8 adv_evt)
+{
+ BOOLEAN rt = FALSE;
+
+ switch (adv_evt)
+ {
+ case BTM_BLE_CONNECT_EVT:
+ rt = (*p_handler)(BTM_BLE_STATE_CONN_ADV_BIT);
+ break;
+
+ case BTM_BLE_NON_CONNECT_EVT:
+ rt = (*p_handler) (BTM_BLE_STATE_NON_CONN_ADV_BIT);
+ break;
+ case BTM_BLE_CONNECT_DIR_EVT:
+ rt = (*p_handler) (BTM_BLE_STATE_HI_DUTY_DIR_ADV_BIT);
+ break;
+
+ case BTM_BLE_DISCOVER_EVT:
+ rt = (*p_handler) (BTM_BLE_STATE_SCAN_ADV_BIT);
+ break;
+
+ default:
+ BTM_TRACE_ERROR1("unknown adv event : %d", adv_evt);
+ break;
+ }
+
+ return rt;
+}
+
+
+/*******************************************************************************
+**
** Function btm_ble_start_adv
**
-** Description Stop the BLE advertising.
+** Description start the BLE advertising.
**
** Returns void
**
*******************************************************************************/
-static tBTM_STATUS btm_ble_start_adv(void)
+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 (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type))
+ return BTM_WRONG_MODE;
+
+ if (p_cb->afp != AP_SCAN_CONN_ALL)
+ {
+ btm_execute_wl_dev_operation();
+ btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
+ }
+
if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
{
if (p_cb->afp != AP_SCAN_CONN_ALL)
@@ -1968,13 +2655,13 @@
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;
+ }
+ else
+ {
+ p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+ }
+ return rt;
}
/*******************************************************************************
**
@@ -1985,7 +2672,7 @@
** Returns void
**
*******************************************************************************/
-static tBTM_STATUS btm_ble_stop_adv(void)
+tBTM_STATUS btm_ble_stop_adv(void)
{
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS rt = BTM_SUCCESS;
@@ -1994,16 +2681,142 @@
{
if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
{
+ p_cb->fast_adv_on = FALSE;
p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+
+ /* clear all adv states */
+ btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK);
}
else
rt = BTM_NO_RESOURCES;
}
return rt;
-
}
+
+/*******************************************************************************
+**
+** Function btm_ble_set_topology_mask
+**
+** Description set BLE topology mask
+**
+** Returns TRUE is request is allowed, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state_mask)
+{
+ BOOLEAN rt = TRUE;
+
+ request_state_mask &= BTM_BLE_STATE_ALL_MASK;
+
+ btm_cb.ble_ctr_cb.cur_states |= request_state_mask;
+
+ return rt;
+}
+/*******************************************************************************
+**
+** Function btm_ble_clear_topology_mask
+**
+** Description Clear BLE topology bit mask
+**
+** Returns TRUE is request is allowed, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_clear_topology_mask (tBTM_BLE_STATE_MASK request_state_mask)
+{
+ request_state_mask &= BTM_BLE_STATE_ALL_MASK;
+
+ btm_cb.ble_ctr_cb.cur_states &= ~request_state_mask;
+
+ return TRUE;
+}
+/*******************************************************************************
+**
+** 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;
+ UINT16 mask = BTM_BLE_STATE_ALL_CONN_MASK;
+
+ UNUSED(bd_addr);
+ UNUSED (conn_cancel);
+
+ if (link_role == HCI_ROLE_SLAVE)
+ {
+ btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+ /* clear all adv states */
+ mask |= BTM_BLE_STATE_ALL_ADV_MASK;
+ }
+
+ btm_ble_clear_topology_mask (mask);
+
+ /* check the device link role maps */
+ for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
+ {
+ if (pa->in_use && pa->transport == BT_TRANSPORT_LE)
+ {
+ if (pa->link_role == HCI_ROLE_MASTER)
+ btm_ble_set_topology_mask (BTM_BLE_STATE_MASTER_BIT);
+ else
+ btm_ble_set_topology_mask (BTM_BLE_STATE_SLAVE_BIT);
+ }
+ }
+
+ if (btm_multi_adv_cb.adv_inst_max == 0 &&
+ btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
+ {
+ btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
+ }
+
+ if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
+ {
+ if (!btm_send_pending_direct_conn())
+ {
+ btm_ble_resume_bg_conn();
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_start_slow_adv
+**
+** Description Restart adv with slow adv interval
+**
+** Returns void
+**
+*******************************************************************************/
+static void btm_ble_start_slow_adv (void)
+{
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+ BD_ADDR p_addr_ptr= {0};
+
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
+ {
+ btm_ble_stop_adv();
+
+ btsnd_hcic_ble_write_adv_params (BTM_BLE_GAP_ADV_SLOW_INT,
+ BTM_BLE_GAP_ADV_SLOW_INT,
+ p_cb->evt_type,
+ p_cb->adv_addr_type,
+ btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,/* slow adv
+ mode never goes into directed adv */
+ p_addr_ptr,
+ p_cb->adv_chnl_map,
+ p_cb->afp);
+
+ btm_ble_start_adv();
+ }
+}
/*******************************************************************************
**
** Function btm_ble_timeout
@@ -2015,27 +2828,47 @@
*******************************************************************************/
void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
{
+ BTM_TRACE_EVENT0 ("btm_ble_timeout");
+
switch (p_tle->event)
{
+ case BTU_TTYPE_BLE_OBSERVE:
+ btm_ble_stop_observe();
+ break;
+
case BTU_TTYPE_BLE_INQUIRY:
- btm_ble_stop_scan();
+ btm_ble_stop_inquiry();
break;
case BTU_TTYPE_BLE_GAP_LIM_DISC:
/* lim_timeout expiried, limited discovery should exit now */
- btm_ble_update_adv_flag(BTM_BLE_NON_LIMIT_DISC_FLAG);
-
- btm_ble_stop_adv();
+ btm_cb.btm_inq_vars.discoverable_mode &= ~BTM_BLE_LIMITED_DISCOVERABLE;
+ btm_ble_set_adv_flag(btm_cb.btm_inq_vars.connectable_mode, btm_cb.btm_inq_vars.discoverable_mode);
break;
case BTU_TTYPE_BLE_RANDOM_ADDR:
if (btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type == BLE_ADDR_RANDOM)
{
+ if ((void *)(p_tle->param) == NULL)
/* refresh the random addr */
- btm_gen_resolvable_private_addr();
+ btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
+ else
+ {
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+ btm_ble_multi_adv_configure_rpa((tBTM_BLE_MULTI_ADV_INST*)p_tle->param);
+#endif
+ }
}
break;
+ case BTU_TTYPE_BLE_GAP_FAST_ADV:
+ /* fast adv is completed, fall back to slow adv interval */
+ btm_ble_start_slow_adv();
+ break;
+
+ default:
+ break;
+
}
}
@@ -2054,13 +2887,13 @@
void btm_ble_read_remote_features_complete(UINT8 *p)
{
tACL_CONN *p_acl_cb = &btm_cb.acl_db[0];
- UINT8 status;
UINT16 handle;
int xx;
BTM_TRACE_EVENT0 ("btm_ble_read_remote_features_complete ");
- STREAM_TO_UINT8 (status, p);
+ /* Skip status */
+ p++;
STREAM_TO_UINT16 (handle, p);
/* Look up the connection by handle and copy features */
@@ -2072,6 +2905,7 @@
break;
}
}
+
}
/*******************************************************************************
@@ -2094,7 +2928,10 @@
p_cb->adv_mode = !p_cb->adv_mode;
}
-
+#if (BLE_VND_INCLUDED == TRUE && BLE_PRIVACY_SPT == TRUE)
+ if (p_cb->adv_mode == BTM_BLE_ADV_DISABLE)
+ btm_ble_vendor_disable_irk_list();
+#endif
}
/*******************************************************************************
@@ -2116,58 +2953,6 @@
/*******************************************************************************
**
-** 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;
- UNUSED(bd_addr);
- UNUSED(conn_cancel);
-
- 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 (btm_ble_get_conn_st() == BLE_CONN_IDLE)
- {
- if (!btm_send_pending_direct_conn())
- {
- btm_ble_resume_bg_conn();
- }
- }
-}
-
-/*******************************************************************************
-**
** Function btm_ble_init
**
** Description Initialize the control block variable values.
@@ -2182,6 +2967,7 @@
BTM_TRACE_EVENT0 ("btm_ble_init ");
memset(p_cb, 0, sizeof(tBTM_BLE_CB));
+ p_cb->cur_states = 0;
p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
p_cb->inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
@@ -2195,6 +2981,83 @@
p_cb->scan_int = p_cb->scan_win = BTM_BLE_CONN_PARAM_UNDEF;
p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+ btm_ble_multi_adv_init();
+#endif
+
+ btm_ble_vendor_capability_init();
}
+/*******************************************************************************
+**
+** Function btm_ble_topology_check
+**
+** Description check to see requested state is supported. One state check at
+** a time is supported
+**
+** Returns TRUE is request is allowed, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request_state_mask)
+{
+ BOOLEAN rt = FALSE;
+ UINT32 llt_mask = 0;
+ UINT8 *p;
+
+ UINT8 state_offset = 0;
+ UINT16 cur_states = btm_cb.ble_ctr_cb.cur_states;
+ UINT8 mask, offset;
+ UINT8 request_state = 0;
+
+ /* check only one bit is set and within valid range */
+ if (request_state_mask == BTM_BLE_STATE_INVALID ||
+ request_state_mask > BTM_BLE_STATE_SCAN_ADV_BIT ||
+ (request_state_mask & (request_state_mask -1 )) != 0)
+ {
+ BTM_TRACE_ERROR1("illegal state requested: %d", request_state_mask);
+ return rt;
+ }
+
+ while (request_state_mask)
+ {
+ request_state_mask >>= 1;
+ request_state ++;
+ }
+
+ /* check if the requested state is supported or not */
+ mask = btm_le_state_combo_tbl[0][request_state - 1][0];
+ offset = btm_le_state_combo_tbl[0][request_state-1][1];
+
+ if (!BTM_LE_STATES_SUPPORTED(btm_cb.devcb.le_supported_states, mask, offset))
+ {
+ BTM_TRACE_ERROR1("state requested not supported: %d", request_state);
+ return rt;
+ }
+
+ rt = TRUE;
+ /* make sure currently active states are all supported in conjunction with the requested
+ state. If the bit in table is not set, the combination is not supported */
+ while (cur_states != 0)
+ {
+ if (cur_states & 0x01)
+ {
+ mask = btm_le_state_combo_tbl[request_state][state_offset][0];
+ offset = btm_le_state_combo_tbl[request_state][state_offset][1];
+
+ if (mask != 0 && offset != 0)
+ {
+ if (!BTM_LE_STATES_SUPPORTED(btm_cb.devcb.le_supported_states, mask, offset))
+ {
+ rt = FALSE;
+ break;
+ }
+ }
+ }
+ cur_states >>= 1;
+ state_offset ++;
+ }
+ return rt;
+}
+
+
#endif /* BLE_INCLUDED */
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 7ce4f16..52be674 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -61,9 +61,17 @@
#define BTM_BLE_GAP_DISC_SCAN_INT 18 /* Interval(scan_int) = 11.25 ms= 0x0010 * 0.625 ms */
#define BTM_BLE_GAP_DISC_SCAN_WIN 18 /* scan_window = 11.25 ms= 0x0010 * 0.625 ms */
#define BTM_BLE_GAP_ADV_INT 512 /* Tgap(gen_disc) = 1.28 s= 512 * 0.625 ms */
-#define BTM_BLE_GAP_LIM_TOUT 30 /* Tgap(lim_timeout) = 30.72 s max, round down to 30 */
+#define BTM_BLE_GAP_LIM_TOUT 180 /* Tgap(lim_timeout) = 180s max */
+#define BTM_BLE_GAP_ADV_FAST_INT_1 48 /* TGAP(adv_fast_interval1) = 30(used) ~ 60 ms = 48 *0.625 */
+#define BTM_BLE_GAP_ADV_FAST_INT_2 160 /* TGAP(adv_fast_interval2) = 100(used) ~ 150 ms = 160 * 0.625 ms */
+#define BTM_BLE_GAP_ADV_SLOW_INT 2048 /* Tgap(adv_slow_interval) = 1.28 s= 512 * 0.625 ms */
+#define BTM_BLE_GAP_ADV_DIR_MAX_INT 800 /* Tgap(dir_conn_adv_int_max) = 500 ms = 800 * 0.625 ms */
+#define BTM_BLE_GAP_ADV_DIR_MIN_INT 400 /* Tgap(dir_conn_adv_int_min) = 250 ms = 400 * 0.625 ms */
+
+#define BTM_BLE_GAP_FAST_ADV_TOUT 30
+
#define BTM_BLE_SEC_REQ_ACT_NONE 0
#define BTM_BLE_SEC_REQ_ACT_ENCRYPT 1 /* encrypt the link using current key or key refresh */
#define BTM_BLE_SEC_REQ_ACT_PAIR 2
@@ -75,6 +83,16 @@
#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)
+/* LE scan activity bit mask, continue with LE inquiry bits */
+#define BTM_LE_SELECT_CONN_ACTIVE 0x40 /* selection connection is in progress */
+#define BTM_LE_OBSERVE_ACTIVE 0x80 /* observe is in progress */
+
+/* BLE scan activity mask checking */
+#define BTM_BLE_IS_SCAN_ACTIVE(x) ((x) & BTM_BLE_SCAN_ACTIVE_MASK)
+#define BTM_BLE_IS_INQ_ACTIVE(x) ((x) & BTM_BLE_INQUIRY_MASK)
+#define BTM_BLE_IS_OBS_ACTIVE(x) ((x) & BTM_LE_OBSERVE_ACTIVE)
+#define BTM_BLE_IS_SEL_CONN_ACTIVE(x) ((x) & BTM_LE_SELECT_CONN_ACTIVE)
+
typedef struct
{
UINT16 data_mask;
@@ -98,16 +116,14 @@
#define BTM_BLE_VALID_PRAM(x, min, max) (((x) >= (min) && (x) <= (max)) || ((x) == BTM_BLE_CONN_PARAM_UNDEF))
+#define BTM_BLE_PRIVATE_ADDR_INT 900 /* 15 minutes minimum for
+ random address refreshing */
+
typedef struct
{
UINT16 discoverable_mode;
UINT16 connectable_mode;
- UINT16 br_edr_supported_flag; /* combined BR EDR discoverable and connectable mode */
- /* only meaningful when it is zero. This means
- BR EDR is not supported*/
- UINT8 proc_mode; /* current procedure mode : inquiry or discovery */
-
UINT16 scan_window;
UINT16 scan_interval;
UINT8 scan_type; /* current scan type: active or passive */
@@ -121,6 +137,8 @@
UINT8 adv_mode;
tBLE_BD_ADDR direct_bda;
BOOLEAN directed_conn;
+ BOOLEAN fast_adv_on;
+ TIMER_LIST_ENT fast_adv_timer;
UINT8 adv_len;
UINT8 adv_data_cache[BTM_BLE_CACHE_ADV_DATA_MAX];
@@ -148,8 +166,8 @@
/* random address management control block */
typedef struct
{
- tBLE_ADDR_TYPE own_addr_type; /* local device LE address type */
- BD_ADDR private_addr;
+ tBLE_ADDR_TYPE own_addr_type; /* local device LE address type */
+ BD_ADDR private_addr;
BD_ADDR random_bda;
BOOLEAN busy;
UINT16 index;
@@ -198,6 +216,37 @@
void *p_param;
}tBTM_BLE_CONN_REQ;
+/* LE state request */
+#define BTM_BLE_STATE_INVALID 0
+#define BTM_BLE_STATE_CONN_ADV 1
+#define BTM_BLE_STATE_INIT 2
+#define BTM_BLE_STATE_MASTER 3
+#define BTM_BLE_STATE_SLAVE 4
+#define BTM_BLE_STATE_LO_DUTY_DIR_ADV 5
+#define BTM_BLE_STATE_HI_DUTY_DIR_ADV 6
+#define BTM_BLE_STATE_NON_CONN_ADV 7
+#define BTM_BLE_STATE_PASSIVE_SCAN 8
+#define BTM_BLE_STATE_ACTIVE_SCAN 9
+#define BTM_BLE_STATE_SCAN_ADV 10
+#define BTM_BLE_STATE_MAX 11
+typedef UINT8 tBTM_BLE_STATE;
+
+#define BTM_BLE_STATE_CONN_ADV_BIT 0x0001
+#define BTM_BLE_STATE_INIT_BIT 0x0002
+#define BTM_BLE_STATE_MASTER_BIT 0x0004
+#define BTM_BLE_STATE_SLAVE_BIT 0x0008
+#define BTM_BLE_STATE_LO_DUTY_DIR_ADV_BIT 0x0010
+#define BTM_BLE_STATE_HI_DUTY_DIR_ADV_BIT 0x0020
+#define BTM_BLE_STATE_NON_CONN_ADV_BIT 0x0040
+#define BTM_BLE_STATE_PASSIVE_SCAN_BIT 0x0080
+#define BTM_BLE_STATE_ACTIVE_SCAN_BIT 0x0100
+#define BTM_BLE_STATE_SCAN_ADV_BIT 0x0200
+typedef UINT16 tBTM_BLE_STATE_MASK;
+
+#define BTM_BLE_STATE_ALL_MASK 0x03ff
+#define BTM_BLE_STATE_ALL_ADV_MASK (BTM_BLE_STATE_CONN_ADV_BIT|BTM_BLE_STATE_LO_DUTY_DIR_ADV_BIT|BTM_BLE_STATE_HI_DUTY_DIR_ADV_BIT|BTM_BLE_STATE_SCAN_ADV_BIT)
+#define BTM_BLE_STATE_ALL_SCAN_MASK (BTM_BLE_STATE_PASSIVE_SCAN_BIT|BTM_BLE_STATE_ACTIVE_SCAN_BIT)
+#define BTM_BLE_STATE_ALL_CONN_MASK (BTM_BLE_STATE_MASTER_BIT|BTM_BLE_STATE_SLAVE_BIT)
typedef struct
{
@@ -210,11 +259,18 @@
*/
typedef struct
{
+ UINT8 scan_activity; /* LE scan activity mask */
+
/*****************************************************
** BLE Inquiry
*****************************************************/
tBTM_BLE_INQ_CB inq_var;
+ /* observer callback and timer */
+ tBTM_INQ_RESULTS_CB *p_obs_results_cb;
+ tBTM_CMPL_CB *p_obs_cmpl_cb;
+ TIMER_LIST_ENT obs_timer_ent;
+
/* background connection procedure cb value */
tBTM_BLE_CONN_TYPE bg_conn_type;
UINT16 scan_int;
@@ -236,12 +292,18 @@
tBTM_LE_RANDOM_CB addr_mgnt_cb;
BOOLEAN enabled;
+#if BLE_PRIVACY_SPT == TRUE
+ BOOLEAN privacy; /* privacy enabled or disabled */
+#endif
tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
#ifdef BTM_BLE_PC_ADV_TEST_MODE
tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback;
#endif
+ /* current BLE link state */
+ tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */
+
} tBTM_BLE_CB;
#ifdef __cplusplus
@@ -259,15 +321,22 @@
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_stop_scan();
+extern void btm_ble_stop_inquiry(void);
extern void btm_ble_init (void);
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_write_adv_enable_complete(UINT8 * p);
extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_read_ble_local_supported_states_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);
+extern UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
+ tBTM_BLE_ADV_DATA *p_data);
+extern tBTM_STATUS btm_ble_start_adv(void);
+extern tBTM_STATUS btm_ble_stop_adv(void);
+extern tBTM_STATUS btm_ble_start_scan (UINT8 filter_enb);
+
/* LE security function from btm_sec.c */
@@ -277,7 +346,7 @@
extern UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data);
extern tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 link_role);
extern void btm_ble_ltk_request(UINT16 handle, UINT8 rand[8], UINT16 ediv);
-extern BOOLEAN btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk);
+extern tBTM_STATUS btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk);
extern void btm_ble_link_encrypted(BD_ADDR bd_addr, UINT8 encr_enable);
#endif
@@ -299,7 +368,7 @@
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_update_scan_filter_policy(tBTM_BLE_AFP adv_policy);
extern void btm_ble_clear_white_list (void);
/* background connection function */
@@ -312,22 +381,40 @@
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);
+extern BOOLEAN btm_execute_wl_dev_operation(void);
/* 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 void btm_gen_resolvable_private_addr (void);
+extern void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback);
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);
+extern void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p);
+
+extern void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst);
+extern void btm_ble_multi_adv_init(void);
+extern void btm_ble_multi_adv_reenable(UINT8 inst_id);
+extern void btm_ble_multi_adv_enb_privacy(BOOLEAN enable);
+extern BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request);
+extern BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state);
+extern BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state);
+
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+/* BLE address mapping with CS feature */
+extern BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type);
+extern BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_type);
+extern void btm_ble_refresh_rra(BD_ADDR pseudo_bda, BD_ADDR rra);
+#endif
#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);
+BT_API extern void btm_ble_set_keep_rfu_in_auth_req(BOOLEAN keep_rfu);
#endif
diff --git a/stack/btm/btm_ble_multi_adv.c b/stack/btm/btm_ble_multi_adv.c
new file mode 100644
index 0000000..67e0767
--- /dev/null
+++ b/stack/btm/btm_ble_multi_adv.c
@@ -0,0 +1,791 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 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"
+
+#if (BLE_INCLUDED == TRUE)
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+#include "bt_types.h"
+#include "hcimsgs.h"
+#include "btu.h"
+#include "btm_int.h"
+#include "bt_utils.h"
+#include "hcidefs.h"
+#include "btm_ble_api.h"
+
+/* length of each multi adv sub command */
+#define BTM_BLE_MULTI_ADV_ENB_LEN 3
+#define BTM_BLE_MULTI_ADV_SET_PARAM_LEN 24
+#define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN (BTM_BLE_AD_DATA_LEN + 3)
+#define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN 8
+
+#ifndef BTM_BLE_MULTI_ADV_INST_MAX
+#define BTM_BLE_MULTI_ADV_INST_MAX 5
+#endif
+
+tBTM_BLE_MULTI_ADV_CB btm_multi_adv_cb;
+
+static void btm_ble_multi_adv_gen_rpa_cmpl_1(tBTM_RAND_ENC *p);
+static void btm_ble_multi_adv_gen_rpa_cmpl_2(tBTM_RAND_ENC *p);
+static void btm_ble_multi_adv_gen_rpa_cmpl_3(tBTM_RAND_ENC *p);
+static void btm_ble_multi_adv_gen_rpa_cmpl_4(tBTM_RAND_ENC *p);
+
+typedef void (*tBTM_MULTI_ADV_RPA_CMPL)(tBTM_RAND_ENC *p);
+const tBTM_MULTI_ADV_RPA_CMPL btm_ble_multi_adv_rpa_cmpl [] =
+{
+ btm_ble_multi_adv_gen_rpa_cmpl_1,
+ btm_ble_multi_adv_gen_rpa_cmpl_2,
+ btm_ble_multi_adv_gen_rpa_cmpl_3,
+ btm_ble_multi_adv_gen_rpa_cmpl_4
+};
+
+#define BTM_BLE_MULTI_ADV_CB_EVT_MASK 0xF0
+#define BTM_BLE_MULTI_ADV_SUBCODE_MASK 0x0F
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_enq_op_q
+**
+** Description enqueue a multi adv operation in q to check command complete
+** status.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt)
+{
+ tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q;
+
+ p_op_q->inst_id[p_op_q->next_idx] = inst_id;
+
+ p_op_q->sub_code[p_op_q->next_idx] = (opcode |(cb_evt << 4));
+
+ p_op_q->next_idx = (p_op_q->next_idx + 1) % BTM_BLE_MULTI_ADV_MAX;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_deq_op_q
+**
+** Description dequeue a multi adv operation from q when command complete
+** is received.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt)
+{
+ tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q;
+
+ *p_inst_id = p_op_q->inst_id[p_op_q->pending_idx] & 0x7F;
+ *p_cb_evt = (p_op_q->sub_code[p_op_q->pending_idx] >> 4);
+ *p_opcode = (p_op_q->sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK);
+
+ p_op_q->pending_idx = (p_op_q->pending_idx + 1) % BTM_BLE_MULTI_ADV_MAX;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_vsc_cmpl_cback
+**
+** Description Multi adv VSC complete callback
+**
+** Parameters
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_multi_adv_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
+{
+ UINT8 status, subcode;
+ UINT8 *p = p_params->p_param_buf, inst_id;
+ UINT16 len = p_params->param_len;
+ tBTM_BLE_MULTI_ADV_INST *p_inst ;
+ UINT8 cb_evt = 0, opcode;
+
+ if (len < 2)
+ {
+ BTM_TRACE_ERROR0("wrong length for btm_ble_multi_adv_vsc_cmpl_cback");
+ return;
+ }
+
+ STREAM_TO_UINT8(status, p);
+ STREAM_TO_UINT8(subcode, p);
+
+ btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt);
+
+ BTM_TRACE_DEBUG3("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt);
+
+ if (opcode != subcode || inst_id == 0)
+ {
+ BTM_TRACE_ERROR2("get unexpected VSC cmpl, expect: %d get: %d",subcode,opcode);
+ return;
+ }
+
+ p_inst = &btm_multi_adv_cb.adv_inst[inst_id - 1];
+
+ switch (subcode)
+ {
+ case BTM_BLE_MULTI_ADV_ENB:
+ BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_ENB status = %d", status);
+ if (status != HCI_SUCCESS)
+ {
+ btm_multi_adv_cb.adv_inst[inst_id-1].inst_id = 0;
+ }
+ break;
+
+ case BTM_BLE_MULTI_ADV_SET_PARAM:
+ {
+ BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_SET_PARAM status = %d", status);
+ break;
+ }
+
+ case BTM_BLE_MULTI_ADV_WRITE_ADV_DATA:
+ {
+ BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_WRITE_ADV_DATA status = %d", status);
+ break;
+ }
+
+ case BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA:
+ {
+ BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA status = %d", status);
+ break;
+ }
+
+ case BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR:
+ {
+ BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR status = %d", status);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (cb_evt != 0 && p_inst->p_cback != NULL)
+ {
+ (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_enable_multi_adv
+**
+** Description This function enable the customer specific feature in controller
+**
+** Parameters enable: enable or disable
+** inst_id: adv instance ID, can not be 0
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_evt)
+{
+ UINT8 param[BTM_BLE_MULTI_ADV_ENB_LEN], *pp;
+ UINT8 enb = enable ? 1: 0;
+ tBTM_STATUS rt;
+
+ pp = param;
+ memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN);
+
+ UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_ENB);
+ UINT8_TO_STREAM (pp, enb);
+ UINT8_TO_STREAM (pp, inst_id);
+
+ BTM_TRACE_EVENT2 (" btm_ble_enable_multi_adv: enb %d, Inst ID %d",enb,inst_id);
+
+ if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+ BTM_BLE_MULTI_ADV_ENB_LEN,
+ param,
+ btm_ble_multi_adv_vsc_cmpl_cback))
+ == BTM_CMD_STARTED)
+ {
+ btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id, cb_evt);
+ }
+ return rt;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_set_params
+**
+** Description This function enable the customer specific feature in controller
+**
+** Parameters advertise parameters used for this instance.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
+ tBTM_BLE_ADV_PARAMS *p_params,
+ UINT8 cb_evt)
+{
+ UINT8 param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN], *pp;
+ tBTM_STATUS rt;
+ BD_ADDR dummy ={0,0,0,0,0,0};
+
+ pp = param;
+ memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN);
+
+ UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM);
+
+ UINT16_TO_STREAM (pp, p_params->adv_int_min);
+ UINT16_TO_STREAM (pp, p_params->adv_int_max);
+ UINT8_TO_STREAM (pp, p_params->adv_type);
+
+#if BLE_PRIVACY_SPT == TRUE
+ if (btm_cb.ble_ctr_cb.privacy)
+ {
+ UINT8_TO_STREAM (pp, BLE_ADDR_RANDOM);
+ BDADDR_TO_STREAM (pp, p_inst->rpa);
+ }
+ else
+#endif
+ {
+ UINT8_TO_STREAM (pp, BLE_ADDR_PUBLIC);
+ BDADDR_TO_STREAM (pp, btm_cb.devcb.local_addr);
+ }
+
+ BTM_TRACE_EVENT3 (" btm_ble_multi_adv_set_params,Min %d, Max %d,adv_type %d",
+ p_params->adv_int_min,p_params->adv_int_max,p_params->adv_type);
+
+ UINT8_TO_STREAM (pp, 0);
+ BDADDR_TO_STREAM (pp, dummy);
+
+ if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP)
+ p_params->channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
+ UINT8_TO_STREAM (pp, p_params->channel_map);
+
+ if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX)
+ p_params->adv_filter_policy = AP_SCAN_CONN_ALL;
+ UINT8_TO_STREAM (pp, p_params->adv_filter_policy);
+
+ UINT8_TO_STREAM (pp, p_inst->inst_id);
+
+ if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX)
+ p_params->tx_power = BTM_BLE_ADV_TX_POWER_MAX;
+ UINT8_TO_STREAM (pp, p_params->tx_power);
+
+ BTM_TRACE_EVENT4("set_params:Chnl Map %d,adv_fltr policy %d,ID:%d, TX Power%d",
+ p_params->channel_map,p_params->adv_filter_policy,p_inst->inst_id,p_params->tx_power);
+
+ if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+ BTM_BLE_MULTI_ADV_SET_PARAM_LEN,
+ param,
+ btm_ble_multi_adv_vsc_cmpl_cback))
+ == BTM_CMD_STARTED)
+ {
+ p_inst->adv_evt = p_params->adv_type;
+
+#if BLE_PRIVACY_SPT == TRUE
+ if (btm_cb.ble_ctr_cb.privacy)
+ {
+ /* start timer */
+ p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
+ btu_start_timer (&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
+ BTM_BLE_PRIVATE_ADDR_INT);
+ }
+#endif
+
+ btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, p_inst->inst_id, cb_evt);
+ }
+ return rt;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_write_rpa
+**
+** Description This function write the random address for the adv instance into
+** controller
+**
+** Parameters
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr)
+{
+ UINT8 param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param;
+ tBTM_STATUS rt;
+
+ BTM_TRACE_EVENT0 (" btm_ble_multi_adv_set_random_addr");
+
+ memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN);
+
+ UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR);
+ BDADDR_TO_STREAM(pp, random_addr);
+ UINT8_TO_STREAM(pp, p_inst->inst_id);
+
+ if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+ BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN,
+ param,
+ btm_ble_multi_adv_vsc_cmpl_cback)) == BTM_CMD_STARTED)
+ {
+ /* start a periodical timer to refresh random addr */
+ btu_stop_timer(&p_inst->raddr_timer_ent);
+ p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
+ btu_start_timer (&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
+ BTM_BLE_PRIVATE_ADDR_INT);
+
+ btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR, p_inst->inst_id, 0);
+ }
+ return rt;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_gen_rpa_cmpl
+**
+** Description RPA generation completion callback for each adv instance. Will
+** continue write the new RPA into controller.
+**
+** Returns none.
+**
+*******************************************************************************/
+void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p, tBTM_BLE_MULTI_ADV_INST *p_inst )
+{
+#if (SMP_INCLUDED == TRUE)
+ tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+ tSMP_ENC output;
+
+ BTM_TRACE_EVENT1 ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id);
+ if (p)
+ {
+ p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
+ p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
+
+ p_inst->rpa[2] = p->param_buf[0];
+ p_inst->rpa[1] = p->param_buf[1];
+ p_inst->rpa[0] = p->param_buf[2];
+
+ if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output))
+ {
+ BTM_TRACE_DEBUG0("generate random address failed");
+ }
+ else
+ {
+ /* set hash to be LSB of rpAddress */
+ p_inst->rpa[5] = output.param_buf[0];
+ p_inst->rpa[4] = output.param_buf[1];
+ p_inst->rpa[3] = output.param_buf[2];
+
+ if (p_inst->inst_id != 0)
+ {
+ /* set it to controller */
+ btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa);
+ }
+ }
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_gen_rpa_cmpl1
+**
+** Description RPA generation completion callback for each adv instance. Will
+** continue write the new RPA into controller.
+**
+** Returns none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_1(tBTM_RAND_ENC *p)
+{
+ btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[0]);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_gen_rpa_cmpl2
+**
+** Description RPA generation completion callback for each adv instance. Will
+** continue write the new RPA into controller.
+**
+** Returns none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_2(tBTM_RAND_ENC *p)
+{
+ btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[1]);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_gen_rpa_cmpl3
+**
+** Description RPA generation completion callback for each adv instance. Will
+** continue write the new RPA into controller.
+**
+** Returns none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_3(tBTM_RAND_ENC *p)
+{
+ btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[2]);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_gen_rpa_cmpl4
+**
+** Description RPA generation completion callback for each adv instance. Will
+** continue write the new RPA into controller.
+**
+** Returns none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_4(tBTM_RAND_ENC *p)
+{
+ btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[3]);
+}
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_configure_rpa
+**
+** Description This function set the random address for the adv instance
+**
+** Parameters advertise parameters used for this instance.
+**
+** Returns none
+**
+*******************************************************************************/
+void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst)
+{
+ btm_gen_resolvable_private_addr((void *)p_inst->p_rpa_cback);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_reenable
+**
+** Description This function re-enable adv instance upon a connection establishment.
+**
+** Parameters advertise parameters used for this instance.
+**
+** Returns none.
+**
+*******************************************************************************/
+void btm_ble_multi_adv_reenable(UINT8 inst_id)
+{
+ tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.adv_inst[inst_id - 1];
+
+ if (p_inst->inst_id != 0)
+ {
+ if (p_inst->adv_evt != BTM_BLE_CONNECT_DIR_EVT)
+ btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, 0);
+ else
+ /* mark directed adv as disabled if adv has been stopped */
+ {
+ (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id,p_inst->p_ref,0);
+ p_inst->inst_id = 0;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_enb_privacy
+**
+** Description This function enable/disable privacy setting in multi adv
+**
+** Parameters enable: enable or disable the adv instance.
+**
+** Returns none.
+**
+*******************************************************************************/
+void btm_ble_multi_adv_enb_privacy(BOOLEAN enable)
+{
+ UINT8 i;
+ tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.adv_inst[0];
+
+ for (i = 0; i < BTM_BLE_MULTI_ADV_MAX; i ++, p_inst++)
+ {
+ if (enable)
+ btm_ble_multi_adv_configure_rpa (p_inst);
+ else
+ btu_stop_timer(&p_inst->raddr_timer_ent);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleEnableAdvInstance
+**
+** Description This function enable a Multi-ADV instance with the specified
+** adv parameters
+**
+** Parameters p_params: pointer to the adv parameter structure, set as default
+** adv parameter when the instance is enabled.
+** p_cback: callback function for the adv instance.
+** p_ref: reference data attach to the adv instance to be enabled.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
+ tBTM_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref)
+{
+ UINT8 i;
+ tBTM_STATUS rt = BTM_NO_RESOURCES;
+ tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.adv_inst[0];
+
+ BTM_TRACE_EVENT0("BTM_BleEnableAdvInstance called");
+
+ if (btm_multi_adv_cb.adv_inst_max == 0)
+ {
+ BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+ return BTM_ERR_PROCESSING;
+ }
+
+ for (i = 0; i < BTM_BLE_MULTI_ADV_MAX; i ++, p_inst++)
+ {
+ if (p_inst->inst_id == 0)
+ {
+ p_inst->inst_id = i + 1;
+
+ /* configure adv parameter */
+ if (p_params)
+ btm_ble_multi_adv_set_params(p_inst, p_params, 0);
+
+ /* enable adv */
+ BTM_TRACE_EVENT1("btm_ble_enable_multi_adv being called with inst_id:%d",
+ p_inst->inst_id);
+ if ((rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, BTM_BLE_MULTI_ADV_ENB_EVT))
+ == BTM_CMD_STARTED)
+ {
+ p_inst->p_cback = p_cback;
+ p_inst->p_ref = p_ref;
+ }
+ else
+ {
+ p_inst->inst_id = 0;
+ BTM_TRACE_ERROR0("BTM_BleEnableAdvInstance failed, no resources");
+ }
+ break;
+ }
+ }
+ return rt;
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvInstParam
+**
+** Description This function update a Multi-ADV instance with the specified
+** adv parameters.
+**
+** Parameters inst_id: adv instance ID
+** p_params: pointer to the adv parameter structure.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params)
+{
+ tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
+ tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.adv_inst[inst_id - 1];
+
+ BTM_TRACE_EVENT1("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id);
+
+ if (btm_multi_adv_cb.adv_inst_max == 0)
+ {
+ BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+ return BTM_ERR_PROCESSING;
+ }
+
+ if (inst_id <= BTM_BLE_MULTI_ADV_MAX &&
+ inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
+ p_params != NULL)
+ {
+ if (p_inst->inst_id == 0)
+ {
+ BTM_TRACE_DEBUG1("adv instance %d is not active", inst_id);
+ return BTM_WRONG_MODE;
+ }
+ else
+ btm_ble_enable_multi_adv(FALSE, inst_id, 0);
+
+ btm_ble_multi_adv_set_params(p_inst, p_params, 0);
+
+ rt = btm_ble_enable_multi_adv(TRUE, inst_id, BTM_BLE_MULTI_ADV_PARAM_EVT);
+ }
+ return rt;
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleCfgAdvInstData
+**
+** Description This function configure a Multi-ADV instance with the specified
+** adv data or scan response data.
+**
+** Parameters inst_id: adv instance ID
+** is_scan_rsp: is this scacn response, if no set as adv data.
+** data_mask: adv data mask.
+** p_data: pointer to the adv data structure.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+ tBTM_BLE_AD_MASK data_mask,
+ tBTM_BLE_ADV_DATA *p_data)
+{
+ UINT8 param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param;
+ UINT8 sub_code = (is_scan_rsp) ?
+ BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA : BTM_BLE_MULTI_ADV_WRITE_ADV_DATA;
+ UINT8 *p_len;
+ tBTM_STATUS rt;
+ UINT8 *pp_temp = (UINT8*)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN -1);
+
+ if (btm_multi_adv_cb.adv_inst_max == 0)
+ {
+ BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+ return BTM_ERR_PROCESSING;
+ }
+
+ BTM_TRACE_EVENT1("BTM_BleCfgAdvInstData called with inst_id:%d", inst_id);
+ if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD)
+ return BTM_ILLEGAL_VALUE;
+
+ memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN);
+
+ UINT8_TO_STREAM(pp, sub_code);
+ p_len = pp ++;
+ btm_ble_build_adv_data(&data_mask, &pp, p_data);
+ *p_len = (UINT8)(pp - param - 2);
+ UINT8_TO_STREAM(pp_temp, inst_id);
+
+ if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+ (UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN,
+ param,
+ btm_ble_multi_adv_vsc_cmpl_cback))
+ == BTM_CMD_STARTED)
+ {
+ btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT);
+ }
+ return rt;
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleDisableAdvInstance
+**
+** Description This function disables a Multi-ADV instance.
+**
+** Parameters inst_id: adv instance ID
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id)
+{
+ tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
+
+ BTM_TRACE_EVENT1("BTM_BleDisableAdvInstance with inst_id:%d", inst_id);
+
+ if (btm_multi_adv_cb.adv_inst_max == 0)
+ {
+ BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+ return BTM_ERR_PROCESSING;
+ }
+
+ if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD)
+ {
+ if ((rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT))
+ == BTM_CMD_STARTED)
+ {
+ btu_stop_timer(&btm_multi_adv_cb.adv_inst[inst_id-1].raddr_timer_ent);
+
+ btm_multi_adv_cb.adv_inst[inst_id-1].inst_id = 0;
+ }
+ }
+ return rt;
+}
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_vse_cback
+**
+** Description VSE callback for multi adv events.
+**
+** Returns
+**
+*******************************************************************************/
+void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
+{
+ UINT8 sub_event;
+ UINT8 adv_inst, reason, conn_handle;
+
+ /* Check if this is a BLE RSSI vendor specific event */
+ STREAM_TO_UINT8(sub_event, p);
+ len--;
+
+ BTM_TRACE_EVENT1("btm_ble_multi_adv_vse_cback called with event:%d", sub_event);
+ if ((sub_event == HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG) && (len>=4))
+ {
+ STREAM_TO_UINT8(adv_inst, p);
+ STREAM_TO_UINT8(reason, p);
+ STREAM_TO_UINT16(conn_handle, p);
+
+ if (adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD)
+ {
+ BTM_TRACE_EVENT0("btm_ble_multi_adv_reenable called");
+ btm_ble_multi_adv_reenable(adv_inst);
+ }
+ /* re-enable connectibility */
+ else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD)
+ {
+ if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
+ {
+ btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
+
+ }
+ }
+
+ }
+
+}
+/*******************************************************************************
+**
+** Function btm_ble_multi_adv_init
+**
+** Description This function initialize the multi adv control block.
+**
+** Parameters
+**
+** Returns status
+**
+*******************************************************************************/
+void btm_ble_multi_adv_init(void)
+{
+ UINT8 i;
+
+ memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
+
+ for (i = 0; i < BTM_BLE_MULTI_ADV_MAX; i ++)
+ btm_multi_adv_cb.adv_inst[i].p_rpa_cback = btm_ble_multi_adv_rpa_cmpl[i];
+
+ BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE);
+}
+#endif
+#endif
+
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index 0dd534c..fbf4df1 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -64,6 +64,7 @@
int i, j;
BOOLEAN found = FALSE;
+ BTM_TRACE_API2("%s, link key type:%x", __FUNCTION__,key_type);
p_dev_rec = btm_find_dev (bd_addr);
if (!p_dev_rec)
{
@@ -79,7 +80,7 @@
memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
p_dev_rec->sec_flags = BTM_SEC_IN_USE;
memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
- p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr);
+ p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
#if BLE_INCLUDED == TRUE
/* use default value for background connection params */
@@ -172,7 +173,7 @@
{
tBTM_SEC_DEV_REC *p_dev_rec;
- if (BTM_IsAclConnectionUp(bd_addr))
+ if (BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE) || BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_BR_EDR))
{
BTM_TRACE_WARNING0("BTM_SecDeleteDevice FAILED: Cannot Delete when connection is active");
return(FALSE);
@@ -215,9 +216,9 @@
** Function btm_sec_alloc_dev
**
** Description Look for the record in the device database for the record
-** with specified handle
+** with specified address
**
-** Returns Pointer to the record
+** Returns Pointer to the record or NULL
**
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
@@ -278,7 +279,10 @@
memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
- p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr);
+#if BLE_INCLUDED == TRUE
+ p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_LE);
+#endif
+ p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
p_dev_rec->timestamp = btm_cb.dev_rec_count++;
return(p_dev_rec);
@@ -376,7 +380,11 @@
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
{
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
- && (p_dev_rec->hci_handle == handle))
+ && ((p_dev_rec->hci_handle == handle)
+#if BLE_INCLUDED == TRUE
+ ||(p_dev_rec->ble_hci_handle == handle)
+#endif
+ ))
return(p_dev_rec);
}
return(NULL);
@@ -440,7 +448,7 @@
** the oldest non-paired device. If all devices are paired it
** deletes the oldest paired device.
**
-** Returns Pointer to the record
+** Returns Pointer to the record or NULL
**
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
@@ -454,7 +462,7 @@
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
{
if (((p_dev_rec->sec_flags & BTM_SEC_IN_USE) == 0)
- || ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) != 0))
+ || ((p_dev_rec->sec_flags & (BTM_SEC_LINK_KEY_KNOWN |BTM_SEC_LE_LINK_KEY_KNOWN)) != 0))
continue; /* Device is paired so skip it */
if (p_dev_rec->timestamp < ot)
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index 240bd2f..35d9932 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -483,6 +483,25 @@
/* Send a Read Local Supported Features message to the Host Controller. */
btsnd_hcic_ble_read_local_spt_feat ();
}
+
+/*******************************************************************************
+**
+** Function btm_read_ble_local_supported_states
+**
+** Description Local function called to send a read BLE local supported
+** features command
+**
+** Returns void
+**
+*******************************************************************************/
+static void btm_read_ble_local_supported_states(void)
+{
+ BTM_TRACE_DEBUG0("btm_read_ble_local_supported_states ");
+ btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
+
+ /* Send a Read Local Supported states message to the Host Controller. */
+ btsnd_hcic_ble_read_supported_states ();
+}
#endif
/*******************************************************************************
**
@@ -652,6 +671,8 @@
btm_cb.ble_ctr_cb.p_select_cback = NULL;
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();
+ btm_ble_multi_adv_init();
+ btm_ble_vendor_capability_init();
#endif
}
}
@@ -808,6 +829,36 @@
l2c_link_processs_ble_num_bufs (lm_num_le_bufs);
}
+ btm_read_ble_local_supported_states();
+}
+/*******************************************************************************
+**
+** Function btm_read_ble_local_supported_states_complete
+**
+** Description This function is called when command complete for
+** Read LE Local Supported states complete is received.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_read_ble_local_supported_states_complete (UINT8 *p, UINT16 evt_len)
+{
+ UINT8 status;
+
+ UNUSED(evt_len);
+ BTM_TRACE_DEBUG0("btm_read_ble_local_supported_states_complete ");
+
+ btu_stop_timer (&btm_cb.devcb.reset_timer);
+
+ STREAM_TO_UINT8 (status, p);
+ if (status == HCI_SUCCESS)
+ {
+ STREAM_TO_ARRAY(&btm_cb.devcb.le_supported_states, p, BTM_LE_SUPPORT_STATE_SIZE);
+ }
+ else
+ {
+ BTM_TRACE_WARNING1 ("btm_read_ble_local_supported_features_complete status = %d", status);
+ }
btm_read_ble_local_supported_features();
}
@@ -842,6 +893,8 @@
BTM_TRACE_WARNING1 ("btm_read_ble_local_supported_features_complete status = %d", status);
}
+ btsnd_hcic_ble_set_evt_mask((UINT8 *)HCI_BLE_EVENT_MASK_DEF);
+
#if BTM_INTERNAL_BB == TRUE
{
UINT8 buf[9] = BTM_INTERNAL_LOCAL_FEA;
@@ -874,6 +927,8 @@
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 simultatunous LE supported */
+ btsnd_hcic_ble_write_host_supported(BTM_BLE_HOST_SUPPORT, BTM_BLE_SIMULTANEOUS_HOST);
btm_get_ble_buffer_size();
}
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index 24f91a8..01cbd56 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -796,10 +796,10 @@
#if BLE_INCLUDED == TRUE
if (((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- &&(active_mode & BTM_LE_INQ_ACTIVE_MASK)
+ &&(active_mode & BTM_BLE_INQ_ACTIVE_MASK)
#endif
)
- btm_ble_stop_scan();
+ btm_ble_stop_inquiry();
#endif
}
@@ -869,7 +869,6 @@
p_inq->scan_type = INQ_GENERAL;
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
- btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
}
else
@@ -1080,7 +1079,8 @@
** BTM_WRONG_MODE if the device is not up.
**
*******************************************************************************/
-tBTM_STATUS BTM_ReadRemoteDeviceName (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb)
+tBTM_STATUS BTM_ReadRemoteDeviceName (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb
+ ,tBT_TRANSPORT transport)
{
tBTM_INQ_INFO *p_cur = NULL;
tINQ_DB_ENT *p_i;
@@ -1101,7 +1101,7 @@
BTM_TRACE_API0 ("no device found in inquiry db");
#if (BLE_INCLUDED == TRUE)
- if (BTM_UseLeLink(remote_bda))
+ if (transport == BT_TRANSPORT_LE)
{
return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
}
@@ -2266,7 +2266,7 @@
#if BLE_INCLUDED == TRUE
if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
- btm_ble_stop_scan();
+ btm_ble_stop_inquiry();
#endif
@@ -2493,14 +2493,13 @@
(p_inq_cb)((tBTM_INQUIRY_CMPL *) &p_inq->inq_cmpl_info);
}
#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
- if(p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))
- {
- /* make inquiry inactive for next iteration */
- p_inq->inq_active = BTM_INQUIRY_INACTIVE;
- /* call the inquiry again */
- BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb);
- return;
- }
+ if(p_inq->inqparms.mode != 0 && !(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE))
+ {
+ /* make inquiry inactive for next iteration */
+ p_inq->inq_active = BTM_INQUIRY_INACTIVE;
+ /* call the inquiry again */
+ BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb);
+ }
#endif
}
if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete
@@ -3422,9 +3421,6 @@
BTM_AddEirService( p_results->eir_uuid, uuid16 );
}
}
-
- BTM_TRACE_DEBUG2("btm_set_eir_uuid eir_uuid=0x%08X %08X",
- p_results->eir_uuid[1], p_results->eir_uuid[0] );
}
#endif
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 7865b3e..2d4e107 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -46,7 +46,7 @@
typedef char tBTM_LOC_BD_NAME[BTM_MAX_LOC_BD_NAME_LEN + 1];
#endif
-#define BTM_ACL_IS_CONNECTED(bda) (btm_bda_to_acl (bda) != NULL)
+#define BTM_ACL_IS_CONNECTED(bda) (btm_bda_to_acl (bda, BT_TRANSPORT_BR_EDR) != NULL)
/* Definitions for Server Channel Number (SCN) management
*/
@@ -119,8 +119,9 @@
#if BTM_PWR_MGR_INCLUDED == FALSE
UINT8 mode;
#endif /* BTM_PWR_MGR_INCLUDED */
+
#if BLE_INCLUDED == TRUE
- UINT8 is_le_link;
+ tBT_TRANSPORT transport;
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 */
@@ -189,24 +190,29 @@
BD_FEATURES local_lmp_features[HCI_EXT_FEATURES_PAGE_MAX + 1];
#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 */
+
BD_ADDR read_tx_pwr_addr; /* read TX power target address */
BD_FEATURES local_le_features; /* Local LE Supported features mask for the device */
tBTM_BLE_LOCAL_ID_KEYS id_keys; /* local BLE ID keys */
BT_OCTET16 er; /* BLE encryption key */
+#define BTM_LE_SUPPORT_STATE_SIZE 8
+UINT8 le_supported_states[BTM_LE_SUPPORT_STATE_SIZE];
+
+
+
#if BTM_BLE_CONFORMANCE_TESTING == TRUE
BOOLEAN no_disc_if_pair_fail;
- BOOLEAN enable_test_mac_val;
+ BOOLEAN enable_test_mac_val;
BT_OCTET8 test_mac;
- BOOLEAN enable_test_local_sign_cntr;
- UINT32 test_local_sign_cntr;
+ BOOLEAN enable_test_local_sign_cntr;
+ UINT32 test_local_sign_cntr;
#endif
-#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
#endif /* BLE_INCLUDED */
@@ -216,8 +222,9 @@
UINT8 state;
tBTM_IO_CAP loc_io_caps; /* IO capability of the local device */
- BOOLEAN loc_auth_req; /* the auth_req flag */
+ tBTM_AUTH_REQ loc_auth_req; /* the auth_req flag */
BD_FEATURES brcm_features; /* Broadcom specific features bit mask */
+#define BTM_RELOAD_LE_HOST_FEATURE 0x10
#define BTM_RE_READ_1ST_PAGE 0x01 /* Set it if you set at least one of "..._HOST_MAY_SUPP_..." bits */
#define BTM_HOST_MAY_SUPP_SSP 0x02
@@ -504,13 +511,16 @@
tBLE_ADDR_TYPE ble_addr_type; /* LE device type: public or random address */
tBLE_ADDR_TYPE static_addr_type; /* static address type */
BD_ADDR static_addr; /* static address */
-#if BTM_BLE_PRIVACY_SPT == TRUE
+#if BLE_PRIVACY_SPT == TRUE
BD_ADDR cur_rand_addr; /* current random address */
#define BTM_BLE_ADDR_PSEUDO 0 /* address index device record */
#define BTM_BLE_ADDR_RRA 1 /* cur_rand_addr */
-#define BTM_BLE_ADDR_STATIC 2 /* static_addr */
+#define BTM_BLE_ADDR_RECONN 2 /* reconnection address */
+#define BTM_BLE_ADDR_STATIC 3 /* static_addr */
UINT8 active_addr_type;
+
+ BOOLEAN privacy_enabled; /* remote device privacy enabled or not */
#endif
#if SMP_INCLUDED == TRUE
@@ -519,6 +529,7 @@
#endif
} tBTM_SEC_BLE;
+
#endif /* BLE_INCLUDED */
/*
@@ -546,8 +557,14 @@
#define BTM_SEC_LINK_KEY_AUTHED 0x20
#define BTM_SEC_ROLE_SWITCHED 0x40
#define BTM_SEC_IN_USE 0x80
+ /* LE link security flag */
+#define BTM_SEC_LE_AUTHENTICATED 0x0200 /* 0x0200 */
+#define BTM_SEC_LE_ENCRYPTED 0x0400 /* 0x04 */
+#define BTM_SEC_LE_NAME_KNOWN 0x0800
+#define BTM_SEC_LE_LINK_KEY_KNOWN 0x1000 /* 0x10 */
+#define BTM_SEC_LE_LINK_KEY_AUTHED 0x2000
- UINT8 sec_flags; /* Current device security state */
+ UINT16 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[HCI_EXT_FEATURES_PAGE_MAX + 1]; /* Features supported by the device */
@@ -586,9 +603,10 @@
#define BTM_SM4_CONN_PEND 0x40 /* set this bit to indicate accepting acl conn; to be cleared on btm_acl_created */
UINT8 sm4; /* BTM_SM4_TRUE, if the peer supports SM4 */
tBTM_IO_CAP rmt_io_caps; /* IO capability of the peer device */
- BOOLEAN rmt_auth_req; /* the auth_req flag as in the IO caps rsp evt */
+ tBTM_AUTH_REQ rmt_auth_req; /* the auth_req flag as in the IO caps rsp evt */
#if (BLE_INCLUDED == TRUE)
+ UINT16 ble_hci_handle; /* use in DUMO connection */
UINT8 enc_key_size; /* current link encryption key size */
tBTM_SEC_BLE ble;
tBT_DEVICE_TYPE device_type;
@@ -612,6 +630,7 @@
#define BTM_SEC_IS_SM4_LEGACY(sm) ((BOOLEAN)(BTM_SM4_KNOWN == ((sm)&BTM_SM4_TRUE)))
#define BTM_SEC_IS_SM4_UNKNOWN(sm) ((BOOLEAN)(BTM_SM4_UNKNOWN == ((sm)&BTM_SM4_TRUE)))
+#define BTM_SEC_LE_MASK (BTM_SEC_LE_AUTHENTICATED|BTM_SEC_LE_ENCRYPTED|BTM_SEC_LE_LINK_KEY_KNOWN|BTM_SEC_LE_LINK_KEY_AUTHED)
/*
** Define device configuration structure
@@ -726,11 +745,13 @@
#define BTM_PAIR_FLAGS_WE_STARTED_DD 0x01 /* We want to do dedicated bonding */
#define BTM_PAIR_FLAGS_PEER_STARTED_DD 0x02 /* Peer initiated dedicated bonding */
-#define BTM_PAIR_FLAGS_DISC_WHEN_DONE 0x04
+#define BTM_PAIR_FLAGS_DISC_WHEN_DONE 0x04 /* Disconnect when done */
#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 */
+#define BTM_PAIR_FLAGS_LE_ACTIVE 0x80 /* use this bit when SMP pairing is active */
+
typedef struct
{
@@ -975,8 +996,8 @@
extern void btm_acl_init (void);
extern void btm_acl_timeout (TIMER_LIST_ENT *p_tle);
extern void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
- UINT16 hci_handle, UINT8 link_role, UINT8 is_le_link);
-extern void btm_acl_removed (BD_ADDR bda);
+ UINT16 hci_handle, UINT8 link_role, tBT_TRANSPORT transport);
+extern void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport);
extern void btm_acl_device_down (void);
extern void btm_acl_update_busy_level (tBTM_BLI_EVENT event);
extern void btm_acl_link_key_change (UINT16 handle, UINT8 status);
@@ -995,7 +1016,7 @@
extern void btm_acl_role_changed (UINT8 hci_status, BD_ADDR bd_addr, UINT8 new_role);
extern void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable);
BTM_API extern UINT16 btm_get_acl_disc_reason_code (void);
-BTM_API extern tBTM_STATUS btm_remove_acl (BD_ADDR bd_addr);
+BTM_API extern tBTM_STATUS btm_remove_acl (BD_ADDR bd_addr, tBT_TRANSPORT transport);
extern void btm_read_remote_features_complete (UINT8 *p);
extern void btm_read_remote_ext_features_complete (UINT8 *p);
extern void btm_read_remote_ext_features_failed (UINT8 status, UINT16 handle);
@@ -1005,7 +1026,7 @@
// btla-specific --
/* Read maximum data packet that can be sent over current connection */
extern UINT16 btm_get_max_packet_size (BD_ADDR addr);
-extern tACL_CONN *btm_bda_to_acl (BD_ADDR bda);
+extern tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport);
extern BOOLEAN btm_acl_notif_conn_collision (BD_ADDR bda);
#if BTM_PWR_MGR_INCLUDED == FALSE
@@ -1139,7 +1160,7 @@
extern void btm_sec_link_key_request (UINT8 *p_bda);
extern void btm_sec_pin_code_request (UINT8 *p_bda);
extern void btm_sec_update_clock_offset (UINT16 handle, UINT16 clock_offset);
-extern void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res);
+extern void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN is_le_trasnport);
#if BLE_INCLUDED == TRUE
extern void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec);
diff --git a/stack/btm/btm_pm.c b/stack/btm/btm_pm.c
index 02e3a6a..711a69b 100644
--- a/stack/btm/btm_pm.c
+++ b/stack/btm/btm_pm.c
@@ -420,7 +420,11 @@
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++)
{
- if ((p->in_use) && (!memcmp (p->remote_addr, remote_bda, BD_ADDR_LEN)))
+ if ((p->in_use) && (!memcmp (p->remote_addr, remote_bda, BD_ADDR_LEN))
+#if (BLE_INCLUDED == TRUE)
+ && p->transport == BT_TRANSPORT_BR_EDR
+#endif
+ )
{
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG2( "btm_pm_find_acl_ind ind:%d, st:%d", xx, btm_cb.pm_mode_db[xx].state);
@@ -848,15 +852,17 @@
BTM_TRACE_DEBUG2( "btm_pm_proc_mode_change new state:0x%x (old:0x%x)", p_cb->state, old_state);
#endif
- if ((p_cb->state == HCI_MODE_ACTIVE) &&
- ((p_lcb = l2cu_find_lcb_by_bd_addr (p->remote_addr)) != NULL))
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr(p->remote_addr, BT_TRANSPORT_BR_EDR)) != NULL)
{
- /* There might be any pending packets due to SNIFF or PENDING state */
- /* Trigger L2C to start transmission of the pending packets. */
- BTM_TRACE_DEBUG0 ("btm mode change to active; check l2c_link for outgoing packets");
- l2c_link_check_send_pkts (p_lcb, NULL, NULL);
+ if ((p_cb->state == BTM_PM_ST_ACTIVE) || (p_cb->state == BTM_PM_ST_SNIFF))
+ {
+ /* There might be any pending packets due to SNIFF or PENDING state */
+ /* Trigger L2C to start transmission of the pending packets. */
+ BTM_TRACE_DEBUG0("btm mode change to active; check l2c_link for outgoing packets");
+ l2c_link_check_send_pkts(p_lcb, NULL, NULL);
//btu_stop_timer (&p_lcb->timer_entry);
+ }
}
/* notify registered parties */
@@ -955,7 +961,9 @@
}
}
}
+
#endif
+
#else /* BTM_PWR_MGR_INCLUDED == TRUE */
/*******************************************************************************
@@ -984,6 +992,7 @@
#endif
+
/*******************************************************************************
**
** Function BTM_IsPowerManagerOn
@@ -998,3 +1007,5 @@
{
return BTM_PWR_MGR_INCLUDED;
}
+
+
diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c
index 2200b71..1ef3827 100644
--- a/stack/btm/btm_sco.c
+++ b/stack/btm/btm_sco.c
@@ -582,7 +582,7 @@
/* If originating, ensure that there is an ACL connection to the BD Address */
if (is_orig)
{
- if ((!remote_bda) || ((acl_handle = BTM_GetHCIConnHandle (remote_bda)) == 0xFFFF))
+ if ((!remote_bda) || ((acl_handle = BTM_GetHCIConnHandle (remote_bda, BT_TRANSPORT_BR_EDR)) == 0xFFFF))
return (BTM_UNKNOWN_ADDR);
}
@@ -682,7 +682,7 @@
{
/* If role change is in progress, do not proceed with SCO setup
* Wait till role change is complete */
- p_acl = btm_bda_to_acl(remote_bda);
+ p_acl = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (p_acl && p_acl->switch_role_state != BTM_ACL_SWKEY_STATE_IDLE)
{
BTM_TRACE_API1("Role Change is in progress for ACL handle 0x%04x",acl_handle);
@@ -740,7 +740,7 @@
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++)
{
if ((p->state == SCO_ST_PEND_UNPARK) &&
- ((acl_handle = BTM_GetHCIConnHandle (p->esco.data.bd_addr)) == hci_handle))
+ ((acl_handle = BTM_GetHCIConnHandle (p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle))
{
BTM_TRACE_API3("btm_sco_chk_pend_unpark -> (e)SCO Link for ACL handle 0x%04x, Desired Type %d, hci_status 0x%02x",
@@ -774,7 +774,7 @@
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++)
{
if ((p->state == SCO_ST_PEND_ROLECHANGE) &&
- ((acl_handle = BTM_GetHCIConnHandle (p->esco.data.bd_addr)) == hci_handle))
+ ((acl_handle = BTM_GetHCIConnHandle (p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle))
{
BTM_TRACE_API1("btm_sco_chk_pend_rolechange -> (e)SCO Link for ACL handle 0x%04x", acl_handle);
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index eb5714a..543bb1a 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -80,13 +80,19 @@
static UINT8 btm_sec_start_authorization (tBTM_SEC_DEV_REC *p_dev_rec);
BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[]);
-static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason);
+static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason, UINT16 conn_handle);
+UINT8 btm_sec_start_role_switch (tBTM_SEC_DEV_REC *p_dev_rec);
tBTM_SEC_DEV_REC *btm_sec_find_dev_by_sec_state (UINT8 state);
static BOOLEAN btm_sec_set_security_level ( CONNECTION_TYPE conn_type, char *p_name, UINT8 service_id,
UINT16 sec_level, UINT16 psm, UINT32 mx_proto_id,
UINT32 mx_chan_id);
+static BOOLEAN btm_dev_authenticated(tBTM_SEC_DEV_REC *p_dev_rec);
+static BOOLEAN btm_dev_encrypted(tBTM_SEC_DEV_REC *p_dev_rec);
+static BOOLEAN btm_dev_authorized(tBTM_SEC_DEV_REC *p_dev_rec);
+static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec);
+
/* TRUE - authenticated link key is possible */
static const BOOLEAN btm_sec_io_map [BTM_IO_CAP_MAX][BTM_IO_CAP_MAX] =
{
@@ -103,6 +109,78 @@
/*******************************************************************************
**
+** Function btm_dev_authenticated
+**
+** Description check device is authenticated
+**
+** Returns BOOLEAN TRUE or FALSE
+**
+*******************************************************************************/
+static BOOLEAN btm_dev_authenticated (tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ if(p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)
+ {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*******************************************************************************
+**
+** Function btm_dev_encrypted
+**
+** Description check device is encrypted
+**
+** Returns BOOLEAN TRUE or FALSE
+**
+*******************************************************************************/
+static BOOLEAN btm_dev_encrypted (tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ if(p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)
+ {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*******************************************************************************
+**
+** Function btm_dev_authorized
+**
+** Description check device is authorized
+**
+** Returns BOOLEAN TRUE or FALSE
+**
+*******************************************************************************/
+static BOOLEAN btm_dev_authorized (tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ if(p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED)
+ {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*******************************************************************************
+**
+** Function btm_serv_trusted
+**
+** Description check service is trusted
+**
+** Returns BOOLEAN TRUE or FALSE
+**
+*******************************************************************************/
+static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec)
+{
+ if(BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask, p_serv_rec->service_id))
+ {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*******************************************************************************
+**
** Function BTM_SecRegister
**
** Description Application manager calls this function to register for
@@ -121,28 +199,29 @@
BTM_TRACE_EVENT0 ("BTM_Sec: application registered");
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- BTM_TRACE_ERROR1 ("BTM_SecRegister:p_cb_info->p_le_callback == 0x%x ", p_cb_info->p_le_callback);
-
if (p_cb_info->p_le_callback)
{
-#if SMP_INCLUDED == TRUE
- BTM_TRACE_EVENT0 ("BTM_Sec: SMP_Register( btm_proc_smp_cback )");
- SMP_Register(btm_proc_smp_cback);
-#endif
- /* if no IR is loaded, need to regenerate all the keys */
- if (memcmp(btm_cb.devcb.id_keys.ir, &temp_value, sizeof(BT_OCTET16)) == 0)
+ BTM_TRACE_ERROR1 ("BTM_SecRegister:p_cb_info->p_le_callback == 0x%x ", p_cb_info->p_le_callback);
+
+ if (p_cb_info->p_le_callback)
{
- btm_ble_reset_id();
+ #if SMP_INCLUDED == TRUE
+ BTM_TRACE_EVENT0 ("BTM_Sec: SMP_Register( btm_proc_smp_cback )");
+ SMP_Register(btm_proc_smp_cback);
+ #endif
+ /* if no IR is loaded, need to regenerate all the keys */
+ if (memcmp(btm_cb.devcb.id_keys.ir, &temp_value, sizeof(BT_OCTET16)) == 0)
+ {
+ btm_ble_reset_id();
+ }
+ }
+ else
+ {
+ BTM_TRACE_ERROR0 ("BTM_SecRegister:p_cb_info->p_le_callback == NULL ");
}
}
- else
- {
- BTM_TRACE_ERROR0 ("BTM_SecRegister:p_cb_info->p_le_callback == NULL ");
- }
#endif
-
-
btm_cb.api = *p_cb_info;
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
BTM_TRACE_ERROR1 ("BTM_SecRegister: btm_cb.api.p_le_callback = 0x%x ", btm_cb.api.p_le_callback);
@@ -270,7 +349,34 @@
if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
{
- *p_sec_flags = p_dev_rec->sec_flags;
+ *p_sec_flags = (UINT8) p_dev_rec->sec_flags;
+ return(TRUE);
+ }
+ BTM_TRACE_ERROR0 ("BTM_GetSecurityFlags false");
+ return(FALSE);
+}
+
+/*******************************************************************************
+**
+** Function BTM_GetSecurityFlagsByTransport
+**
+** Description Get security flags for the device on a particular transport
+**
+** Returns BOOLEAN TRUE or FALSE is device found
+**
+*******************************************************************************/
+BOOLEAN BTM_GetSecurityFlagsByTransport (BD_ADDR bd_addr, UINT8 * p_sec_flags,
+ tBT_TRANSPORT transport)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec;
+
+ if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
+ {
+ if (transport == BT_TRANSPORT_BR_EDR)
+ *p_sec_flags = (UINT8) p_dev_rec->sec_flags;
+ else
+ *p_sec_flags = (UINT8) (p_dev_rec->sec_flags >> 8);
+
return(TRUE);
}
BTM_TRACE_ERROR0 ("BTM_GetSecurityFlags false");
@@ -958,7 +1064,8 @@
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_AUTHED;
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
+ if (btm_cb.api.p_auth_complete_callback)
+ (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
p_dev_rec->sec_bd_name, HCI_ERR_AUTH_FAILURE);
}
return;
@@ -1028,25 +1135,21 @@
if (res != BTM_SUCCESS)
{
- btm_sec_dev_rec_cback_event (p_dev_rec, res);
+ btm_sec_dev_rec_cback_event (p_dev_rec, res, FALSE);
return;
}
if ((res = (UINT8)btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
{
- btm_sec_dev_rec_cback_event (p_dev_rec, res);
+ btm_sec_dev_rec_cback_event (p_dev_rec, res, FALSE);
}
}
-
-
/*******************************************************************************
**
-** Function BTM_SecBond
+** Function btm_sec_bond_by_transport
**
-** Description This function is called to perform bonding with peer device.
-** If the connection is already up, but not secure, pairing
-** is attempted. If already paired BTM_SUCCESS is returned.
+** Description this is the bond function that will start either SSP or SMP.
**
** Parameters: bd_addr - Address of the device to bond
** pin_len - length in bytes of the PIN Code
@@ -1055,16 +1158,20 @@
**
** Note: After 2.1 parameters are not used and preserved here not to change API
*******************************************************************************/
-tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+ UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
{
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_STATUS status;
UINT8 *p_features;
UINT8 ii;
-
- BTM_TRACE_API6 ("BTM_SecBond BDA: %02x:%02x:%02x:%02x:%02x:%02x",
+ tACL_CONN *p= btm_bda_to_acl(bd_addr, transport);
+ BTM_TRACE_API6 ("btm_sec_bond_by_transport 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]);
+ BTM_TRACE_DEBUG1("btm_sec_bond_by_transport: Transport used %d" , transport);
+
+
/* Other security process is in progress */
if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
{
@@ -1075,13 +1182,19 @@
if ((p_dev_rec = btm_find_or_alloc_dev (bd_addr)) == NULL)
{
return(BTM_NO_RESOURCES);
- }
+ }
BTM_TRACE_DEBUG1 ("before update sec_flags=0x%x", p_dev_rec->sec_flags);
/* Finished if connection is active and already paired */
- if ( (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)
- && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED) )
+ if ( ((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_BR_EDR
+ && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))
+#if (BLE_INCLUDED == TRUE)
+ ||((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_LE
+ && (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))
+#endif
+
+ )
{
BTM_TRACE_WARNING0("BTM_SecBond -> Already Paired");
return(BTM_SUCCESS);
@@ -1107,25 +1220,28 @@
if (trusted_mask)
BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ if (transport == BT_TRANSPORT_LE)
+ {
+ p_dev_rec->sec_flags &= ~ BTM_SEC_LE_MASK;
+
+ if (SMP_Pair(bd_addr) == SMP_STARTED)
+ {
+ btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
+ p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
+ btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
+ return BTM_CMD_STARTED;
+ }
+
+ btm_cb.pairing_flags = 0;
+ return(BTM_NO_RESOURCES);
+ }
+#endif
+
p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
| BTM_SEC_ROLE_SWITCHED | BTM_SEC_LINK_KEY_AUTHED);
-#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- /* LE device, do SMP pairing */
- if (BTM_UseLeLink(bd_addr))
- {
- if (SMP_Pair(bd_addr) == SMP_STARTED)
- {
- btm_cb.pairing_state = BTM_PAIR_STATE_WAIT_AUTH_COMPLETE;
- p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
- return BTM_CMD_STARTED;
- }
- else
- return(BTM_NO_RESOURCES);
- }
-#endif
-
BTM_TRACE_DEBUG1 ("after update sec_flags=0x%x", p_dev_rec->sec_flags);
if (!HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
{
@@ -1157,7 +1273,7 @@
#endif
/* If connection already exists... */
- if (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)
+ if (p && p->hci_handle != BTM_SEC_INVALID_HANDLE)
{
if (!btm_sec_start_authentication (p_dev_rec))
return(BTM_NO_RESOURCES);
@@ -1185,14 +1301,15 @@
* -> RNR (to learn if peer is 2.1)
* RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
- BTM_ReadRemoteDeviceName(bd_addr, NULL);
+ BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
}
else
{
/* We are accepting connection request from peer */
btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
}
- BTM_TRACE_DEBUG3 ("State:%s sm4: 0x%x sec_state:%d", btm_pair_state_descr (btm_cb.pairing_state), p_dev_rec->sm4, p_dev_rec->sec_state);
+ BTM_TRACE_DEBUG3 ("State:%s sm4: 0x%x sec_state:%d",
+ btm_pair_state_descr (btm_cb.pairing_state), p_dev_rec->sm4, p_dev_rec->sec_state);
return BTM_CMD_STARTED;
}
@@ -1207,7 +1324,64 @@
return status;
}
+/*******************************************************************************
+**
+** Function BTM_SecBondByTransport
+**
+** Description This function is called to perform bonding with peer device.
+** If the connection is already up, but not secure, pairing
+** is attempted. If already paired BTM_SUCCESS is returned.
+**
+** Parameters: bd_addr - Address of the device to bond
+** transport - doing SSP over BR/EDR or SMP over LE
+** 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)
+**
+** Note: After 2.1 parameters are not used and preserved here not to change API
+*******************************************************************************/
+tBTM_STATUS BTM_SecBondByTransport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+ UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+#if SMP_INCLUDED == TRUE
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type;
+ BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
+ /* LE device, do SMP pairing */
+ if ((transport == BT_TRANSPORT_LE && (dev_type & BT_DEVICE_TYPE_BLE) == 0) ||
+ (transport == BT_TRANSPORT_BR_EDR && (dev_type & BT_DEVICE_TYPE_BREDR) == 0))
+ {
+ return BTM_ILLEGAL_ACTION;
+ }
+#endif
+ return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin, trusted_mask);
+}
+
+/*******************************************************************************
+**
+** Function BTM_SecBond
+**
+** Description This function is called to perform bonding with peer device.
+** If the connection is already up, but not secure, pairing
+** is attempted. If already paired BTM_SUCCESS is returned.
+**
+** 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)
+**
+** Note: After 2.1 parameters are not used and preserved here not to change API
+*******************************************************************************/
+tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+#if BLE_INCLUDED == TRUE
+ if (BTM_UseLeLink(bd_addr))
+ transport = BT_TRANSPORT_LE;
+#endif
+ return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin, trusted_mask);
+}
/*******************************************************************************
**
** Function BTM_SecBondCancel
@@ -1216,14 +1390,12 @@
** with peer device.
**
** Parameters: bd_addr - Address of the peer device
+** transport - FALSE for BR/EDR link; TRUE for LE link
**
*******************************************************************************/
tBTM_STATUS BTM_SecBondCancel (BD_ADDR bd_addr)
{
tBTM_SEC_DEV_REC *p_dev_rec;
-#if SMP_INCLUDED == TRUE
- tACL_CONN *p=NULL;
-#endif
BTM_TRACE_API2 ("BTM_SecBondCancel() State: %s flags:0x%x",
btm_pair_state_descr (btm_cb.pairing_state), btm_cb.pairing_flags);
@@ -1233,19 +1405,17 @@
return BTM_UNKNOWN_ADDR;
#if SMP_INCLUDED == TRUE
- p = btm_bda_to_acl(bd_addr);
- if (p && p->is_le_link &&
- (p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING))
+ if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_LE_ACTIVE)
{
- BTM_TRACE_DEBUG0 ("Cancel LE pairing");
- if (SMP_PairCancel(bd_addr))
+ if (p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
{
- return BTM_CMD_STARTED;
+ BTM_TRACE_DEBUG0 ("Cancel LE pairing");
+ if (SMP_PairCancel(bd_addr))
+ {
+ return BTM_CMD_STARTED;
+ }
}
- else
- {
- return BTM_WRONG_MODE;
- }
+ return BTM_WRONG_MODE;
}
#endif
@@ -1271,7 +1441,7 @@
/* If the HCI link was set up by Bonding process */
if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE)
- return btm_sec_send_hci_disconnect(p_dev_rec, HCI_ERR_PEER_USER);
+ return btm_sec_send_hci_disconnect(p_dev_rec, HCI_ERR_PEER_USER, p_dev_rec->hci_handle);
else
l2cu_update_lcb_4_bonding(bd_addr, FALSE);
@@ -1375,6 +1545,8 @@
** p_ref_data - pointer to any data the caller wishes to receive
** in the callback function upon completion.
* can be set to NULL if not used.
+** transport - TRUE to encryption the link over LE trasnport
+** or FALSE for BR/EDR trasnport
**
** Returns BTM_SUCCESS - already encrypted
** BTM_PENDING - command will be returned in the callback
@@ -1383,41 +1555,45 @@
** BTM_MODE_UNSUPPORTED - if security manager not linked in.
**
*******************************************************************************/
-tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBTM_SEC_CBACK *p_callback,
+tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CBACK *p_callback,
void *p_ref_data)
{
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_STATUS rc;
-
#if BLE_INCLUDED == TRUE
- tACL_CONN *p;
- p = btm_bda_to_acl(bd_addr);
+ tACL_CONN *p = btm_bda_to_acl(bd_addr, transport);
#endif
p_dev_rec = btm_find_dev (bd_addr);
- if (!p_dev_rec || (p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE))
+
+ if (!p_dev_rec ||
+ (transport == BT_TRANSPORT_BR_EDR && p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE)
+#if BLE_INCLUDED == TRUE
+ || (transport == BT_TRANSPORT_LE && p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE)
+#endif
+ )
{
/* Connection should be up and runnning */
BTM_TRACE_WARNING0 ("Security Manager: BTM_SetEncryption not connected");
if (p_callback)
- (*p_callback) (bd_addr, p_ref_data, BTM_WRONG_MODE);
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_WRONG_MODE);
return(BTM_WRONG_MODE);
}
-
- if (
-#if BLE_INCLUDED == TRUE
- !p->is_le_link &&
+ if ((transport == BT_TRANSPORT_BR_EDR &&
+ (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ || (transport == BT_TRANSPORT_LE &&
+ (p_dev_rec->sec_flags & BTM_SEC_LE_ENCRYPTED))
#endif
- (p_dev_rec->sec_flags & (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED))
- == (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED))
+ )
{
BTM_TRACE_EVENT0 ("Security Manager: BTM_SetEncryption already encrypted");
if (p_callback)
- (*p_callback) (bd_addr, p_ref_data, BTM_SUCCESS);
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_SUCCESS);
return(BTM_SUCCESS);
}
@@ -1428,7 +1604,7 @@
BTM_TRACE_WARNING0 ("Security Manager: BTM_SetEncryption busy");
if (p_callback)
- (*p_callback) (bd_addr, p_ref_data, BTM_BUSY);
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_BUSY);
return(BTM_BUSY);
}
@@ -1441,8 +1617,9 @@
BTM_TRACE_API4 ("Security Manager: BTM_SetEncryption Handle:%d State:%d Flags:0x%x Required:0x%x",
p_dev_rec->hci_handle, p_dev_rec->sec_state, p_dev_rec->sec_flags,
p_dev_rec->security_required);
+
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (p->is_le_link)
+ if (transport == BT_TRANSPORT_LE)
{
rc = btm_ble_set_encryption(bd_addr, p_ref_data, p->link_role);
}
@@ -1451,12 +1628,12 @@
rc = btm_sec_execute_procedure (p_dev_rec);
- if ( rc != BTM_CMD_STARTED)
+ if (rc != BTM_CMD_STARTED && rc != BTM_BUSY)
{
if (p_callback)
{
p_dev_rec->p_callback = NULL;
- (*p_callback) (bd_addr, p_dev_rec->p_ref_data, rc);
+ (*p_callback) (bd_addr, transport, p_dev_rec->p_ref_data, rc);
}
}
return(rc);
@@ -1465,13 +1642,13 @@
/*******************************************************************************
* disconnect the ACL link, if it's not done yet.
*******************************************************************************/
-static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason)
+static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason, UINT16 conn_handle)
{
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);
+ conn_handle, reason);
/* if some other thread disconnecting, we do not send second command */
if (BTM_SEC_STATE_DISCONNECTING != old_state)
@@ -1480,16 +1657,18 @@
#if BTM_DISC_DURING_RS == TRUE
/* If a Role Switch is in progress, delay the HCI Disconnect to avoid controller problem (4329B1) */
- if (p_dev_rec->rs_disc_pending == BTM_SEC_RS_PENDING)
+ if (p_dev_rec->rs_disc_pending == BTM_SEC_RS_PENDING &&
+ p_dev_rec->hci_handle == conn_handle)
+
{
- BTM_TRACE_ERROR0("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect");
+ BTM_TRACE_DEBUG0("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;
status = BTM_SUCCESS;
}
else
#endif
/* Tear down the HCI link */
- if (!btsnd_hcic_disconnect (p_dev_rec->hci_handle, reason))
+ if (!btsnd_hcic_disconnect (conn_handle, reason))
{
/* could not send disconnect. restore old state */
p_dev_rec->sec_state = old_state;
@@ -1579,7 +1758,7 @@
btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
if (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE);
+ btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
else
BTM_SecBondCancel(bd_addr);
@@ -1951,9 +2130,17 @@
if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)
{
is_possible = FALSE;
+ if(p_dev_rec->p_cur_service)
+ {
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);
+ }
+ else
+ {
+ BTM_TRACE_DEBUG3 ("btm_sec_is_upgrade_possible link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, ",
+ p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps, mtm_check);
+ }
/* Already have a link key to the connected peer. Is the link key secure enough?
** Is a link key upgrade even possible?
*/
@@ -2050,6 +2237,7 @@
tBTM_STATUS rc = BTM_SUCCESS;
BOOLEAN chk_acp_auth_done = FALSE;
BOOLEAN is_originator;
+ BOOLEAN transport = FALSE; /* should check PSM range in LE connection oriented L2CAP connection */
#if (L2CAP_UCD_INCLUDED == TRUE)
if (conn_type & CONNECTION_TYPE_ORIG_MASK)
@@ -2077,7 +2265,7 @@
{
BTM_TRACE_WARNING1 ("btm_sec_l2cap_access_req() PSM:%d no application registerd", psm);
- (*p_callback) (bd_addr, p_ref_data, BTM_MODE_UNSUPPORTED);
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_MODE_UNSUPPORTED);
return(BTM_MODE_UNSUPPORTED);
}
@@ -2085,7 +2273,7 @@
/* SDP connection we will always let through */
if (BT_PSM_SDP == psm)
{
- (*p_callback) (bd_addr, p_ref_data, BTM_SUCCESS_NO_SECURITY);
+ (*p_callback) (bd_addr,transport, p_ref_data, BTM_SUCCESS_NO_SECURITY);
return(BTM_SUCCESS);
}
@@ -2119,7 +2307,7 @@
if (rc == BTM_SUCCESS)
{
if (p_callback)
- (*p_callback) (bd_addr, (void *)p_ref_data, BTM_SUCCESS);
+ (*p_callback) (bd_addr, transport, (void *)p_ref_data, BTM_SUCCESS);
return(BTM_SUCCESS);
}
@@ -2148,9 +2336,9 @@
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))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_FLAGS) && (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED))) )
+ ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec))) ||
+ ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && btm_dev_encrypted(p_dev_rec))) ||
+ ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_FLAGS) && btm_dev_authorized(p_dev_rec) && btm_dev_encrypted(p_dev_rec))) )
{
rc = BTM_SUCCESS;
}
@@ -2158,9 +2346,12 @@
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))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) && (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED))) )
+ (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec)) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && btm_dev_encrypted(p_dev_rec)) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHORIZE) && (btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec))) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_AUTHORIZE)) && ((btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_authenticated(p_dev_rec))) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHORIZE)) && ((btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_encrypted(p_dev_rec))) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) && btm_dev_encrypted(p_dev_rec) && (btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec))))
{
rc = BTM_SUCCESS;
}
@@ -2169,7 +2360,7 @@
if (rc == BTM_SUCCESS)
{
if (p_callback)
- (*p_callback) (bd_addr, (void *)p_ref_data, BTM_SUCCESS);
+ (*p_callback) (bd_addr, transport, (void *)p_ref_data, BTM_SUCCESS);
return(BTM_SUCCESS);
}
@@ -2262,7 +2453,7 @@
p_dev_rec->security_required = old_security_required;
p_dev_rec->is_originator = old_is_originator;
- (*p_callback) (bd_addr, p_ref_data, BTM_SUCCESS);
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_SUCCESS);
return(BTM_SUCCESS);
}
@@ -2277,7 +2468,7 @@
p_dev_rec->security_required = old_security_required;
p_dev_rec->is_originator = old_is_originator;
- (*p_callback) (bd_addr, p_ref_data, BTM_SUCCESS);
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_SUCCESS);
return(BTM_SUCCESS);
}
@@ -2299,9 +2490,9 @@
BTM_TRACE_ERROR0 ("peer should have initiated security process by now (SM4 to SM4)");
p_dev_rec->p_callback = p_callback;
p_dev_rec->sec_state = BTM_SEC_STATE_DELAY_FOR_ENC;
- (*p_callback) (bd_addr, p_ref_data, rc);
+ (*p_callback) (bd_addr, transport, p_ref_data, rc);
- return(BTM_SUCCESS);
+ return(BTM_CMD_STARTED);
}
}
@@ -2330,7 +2521,7 @@
if ((rc = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
{
p_dev_rec->p_callback = NULL;
- (*p_callback) (bd_addr, p_dev_rec->p_ref_data, (UINT8)rc);
+ (*p_callback) (bd_addr, transport, p_dev_rec->p_ref_data, (UINT8)rc);
}
return(rc);
@@ -2368,6 +2559,7 @@
tBTM_SEC_SERV_REC *p_serv_rec;
tBTM_STATUS rc;
UINT16 security_required;
+ BOOLEAN transport = FALSE;/* should check PSM range in LE connection oriented L2CAP connection */
BTM_TRACE_DEBUG1 ("btm_sec_mx_access_request is_originator:%d", is_originator);
/* Find or get oldest record */
@@ -2380,7 +2572,7 @@
if (!p_serv_rec)
{
if (p_callback)
- (*p_callback) (bd_addr, p_ref_data, BTM_MODE_UNSUPPORTED);
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_MODE_UNSUPPORTED);
BTM_TRACE_ERROR3 ("Security Manager: MX service not found PSM:%d Proto:%d SCN:%d",
psm, mx_proto_id, mx_chan_id);
@@ -2406,8 +2598,8 @@
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)))
+ ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec))) ||
+ ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && btm_dev_encrypted(p_dev_rec)))
)
{
rc = BTM_SUCCESS;
@@ -2416,8 +2608,11 @@
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)))
+ ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec))) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHORIZE) && (btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec))) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_AUTHENTICATE)) && ((btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_authenticated(p_dev_rec))) ||
+ (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT)) && ((btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec))&& btm_dev_encrypted(p_dev_rec))) ||
+ ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && btm_dev_encrypted(p_dev_rec)))
)
{
rc = BTM_SUCCESS;
@@ -2462,7 +2657,7 @@
{
p_dev_rec->p_callback = NULL;
- (*p_callback) (bd_addr, p_ref_data, (UINT8)rc);
+ (*p_callback) (bd_addr,transport, p_ref_data, (UINT8)rc);
}
}
@@ -2666,7 +2861,7 @@
while ((p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_dequeue (&bq)) != NULL)
{
/* Check that the ACL is still up before starting security procedures */
- if (btm_bda_to_acl(p_e->bd_addr) != NULL)
+ if (btm_bda_to_acl(p_e->bd_addr, BT_TRANSPORT_BR_EDR) != NULL)
{
BTM_TRACE_EVENT4 ("btm_sec_check_pending_reqs() submitting PSM: 0x%04x Is_Orig: %u mx_proto_id: %u mx_chan_id: %u",
p_e->psm, p_e->is_orig, p_e->mx_proto_id, p_e->mx_chan_id);
@@ -2747,9 +2942,13 @@
* right now. */
if (HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
{
+ btsnd_hcic_write_simple_pairing_mode(HCI_SP_MODE_ENABLED);
#if BLE_INCLUDED == TRUE
btsnd_hcic_set_event_mask(LOCAL_BR_EDR_CONTROLLER_ID,
(UINT8 *)HCI_DUMO_EVENT_MASK_EXT);
+
+ btsnd_hcic_ble_set_evt_mask((UINT8 *)HCI_BLE_EVENT_MASK_DEF);
+
#else
btsnd_hcic_set_event_mask(LOCAL_BR_EDR_CONTROLLER_ID,
(UINT8 *)HCI_LISBON_EVENT_MASK_EXT);
@@ -2815,7 +3014,7 @@
tL2C_LCB *p_lcb;
/* Make sure an L2cap link control block is available */
- if ((p_lcb = l2cu_allocate_lcb (p_dev_rec->bd_addr, TRUE)) == NULL)
+ if ((p_lcb = l2cu_allocate_lcb (p_dev_rec->bd_addr, TRUE, BT_TRANSPORT_BR_EDR)) == NULL)
{
BTM_TRACE_WARNING6 ("Security Manager: failed allocate LCB [%02x%02x%02x%02x%02x%02x]",
p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
@@ -2827,7 +3026,7 @@
/* set up the control block to indicated dedicated bonding */
btm_cb.pairing_flags |= BTM_PAIR_FLAGS_DISC_WHEN_DONE;
- if (l2cu_create_conn(p_lcb) == FALSE)
+ if (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE)
{
BTM_TRACE_WARNING6 ("Security Manager: failed create [%02x%02x%02x%02x%02x%02x]",
p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
@@ -2995,23 +3194,29 @@
{
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, status);
+ if (btm_cb.api.p_auth_complete_callback)
+ (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
+ p_dev_rec->sec_bd_name, status);
return;
}
/* if peer is very old legacy devices, HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT is not reported */
if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4))
{
- /* set the KNOWN flag only if BTM_PAIR_FLAGS_REJECTED_CONNECT is not set.
- * If it is set, there may be a race condition */
- BTM_TRACE_EVENT1 ("btm_sec_rmt_name_request_complete IS_SM4_UNKNOWN Flags:0x%04x", btm_cb.pairing_flags);
+ /* set the KNOWN flag only if BTM_PAIR_FLAGS_REJECTED_CONNECT is not set.*/
+ /* If it is set, there may be a race condition */
+ BTM_TRACE_DEBUG1 ("btm_sec_rmt_name_request_complete IS_SM4_UNKNOWN Flags:0x%04x",
+ btm_cb.pairing_flags);
if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_REJECTED_CONNECT) == 0)
{
p_dev_rec->sm4 |= BTM_SM4_KNOWN;
}
}
+ BTM_TRACE_DEBUG5("%s, SM4 Value: %x, Legacy:%d,IS SM4:%d, Unknown:%d",__FUNCTION__,
+ p_dev_rec->sm4, BTM_SEC_IS_SM4_LEGACY(p_dev_rec->sm4),
+ BTM_SEC_IS_SM4(p_dev_rec->sm4),BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4));
+
/* BT 2.1 or carkit, bring up the connection to force the peer to request PIN.
** Else prefetch (btm_sec_check_prefetch_pin will do the prefetching if needed)
*/
@@ -3030,6 +3235,7 @@
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
+ if (btm_cb.api.p_auth_complete_callback)
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
p_dev_rec->sec_bd_name, HCI_ERR_MEMORY_FULL);
}
@@ -3040,7 +3246,7 @@
{
BTM_TRACE_WARNING0 ("btm_sec_rmt_name_request_complete: wrong BDA, retry with pairing BDA");
- BTM_ReadRemoteDeviceName (btm_cb.pairing_bda, NULL);
+ BTM_ReadRemoteDeviceName (btm_cb.pairing_bda, NULL, BT_TRANSPORT_BR_EDR);
return;
}
}
@@ -3084,7 +3290,7 @@
/* If get name failed, notify the waiting layer */
if (status != HCI_SUCCESS)
{
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING);
+ btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
return;
}
@@ -3102,7 +3308,7 @@
return;
/* There is no next procedure or start of procedure failed, notify the waiting layer */
- btm_sec_dev_rec_cback_event (p_dev_rec, status);
+ btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
}
/*******************************************************************************
@@ -3592,7 +3798,11 @@
if (disc)
{
/* simple pairing failed */
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE);
+ /* Avoid sending disconnect on HCI_ERR_PEER_USER */
+ if ((status != HCI_ERR_PEER_USER) && (status != HCI_ERR_CONN_CAUSE_LOCAL_HOST))
+ {
+ btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
+ }
}
}
@@ -3831,7 +4041,10 @@
p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
if (status != HCI_SUCCESS)
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_PEER_USER);
+ {
+ if(((status != HCI_ERR_PEER_USER) && (status != HCI_ERR_CONN_CAUSE_LOCAL_HOST)))
+ btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_PEER_USER, p_dev_rec->hci_handle);
+ }
else
l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
@@ -3871,11 +4084,11 @@
}
}
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING);
+ btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE)
{
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE);
+ btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
}
return;
}
@@ -3887,7 +4100,7 @@
/* If there is no next procedure, or procedure failed to start, notify the caller */
if (status != BTM_CMD_STARTED)
- btm_sec_dev_rec_cback_event (p_dev_rec, status);
+ btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
}
/*******************************************************************************
@@ -3933,7 +4146,8 @@
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- tACL_CONN *p_acl;
+ tACL_CONN *p_acl = NULL;
+ UINT8 acl_idx = btm_handle_to_acl_index(handle);
#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);
@@ -3952,19 +4166,30 @@
return;
if ((status == HCI_SUCCESS) && encr_enable)
- p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED);
+ {
+ if (p_dev_rec->hci_handle == handle)
+ p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED);
+ else
+ p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED);
+ }
/* It is possible that we decrypted the link to perform role switch */
/* mark link not to be encrypted, so that when we execute security next time it will kick in again */
if ((status == HCI_SUCCESS) && !encr_enable)
- p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED;
+ {
+ if (p_dev_rec->hci_handle == handle)
+ p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED;
+ else
+ p_dev_rec->sec_flags &= ~BTM_SEC_LE_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
- p_acl = btm_bda_to_acl(p_dev_rec->bd_addr);
+ if (acl_idx != MAX_L2CAP_LINKS )
+ p_acl = &btm_cb.acl_db[acl_idx];
- if (p_acl && p_acl->is_le_link)
+ if (p_acl && p_acl->transport == BT_TRANSPORT_LE)
{
btm_ble_link_encrypted(p_dev_rec->bd_addr, encr_enable);
return;
@@ -3991,7 +4216,7 @@
/* If encryption setup failed, notify the waiting layer */
if (status != HCI_SUCCESS)
{
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING);
+ btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
return;
}
@@ -4000,7 +4225,7 @@
/* If there is no next procedure, or procedure failed to start, notify the caller */
if (status != BTM_CMD_STARTED)
- btm_sec_dev_rec_cback_event (p_dev_rec, status);
+ btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
}
/*******************************************************************************
@@ -4060,6 +4285,7 @@
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
+ if (btm_cb.api.p_auth_complete_callback)
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
p_dev_rec->sec_bd_name, HCI_ERR_MEMORY_FULL);
}
@@ -4081,6 +4307,7 @@
UINT8 res;
BOOLEAN is_pairing_device = FALSE;
tACL_CONN *p_acl_cb;
+ UINT8 bit_shift = 0;
btm_acl_resubmit_page();
@@ -4108,9 +4335,6 @@
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
{
@@ -4121,6 +4345,10 @@
}
else /* Update the timestamp for this device */
{
+
+#if BLE_INCLUDED == TRUE
+ bit_shift = (handle == p_dev_rec->ble_hci_handle) ? 8 :0;
+#endif
p_dev_rec->timestamp = btm_cb.dev_rec_count++;
if (p_dev_rec->sm4 & BTM_SM4_CONN_PEND)
{
@@ -4147,7 +4375,7 @@
else
{
btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
- BTM_ReadRemoteDeviceName(p_dev_rec->bd_addr, NULL);
+ BTM_ReadRemoteDeviceName(p_dev_rec->bd_addr, NULL, BT_TRANSPORT_BR_EDR);
}
#if BTM_DISC_DURING_RS == TRUE
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
@@ -4164,6 +4392,10 @@
}
}
+#if BLE_INCLUDED == TRUE
+ p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
+#endif
+
#if BTM_DISC_DURING_RS == TRUE
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
#endif
@@ -4185,7 +4417,7 @@
{
/* Try again: RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
- BTM_ReadRemoteDeviceName(bda, NULL);
+ BTM_ReadRemoteDeviceName(bda, NULL, BT_TRANSPORT_BR_EDR);
return;
}
@@ -4221,7 +4453,7 @@
if (is_pairing_device)
{
p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
+ p_dev_rec->sec_flags &= ~((BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED) << bit_shift);
BTM_TRACE_DEBUG1 ("security_required:%x ", p_dev_rec->security_required );
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
@@ -4234,17 +4466,33 @@
p_dev_rec->sec_bd_name, status);
}
}
- else if ((status == HCI_ERR_AUTH_FAILURE) ||
+ /*
+ Do not send authentication failure, if following conditions hold good
+ 1. BTM Sec Pairing state is idle
+ 2. Link key for the remote device is present.
+ 3. Remote is SSP capable.
+ */
+ else if ((p_dev_rec->link_key_type <= BTM_LKEY_TYPE_REMOTE_UNIT) &&
+ (((status == HCI_ERR_AUTH_FAILURE) ||
(status == HCI_ERR_KEY_MISSING) ||
(status == HCI_ERR_HOST_REJECT_SECURITY) ||
(status == HCI_ERR_PAIRING_NOT_ALLOWED) ||
(status == HCI_ERR_UNIT_KEY_USED) ||
(status == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) ||
(status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) ||
- (status == HCI_ERR_REPEATED_ATTEMPTS))
+ (status == HCI_ERR_REPEATED_ATTEMPTS))))
{
p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
- p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_KNOWN;
+ p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN << bit_shift);
+
+
+#ifdef BRCM_NOT_4_BTE
+ /* If we rejected pairing, pass this special result code */
+ if (btm_cb.acl_disc_reason == HCI_ERR_HOST_REJECT_SECURITY)
+ {
+ status = HCI_ERR_HOST_REJECT_SECURITY;
+ }
+#endif
/* We need to notify host that the key is not known any more */
if (btm_cb.api.p_auth_complete_callback)
@@ -4257,9 +4505,9 @@
if (status == HCI_ERR_CONNECTION_TOUT || status == HCI_ERR_LMP_RESPONSE_TIMEOUT ||
status == HCI_ERR_UNSPECIFIED || status == HCI_ERR_PAGE_TIMEOUT)
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_DEVICE_TIMEOUT);
+ btm_sec_dev_rec_cback_event (p_dev_rec, BTM_DEVICE_TIMEOUT, FALSE);
else
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING);
+ btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
return;
}
@@ -4304,7 +4552,7 @@
/* role may not be correct here, it will be updated by l2cap, but we need to */
/* notify btm_acl that link is up, so starting of rmt name request will not */
/* set paging flag up */
- p_acl_cb = btm_bda_to_acl(bda);
+ p_acl_cb = btm_bda_to_acl(bda, BT_TRANSPORT_BR_EDR);
if (p_acl_cb)
{
/* whatever is in btm_establish_continue() without reporting the BTM_BL_CONN_EVT event */
@@ -4318,19 +4566,19 @@
BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
#endif
}
- btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, FALSE);
+ btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, BT_TRANSPORT_BR_EDR);
/* Initialize security flags. We need to do that because some */
/* authorization complete could have come after the connection is dropped */
/* and that would set wrong flag that link has been authorized already */
- p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED |
- BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
+ p_dev_rec->sec_flags &= ~((BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED |
+ BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED) << bit_shift);
if (enc_mode != HCI_ENCRYPT_MODE_DISABLED)
- p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED);
+ p_dev_rec->sec_flags |= ((BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED) << bit_shift);
if (btm_cb.security_mode == BTM_SEC_MODE_LINK)
- p_dev_rec->sec_flags |= BTM_SEC_AUTHENTICATED;
+ p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED << bit_shift);
p_dev_rec->link_key_changed = FALSE;
@@ -4341,7 +4589,7 @@
if (!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN) || p_dev_rec->is_originator)
{
if ((res = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
- btm_sec_dev_rec_cback_event (p_dev_rec, res);
+ btm_sec_dev_rec_cback_event (p_dev_rec, res, FALSE);
}
return;
}
@@ -4371,7 +4619,7 @@
if (((p_dev_rec->security_required & BTM_SEC_FORCE_MASTER) && !p_dev_rec->role_master)
|| ((p_dev_rec->security_required & BTM_SEC_FORCE_SLAVE) && p_dev_rec->role_master))
{
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING);
+ btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
return;
}
@@ -4384,7 +4632,7 @@
if ((res = (UINT8)btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
{
- btm_sec_dev_rec_cback_event (p_dev_rec, res);
+ btm_sec_dev_rec_cback_event (p_dev_rec, res, FALSE);
}
}
@@ -4418,7 +4666,7 @@
return(BTM_BUSY);
}
- return(btm_sec_send_hci_disconnect(p_dev_rec, reason));
+ return(btm_sec_send_hci_disconnect(p_dev_rec, reason, handle));
}
/*******************************************************************************
@@ -4437,6 +4685,7 @@
UINT8 old_pairing_flags = btm_cb.pairing_flags;
int result = HCI_ERR_AUTH_FAILURE;
tBTM_SEC_CALLBACK *p_callback = NULL;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
/* If page was delayed for disc complete, can do it now */
btm_cb.discing = FALSE;
@@ -4446,6 +4695,8 @@
if (!p_dev_rec)
return;
+ transport = (handle == p_dev_rec->hci_handle) ? BT_TRANSPORT_BR_EDR: BT_TRANSPORT_LE;
+
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
#if BTM_DISC_DURING_RS == TRUE
@@ -4487,16 +4738,24 @@
}
}
- p_dev_rec->hci_handle = BTM_SEC_INVALID_HANDLE;
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
-
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
p_dev_rec->enc_key_size = 0;
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);
+ if (transport == BT_TRANSPORT_LE)
+ {
+ p_dev_rec->ble_hci_handle = BTM_SEC_INVALID_HANDLE;
+ p_dev_rec->sec_flags &= ~(BTM_SEC_LE_AUTHENTICATED|BTM_SEC_LE_ENCRYPTED);
+ }
+ else
+#endif
+ {
+ p_dev_rec->hci_handle = BTM_SEC_INVALID_HANDLE;
+ p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
+ }
+
+ p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
p_dev_rec->security_required = BTM_SEC_NONE;
p_callback = p_dev_rec->p_callback;
@@ -4506,7 +4765,7 @@
{
p_dev_rec->p_callback = NULL; /* when the peer device time out the authentication before
we do, this call back must be reset here */
- (*p_callback) (p_dev_rec->bd_addr, p_dev_rec->p_ref_data, BTM_ERR_PROCESSING);
+ (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, BTM_ERR_PROCESSING);
}
BTM_TRACE_EVENT1("after Update sec_flags=0x%x", p_dev_rec->sec_flags);
@@ -4741,7 +5000,7 @@
(p_cb->pairing_bda[4] << 8) + p_cb->pairing_bda[5]);
break;
}
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE);
+ btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
break;
@@ -5384,7 +5643,7 @@
if (status != BTM_CMD_STARTED)
{
/* There is no next procedure or start of procedure failed, notify the waiting layer */
- btm_sec_dev_rec_cback_event (btm_cb.p_collided_dev_rec, status);
+ btm_sec_dev_rec_cback_event (btm_cb.p_collided_dev_rec, status, FALSE);
}
}
@@ -5609,7 +5868,7 @@
** Parameters: void
**
*******************************************************************************/
-void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res)
+void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN transport)
{
tBTM_SEC_CALLBACK *p_callback = p_dev_rec->p_callback;
@@ -5617,7 +5876,7 @@
{
p_dev_rec->p_callback = NULL;
- (*p_callback) (p_dev_rec->bd_addr, p_dev_rec->p_ref_data, res);
+ (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, res);
}
btm_sec_check_pending_reqs();
@@ -5695,7 +5954,7 @@
if (btm_cb.api.p_pin_callback && ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_PIN_REQD) == 0))
{
BTM_TRACE_DEBUG0("btm_sec_check_prefetch_pin: PIN code callback called");
- if (btm_bda_to_acl(p_dev_rec->bd_addr) == NULL)
+ if (btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR) == NULL)
btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD;
(btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_dev_rec->sec_bd_name);
}
@@ -5746,12 +6005,14 @@
tBTM_SEC_DEV_REC *p_dev_rec= btm_find_dev (bda);
BOOLEAN is_bonded= FALSE;
+ if (p_dev_rec &&
#if (SMP_INCLUDED== TRUE)
- if (p_dev_rec && (p_dev_rec->ble.key_type || (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)))
+ ((p_dev_rec->ble.key_type && (p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_KNOWN))||
+#endif
+ (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)))
{
is_bonded = TRUE;
}
-#endif
BTM_TRACE_DEBUG1 ("btm_sec_is_a_bonded_dev is_bonded=%d", is_bonded);
return(is_bonded);
}
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index cef5096..32c6b58 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -139,6 +139,9 @@
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p);
static void btu_ble_proc_ltk_req (UINT8 *p);
static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p);
+#if (BLE_LLT_INCLUDED == TRUE)
+static void btu_ble_rc_param_req_evt(UINT8 *p);
+#endif
#endif
/*******************************************************************************
**
@@ -424,6 +427,12 @@
case HCI_BLE_LTK_REQ_EVT: /* received only at slave device */
btu_ble_proc_ltk_req(p);
break;
+#if (BLE_LLT_INCLUDED == TRUE)
+ case HCI_BLE_RC_PARAM_REQ_EVT:
+ btu_ble_rc_param_req_evt(p);
+ break;
+#endif
+
}
break;
#endif /* BLE_INCLUDED */
@@ -1141,6 +1150,10 @@
btm_ble_write_adv_enable_complete(p);
break;
+ case HCI_BLE_READ_SUPPORTED_STATES:
+ btm_read_ble_local_supported_states_complete(p, evt_len);
+ break;
+
case HCI_BLE_TRANSMITTER_TEST:
case HCI_BLE_RECEIVER_TEST:
case HCI_BLE_TEST_END:
@@ -2269,16 +2282,7 @@
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p)
{
- /* LE connection update has completed successfully as a master. */
- /* We can enable the update request if the result is a success. */
- /* extract the HCI handle first */
- UINT8 status;
- UINT16 handle;
- BT_TRACE_0(TRACE_LAYER_HCI, TRACE_TYPE_EVENT, "btu_ble_ll_conn_param_upd_evt");
-
- STREAM_TO_UINT8 (status, p);
- STREAM_TO_UINT16 (handle, p);
- L2CA_HandleConnUpdateEvent(handle, status);
+ /* This is empty until an upper layer cares about returning event */
}
static void btu_ble_read_remote_feat_evt (UINT8 *p)
@@ -2302,5 +2306,21 @@
/**********************************************
** End of BLE Events Handler
***********************************************/
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+static void btu_ble_rc_param_req_evt(UINT8 *p)
+{
+ UINT16 handle;
+ UINT16 int_min, int_max, latency, timeout;
+
+ STREAM_TO_UINT16(handle, p);
+ STREAM_TO_UINT16(int_min, p);
+ STREAM_TO_UINT16(int_max, p);
+ STREAM_TO_UINT16(latency, p);
+ STREAM_TO_UINT16(timeout, p);
+
+ l2cble_process_rc_param_request_evt(handle, int_min, int_max, latency, timeout);
+}
+#endif /* BLE_LLT_INCLUDED */
+
#endif /* BLE_INCLUDED */
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index 9c09214..5b5108a 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -400,6 +400,9 @@
case BTU_TTYPE_L2CAP_HOLD:
case BTU_TTYPE_L2CAP_INFO:
case BTU_TTYPE_L2CAP_FCR_ACK:
+#if (BLE_INCLUDED == TRUE)
+ case BTU_TTYPE_L2CAP_END_CONN_UPD:
+#endif
l2c_process_timeout (p_tle);
break;
@@ -473,6 +476,8 @@
case BTU_TTYPE_BLE_INQUIRY:
case BTU_TTYPE_BLE_GAP_LIM_DISC:
case BTU_TTYPE_BLE_RANDOM_ADDR:
+ case BTU_TTYPE_BLE_GAP_FAST_ADV:
+ case BTU_TTYPE_BLE_OBSERVE:
btm_ble_timeout(p_tle);
break;
diff --git a/stack/gap/gap_api.c b/stack/gap/gap_api.c
index fb90d03..e04fc8e 100644
--- a/stack/gap/gap_api.c
+++ b/stack/gap/gap_api.c
@@ -734,7 +734,7 @@
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]);
+ btm_status = BTM_ReadRemoteDeviceName (addr, gap_cb.btm_cback[p_cb->index], BT_TRANSPORT_BR_EDR);
/* 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)
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
index d44577d..d67bf5a 100644
--- a/stack/gap/gap_ble.c
+++ b/stack/gap/gap_ble.c
@@ -57,7 +57,8 @@
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_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected,
+ tGATT_DISCONN_REASON reason, tGATT_TRANSPORT transport);
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 =
@@ -213,65 +214,6 @@
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
@@ -316,16 +258,6 @@
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 */
@@ -357,18 +289,6 @@
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;
-}
/******************************************************************************
**
@@ -389,26 +309,7 @@
{
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_WRITE_NOT_PERMIT;
}
}
return GATT_NOT_FOUND;
@@ -513,6 +414,21 @@
GATT_CHAR_PROP_BIT_READ);
p_db_attr ++;
+#if BTM_PERIPHERAL_ENABLED == TRUE /* Only needed for peripheral testing */
+ /* add preferred connection parameter characteristic
+ */
+ uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
+ p_db_attr->attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
+ p_db_attr->attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
+ p_db_attr->attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
+ p_db_attr->attr_value.conn_param.sp_tout = GAP_PREFER_CONN_SP_TOUT; /* 2000 */
+ p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
+ &uuid,
+ GATT_PERM_READ,
+ GATT_CHAR_PROP_BIT_READ);
+ p_db_attr ++;
+#endif
+
/* start service now */
memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
@@ -596,8 +512,6 @@
(* p_dev_name_cback)(status, p_clcb->bda, len, (char *)p_name);
}
- if (!gap_ble_process_pending_op(p_clcb) &&
- p_clcb->cl_op_uuid == 0)
GATT_Disconnect(p_clcb->conn_id);
}
@@ -612,11 +526,14 @@
**
*******************************************************************************/
static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
- BOOLEAN connected, tGATT_DISCONN_REASON reason)
+ BOOLEAN connected, tGATT_DISCONN_REASON reason,
+ tGATT_TRANSPORT transport)
{
tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (bda);
UINT16 cl_op_uuid;
+
UNUSED(gatt_if);
+ UNUSED(transport);
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],
@@ -636,9 +553,6 @@
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
{
@@ -659,6 +573,10 @@
{
GAP_BleReadPeerDevName (bda, (tGAP_BLE_DEV_NAME_CBACK *)p_clcb->p_cback);
}
+ else if (cl_op_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
+ {
+ GAP_BleReadPeerPrefConnParams(bda);
+ }
}
/* current link disconnect */
else
@@ -695,7 +613,7 @@
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)
+ if (op != GATTC_OPTYPE_READ)
return;
if (status != GATT_SUCCESS)
@@ -731,7 +649,6 @@
break;
case GATT_UUID_GAP_ICON:
break;
-
}
}
@@ -806,18 +723,20 @@
return(FALSE);
/* hold the link here */
- GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
-
- if (p_clcb->connected)
+ if (GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
{
- return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
+
+ if (p_clcb->connected)
+ {
+ return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
+ }
+ /* Mark currently active operation */
+ p_clcb->cl_op_uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
+
+ return(TRUE);
}
- /* Mark currently active operation */
- p_clcb->cl_op_uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
-
- return(TRUE);
-
-
+ else
+ return FALSE;
}
/*******************************************************************************
@@ -839,10 +758,10 @@
if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL)
{
if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
- {
- GAP_TRACE_ERROR0("GAP_BleReadPeerDevName max connection reached");
+ {
+ GAP_TRACE_ERROR0("GAP_BleReadPeerDevName max connection reached");
return FALSE;
- }
+ }
p_clcb->connected = FALSE;
}
@@ -855,21 +774,26 @@
return(FALSE);
/* hold the link here */
- GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
- if (p_clcb->connected)
+ if (GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
{
- return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_DEVICE_NAME, (void *)p_cback);
+ 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);
}
-
- p_clcb->p_cback = (void *)p_cback;
- /* Mark currently active operation */
- p_clcb->cl_op_uuid = GATT_UUID_GAP_DEVICE_NAME;
-
-
- return(TRUE);
+ else
+ return FALSE;
}
+
/*******************************************************************************
**
** Function GAP_BleCancelReadPeerDevName
@@ -907,73 +831,6 @@
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(¶m, 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, ¶m) != 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
index 44bb5ec..5e26ce2 100644
--- a/stack/gap/gap_conn.c
+++ b/stack/gap/gap_conn.c
@@ -799,10 +799,11 @@
** Returns void
**
*******************************************************************************/
-static void gap_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+static void gap_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data;
UNUSED(bd_addr);
+ UNUSED (transport);
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);
diff --git a/stack/gap/gap_utils.c b/stack/gap/gap_utils.c
index 866ad7a..e852d20 100644
--- a/stack/gap/gap_utils.c
+++ b/stack/gap/gap_utils.c
@@ -183,7 +183,7 @@
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)
+ (tBTM_CMPL_CB *) gap_find_addr_name_cb, BT_TRANSPORT_BR_EDR)) == 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);
@@ -246,7 +246,7 @@
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)
+ (tBTM_CMPL_CB *) gap_find_addr_name_cb, BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
return; /* Wait for the response in gap_find_addr_name_cb() */
else
p_result->status = gap_convert_btm_status (p->status);
diff --git a/stack/gatt/att_protocol.c b/stack/gatt/att_protocol.c
index 3348599..51ea284 100644
--- a/stack/gatt/att_protocol.c
+++ b/stack/gatt/att_protocol.c
@@ -162,7 +162,7 @@
** Returns pointer to the command buffer.
**
*******************************************************************************/
-BT_HDR *attp_build_read_handles_cmd (UINT16 payload_size, tGATT_FIND_TYPE_VALUE *p_value_type)
+BT_HDR *attp_build_read_by_type_value_cmd (UINT16 payload_size, tGATT_FIND_TYPE_VALUE *p_value_type)
{
BT_HDR *p_buf = NULL;
UINT8 *p;
@@ -606,7 +606,7 @@
break;
case GATT_REQ_FIND_TYPE_VALUE:
- p_cmd = attp_build_read_handles_cmd(p_tcb->payload_size, &p_msg->find_type_value);
+ p_cmd = attp_build_read_by_type_value_cmd(p_tcb->payload_size, &p_msg->find_type_value);
break;
case GATT_REQ_READ_MULTI:
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 54ea0f0..0321fe8 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -238,7 +238,7 @@
}
}
- if (!gatts_init_service_db(&p_list->svc_db, *p_svc_uuid, is_pri, s_hdl , num_handles))
+ if (!gatts_init_service_db(&p_list->svc_db, p_svc_uuid, is_pri, s_hdl , num_handles))
{
GATT_TRACE_ERROR0 ("GATTS_ReserveHandles: service DB initialization failed");
if (p_list)
@@ -366,7 +366,8 @@
return 0;
}
if (p_descr_uuid == NULL ||
- (p_descr_uuid->len != LEN_UUID_128 && p_descr_uuid->len != LEN_UUID_16))
+ (p_descr_uuid->len != LEN_UUID_128 && p_descr_uuid->len != LEN_UUID_16
+ && p_descr_uuid->len != LEN_UUID_32))
{
GATT_TRACE_DEBUG0("Illegal parameter");
return 0;
@@ -689,8 +690,13 @@
memcpy (notif.value, p_val, val_len);
notif.auth_req = GATT_AUTH_REQ_NONE;;
- p_buf = attp_build_sr_msg (p_tcb, GATT_HANDLE_VALUE_NOTIF, (tGATT_SR_MSG *)¬if);
- cmd_sent = attp_send_sr_msg (p_tcb, p_buf);
+ if ((p_buf = attp_build_sr_msg (p_tcb, GATT_HANDLE_VALUE_NOTIF, (tGATT_SR_MSG *)¬if))
+ != NULL)
+ {
+ cmd_sent = attp_send_sr_msg (p_tcb, p_buf);
+ }
+ else
+ cmd_sent = GATT_NO_RESOURCES;
}
return cmd_sent;
}
@@ -1147,12 +1153,12 @@
** Returns void
**
*******************************************************************************/
-void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout)
+void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout, tBT_TRANSPORT transport)
{
tGATT_TCB *p_tcb;
BOOLEAN status = FALSE;
- if ((p_tcb = gatt_find_tcb_by_addr (bd_addr)) != NULL)
+ if ((p_tcb = gatt_find_tcb_by_addr (bd_addr, transport)) != NULL)
{
if (p_tcb->att_lcid == L2CAP_ATT_CID)
{
@@ -1275,7 +1281,7 @@
if (!gatt_num_apps_hold_link(p_tcb))
{
/* this will disconnect the link or cancel the pending connect request at lower layer*/
- gatt_disconnect(p_tcb->peer_bda);
+ gatt_disconnect(p_tcb);
}
}
@@ -1323,19 +1329,20 @@
BD_ADDR bda;
UINT8 start_idx, found_idx;
UINT16 conn_id;
+ tGATT_TRANSPORT transport ;
GATT_TRACE_API1 ("GATT_StartIf gatt_if=%d", gatt_if);
if ((p_reg = gatt_get_regcb(gatt_if)) != NULL)
{
p_reg = &gatt_cb.cl_rcb[gatt_if - 1];
start_idx = 0;
- while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
+ while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport))
{
- p_tcb = gatt_find_tcb_by_addr(bda);
+ p_tcb = gatt_find_tcb_by_addr(bda, transport);
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);
+ (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0, transport);
}
start_idx = ++found_idx;
}
@@ -1357,9 +1364,10 @@
** Returns TRUE if connection started; FALSE if connection start failure.
**
*******************************************************************************/
-BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct){
+BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct, tBT_TRANSPORT transport)
+{
tGATT_REG *p_reg;
- BOOLEAN status;
+ BOOLEAN status = FALSE;
GATT_TRACE_API1 ("GATT_Connect gatt_if=%d", gatt_if);
@@ -1371,9 +1379,16 @@
}
if (is_direct)
- status = gatt_act_connect (p_reg, bd_addr);
+ status = gatt_act_connect (p_reg, bd_addr, transport);
else
+ {
+ if (transport == BT_TRANSPORT_LE)
status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr, TRUE);
+ else
+ {
+ GATT_TRACE_ERROR0("Unsupported transport for background connection");
+ }
+ }
return status;
@@ -1414,7 +1429,8 @@
{
GATT_TRACE_DEBUG0("GATT_CancelConnect - unconditional");
start_idx = 0;
- p_tcb = gatt_find_tcb_by_addr(bd_addr);
+ /* only LE connection can be cancelled */
+ p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
if (p_tcb && gatt_num_apps_hold_link(p_tcb))
{
while (status && gatt_find_app_hold_link(p_tcb, start_idx, &found_idx, &temp_gatt_if))
@@ -1486,7 +1502,7 @@
gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
if (!gatt_num_apps_hold_link(p_tcb))
{
- gatt_disconnect(p_tcb->peer_bda);
+ gatt_disconnect(p_tcb);
}
ret = GATT_SUCCESS;
}
@@ -1508,7 +1524,8 @@
** Returns TRUE the ligical link information is found for conn_id
**
*******************************************************************************/
-BOOLEAN GATT_GetConnectionInfor(UINT16 conn_id, tGATT_IF *p_gatt_if, BD_ADDR bd_addr)
+BOOLEAN GATT_GetConnectionInfor(UINT16 conn_id, tGATT_IF *p_gatt_if, BD_ADDR bd_addr,
+ tBT_TRANSPORT *p_transport)
{
tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
@@ -1523,6 +1540,7 @@
{
memcpy(bd_addr, p_tcb->peer_bda, BD_ADDR_LEN);
*p_gatt_if = gatt_if;
+ *p_transport = p_tcb->transport;
status = TRUE;
}
return status;
@@ -1539,14 +1557,16 @@
** Parameters gatt_if: applicaiton interface (input)
** bd_addr: peer device address. (input)
** p_conn_id: connection id (output)
+** transport: transport option
**
** Returns TRUE the logical link is connected
**
*******************************************************************************/
-BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id)
+BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id,
+ tBT_TRANSPORT transport)
{
tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
- tGATT_TCB *p_tcb= gatt_find_tcb_by_addr(bd_addr);
+ tGATT_TCB *p_tcb= gatt_find_tcb_by_addr(bd_addr, transport);
BOOLEAN status=FALSE;
if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) )
@@ -1598,10 +1618,7 @@
p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE;
}
- gatt_update_listen_mode();
-
- return status;
-
+ return gatt_update_listen_mode();
}
#endif
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index 1ee4ae3..60beaa7 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -41,7 +41,8 @@
#endif
static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
-static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport);
static tGATT_CBACK gatt_profile_cback =
{
@@ -87,14 +88,15 @@
** Returns Pointer to the found link conenction control block.
**
*******************************************************************************/
-tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda)
+static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda, tBT_TRANSPORT transport)
{
UINT8 i_clcb;
tGATT_PROFILE_CLCB *p_clcb = NULL;
for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
{
- if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
+ if (p_clcb->in_use && p_clcb->transport == transport &&
+ p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
{
return p_clcb;
}
@@ -112,7 +114,7 @@
** Returns NULL if not found. Otherwise pointer to the connection link block.
**
*******************************************************************************/
-tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
+tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda, tBT_TRANSPORT tranport)
{
UINT8 i_clcb = 0;
tGATT_PROFILE_CLCB *p_clcb = NULL;
@@ -124,6 +126,7 @@
p_clcb->in_use = TRUE;
p_clcb->conn_id = conn_id;
p_clcb->connected = TRUE;
+ p_clcb->transport = tranport;
memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
break;
}
@@ -215,7 +218,8 @@
**
*******************************************************************************/
static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
- BOOLEAN connected, tGATT_DISCONN_REASON reason)
+ BOOLEAN connected, tGATT_DISCONN_REASON reason,
+ tBT_TRANSPORT transport)
{
UNUSED(gatt_if);
@@ -225,7 +229,7 @@
if (connected)
{
- if (gatt_profile_clcb_alloc(conn_id, bda) == NULL)
+ if (gatt_profile_clcb_alloc(conn_id, bda, transport) == NULL)
{
GATT_TRACE_ERROR0 ("gatt_profile_connect_cback: no_resource");
return;
diff --git a/stack/gatt/gatt_auth.c b/stack/gatt/gatt_auth.c
index 7dc99e1..b093725 100644
--- a/stack/gatt/gatt_auth.c
+++ b/stack/gatt/gatt_auth.c
@@ -114,9 +114,8 @@
}
else
{
- /* if this is a bad signature, assume from attacker, ignore it */
- GATT_TRACE_ERROR0("Signature Verification Failed");
- gatt_disconnect(p_tcb->peer_bda);
+ /* if this is a bad signature, assume from attacker, ignore it */
+ GATT_TRACE_ERROR0("Signature Verification Failed, data ignored");
}
return;
@@ -157,7 +156,7 @@
** Returns
**
*******************************************************************************/
-void gatt_enc_cmpl_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+void gatt_enc_cmpl_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, tBTM_STATUS result)
{
tGATT_TCB *p_tcb;
UINT8 sec_flag;
@@ -167,7 +166,7 @@
UNUSED(p_ref_data);
GATT_TRACE_DEBUG0("gatt_enc_cmpl_cback");
- if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
+ if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, transport)) != NULL)
{
if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
return;
@@ -178,8 +177,9 @@
{
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)
+ BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, transport);
+
+ if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
{
status = TRUE;
}
@@ -232,7 +232,7 @@
UINT16 count;
UINT8 i = 0;
- if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
+ if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE)) != NULL)
{
for (i = 0; i < GATT_MAX_APPS; i++)
{
@@ -316,9 +316,7 @@
UINT8 sec_flag;
tGATT_TCB *p_tcb = p_clcb->p_tcb;
tGATT_AUTH_REQ auth_req = p_clcb->auth_req;
-
BOOLEAN is_link_encrypted= FALSE;
- BOOLEAN is_le_link=FALSE;
BOOLEAN is_link_key_known=FALSE;
BOOLEAN is_key_mitm=FALSE;
UINT8 key_type;
@@ -327,8 +325,8 @@
if (auth_req == GATT_AUTH_REQ_NONE )
return act;
- is_le_link = BTM_UseLeLink(p_tcb->peer_bda);
- BTM_GetSecurityFlags(p_tcb->peer_bda, &sec_flag);
+ BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag, p_clcb->p_tcb->transport);
+
btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act);
/* if a encryption is pending, need to wait */
@@ -336,24 +334,15 @@
auth_req != GATT_AUTH_REQ_NONE)
return GATT_SEC_ENC_PENDING;
- if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
+ if (sec_flag & (BTM_SEC_FLAG_ENCRYPTED| BTM_SEC_FLAG_LKEY_KNOWN))
{
- is_link_encrypted = TRUE;
+ 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;
- }
-
- }
- else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
- {
- is_link_key_known = TRUE;
- if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
- {
- is_key_mitm = TRUE;
- }
}
/* first check link key upgrade required or not */
@@ -377,7 +366,7 @@
/* now check link needs to be encrypted or not if the link key upgrade is not required */
if (act == GATT_SEC_OK)
{
- if (is_le_link &&
+ if (p_tcb->transport == BT_TRANSPORT_LE &&
(p_clcb->operation == GATTC_OPTYPE_WRITE) &&
(p_clcb->op_subtype == GATT_WRITE_NO_RSP))
{
@@ -430,7 +419,7 @@
tGATT_STATUS encrypt_status = GATT_NOT_ENCRYPTED;
UINT8 sec_flag=0;
- BTM_GetSecurityFlags(p_tcb->peer_bda, &sec_flag);
+ BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag, p_tcb->transport);
if ((sec_flag & BTM_SEC_FLAG_ENCRYPTED) && (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN))
{
@@ -510,7 +499,7 @@
{
GATT_TRACE_DEBUG0("gatt_security_check_start: Encrypt now or key upgreade first");
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);
+ btm_status = BTM_SetEncryption(p_tcb->peer_bda, p_tcb->transport , 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);
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index e8c41fc..930cd35 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -27,6 +27,7 @@
#if BLE_INCLUDED == TRUE
#include <string.h>
+#include "bt_utils.h"
#include "gki.h"
#include "gatt_int.h"
@@ -102,6 +103,13 @@
cl_req.find_type_value.s_handle = p_clcb->s_handle;
cl_req.find_type_value.e_handle = p_clcb->e_handle;
cl_req.find_type_value.value_len = p_clcb->uuid.len;
+ /* if service type is 32 bits UUID, convert it now */
+ if (p_clcb->uuid.len == LEN_UUID_32)
+ {
+ cl_req.find_type_value.value_len = LEN_UUID_128;
+ gatt_convert_uuid32_to_uuid128(cl_req.find_type_value.value, p_clcb->uuid.uu.uuid32);
+ }
+ else
memcpy (cl_req.find_type_value.value, &p_clcb->uuid.uu, p_clcb->uuid.len);
}
@@ -402,11 +410,13 @@
** Returns void
**
*******************************************************************************/
-static void gatt_process_find_type_value_rsp (tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
+void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
{
tGATT_DISC_RES result;
UINT8 *p = p_data;
+ UNUSED(p_tcb);
+
GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp ");
/* unexpected response */
if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
@@ -445,11 +455,15 @@
** Returns void
**
*******************************************************************************/
-static void gatt_process_read_info_rsp(tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
+void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
+ UINT16 len, UINT8 *p_data)
{
tGATT_DISC_RES result;
UINT8 *p = p_data, uuid_len = 0, type;
+ UNUSED(p_tcb);
+ UNUSED(op_code);
+
if (len < GATT_INFO_RSP_MIN_LEN)
{
GATT_TRACE_ERROR0("invalid Info Response PDU received, discard.");
@@ -500,10 +514,14 @@
** Returns void.
**
*******************************************************************************/
-static void gatt_proc_disc_error_rsp(tGATT_CLCB *p_clcb, UINT8 opcode, UINT8 reason)
+void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode,
+ UINT16 handle, UINT8 reason)
{
tGATT_STATUS status = (tGATT_STATUS) reason;
+ UNUSED(p_tcb);
+ UNUSED(handle);
+
GATT_TRACE_DEBUG2("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode);
switch (opcode)
@@ -536,12 +554,16 @@
** Returns void
**
*******************************************************************************/
-static void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 *p_data)
+void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
+ UINT16 len, UINT8 *p_data)
{
UINT8 opcode, reason, * p= p_data;
UINT16 handle;
tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
+ UNUSED(op_code);
+ UNUSED(len);
+
GATT_TRACE_DEBUG0("gatt_process_error_rsp ");
STREAM_TO_UINT8(opcode, p);
STREAM_TO_UINT16(handle, p);
@@ -549,7 +571,7 @@
if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
{
- gatt_proc_disc_error_rsp(p_clcb, opcode, reason);
+ gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason);
}
else
{
@@ -921,12 +943,14 @@
** Returns void
**
*******************************************************************************/
-static void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb,
- UINT16 len, UINT8 *p_data)
+void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
+ UINT16 len, UINT8 *p_data)
{
UINT16 offset = p_clcb->counter;
UINT8 * p= p_data;
+ UNUSED(op_code);
+
if (p_clcb->operation == GATTC_OPTYPE_READ)
{
if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
@@ -1169,7 +1193,7 @@
switch (op_code)
{
case GATT_RSP_ERROR:
- gatt_process_error_rsp(p_tcb, p_clcb, p_data);
+ gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
break;
case GATT_RSP_MTU: /* 2 bytes mtu */
@@ -1177,7 +1201,7 @@
break;
case GATT_RSP_FIND_INFO:
- gatt_process_read_info_rsp(p_clcb, len, p_data);
+ gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
break;
case GATT_RSP_READ_BY_TYPE:
@@ -1188,11 +1212,11 @@
case GATT_RSP_READ:
case GATT_RSP_READ_BLOB:
case GATT_RSP_READ_MULTI:
- gatt_process_read_rsp(p_tcb, p_clcb, len, p_data);
+ gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
break;
case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
- gatt_process_find_type_value_rsp(p_clcb, len, p_data);
+ gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
break;
case GATT_RSP_WRITE:
diff --git a/stack/gatt/gatt_db.c b/stack/gatt/gatt_db.c
index 268bc7d..a1b0a8a 100644
--- a/stack/gatt/gatt_db.c
+++ b/stack/gatt/gatt_db.c
@@ -27,6 +27,7 @@
#if BLE_INCLUDED == TRUE
#include "bt_trace.h"
+#include "bt_utils.h"
#include <stdio.h>
#include <string.h>
@@ -38,11 +39,11 @@
** L O C A L F U N C T I O N P R O T O T Y P E S *
*********************************************************************************/
static BOOLEAN allocate_svc_db_buf(tGATT_SVC_DB *p_db);
-static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, UINT16 uuid16, UINT8 *p_uuid128, tGATT_PERM perm);
+static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PERM perm);
static BOOLEAN deallocate_attr_in_db(tGATT_SVC_DB *p_db, void *p_attr);
static BOOLEAN copy_extra_byte_in_db(tGATT_SVC_DB *p_db, void **p_dst, UINT16 len);
-static void gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID service, BOOLEAN is_pri);
+static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri);
static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
UINT16 handle, UINT16 offset, UINT32 trans_id);
@@ -58,7 +59,7 @@
** Returns Status of te operation.
**
*******************************************************************************/
-BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID service, BOOLEAN is_pri,
+BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri,
UINT16 s_hdl, UINT16 num_handle)
{
if (!allocate_svc_db_buf(p_db))
@@ -74,9 +75,7 @@
p_db->next_handle = s_hdl;
p_db->end_handle = s_hdl + num_handle;
- gatts_db_add_service_declaration(p_db, service, is_pri);
-
- return TRUE;
+ return gatts_db_add_service_declaration(p_db, p_service, is_pri);
}
/*******************************************************************************
@@ -115,6 +114,7 @@
**
*******************************************************************************/
static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr,
+ UINT16 offset,
BOOLEAN read_long,
tGATT_SEC_FLAG sec_flag,
UINT8 key_size)
@@ -122,6 +122,7 @@
UINT16 min_key_size;
tGATT_PERM perm = p_attr->permission;
+ UNUSED(offset);
min_key_size = (((perm & GATT_ENCRYPT_KEY_SIZE_MASK) >> 12));
if (min_key_size != 0 )
{
@@ -223,14 +224,14 @@
offset,
read_long);
- status = gatts_check_attr_readability((tGATT_ATTR16 *)p_attr, read_long, sec_flag, key_size);
-
- if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16)
- uuid16 = p_attr16->uuid;
+ status = gatts_check_attr_readability((tGATT_ATTR16 *)p_attr, offset, read_long, sec_flag, key_size);
if (status != GATT_SUCCESS)
return status;
+ if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16)
+ uuid16 = p_attr16->uuid;
+
status = GATT_NO_RESOURCES;
if (read_long &&
@@ -261,6 +262,12 @@
{
UINT16_TO_STREAM(p, ((tGATT_ATTR16 *)(p_attr16->p_next))->uuid);
}
+ /* convert a 32bits UUID to 128 bits */
+ else if (((tGATT_ATTR32 *)(p_attr16->p_next))->uuid_type == GATT_ATTR_UUID_TYPE_32)
+ {
+ gatt_convert_uuid32_to_uuid128 (p, ((tGATT_ATTR32 *)(p_attr16->p_next))->uuid);
+ p += LEN_UUID_128;
+ }
else
{
ARRAY_TO_STREAM (p, ((tGATT_ATTR128 *)(p_attr16->p_next))->uuid, LEN_UUID_128);
@@ -271,13 +278,17 @@
}
else if (uuid16 == GATT_UUID_INCLUDE_SERVICE)
{
- len = (p_attr16->p_value->incl_handle.service_type.len == 2) ? 6 : 4;
+ if (p_attr16->p_value->incl_handle.service_type.len == LEN_UUID_16)
+ len = 6;
+ else
+ len = 4;
+
if (mtu >= len)
{
UINT16_TO_STREAM(p, p_attr16->p_value->incl_handle.s_handle);
UINT16_TO_STREAM(p, p_attr16->p_value->incl_handle.e_handle);
- if (p_attr16->p_value->incl_handle.service_type.len == 2)
+ if (p_attr16->p_value->incl_handle.service_type.len == LEN_UUID_16)
{
UINT16_TO_STREAM(p, p_attr16->p_value->incl_handle.service_type.uu.uuid16);
}
@@ -345,6 +356,11 @@
attr_uuid.len = LEN_UUID_16;
attr_uuid.uu.uuid16 = p_attr->uuid;
}
+ else if (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_32)
+ {
+ attr_uuid.len = LEN_UUID_32;
+ attr_uuid.uu.uuid32 = ((tGATT_ATTR32 *)p_attr)->uuid;
+ }
else
{
attr_uuid.len = LEN_UUID_128;
@@ -436,6 +452,7 @@
tBT_UUID service)
{
tGATT_ATTR16 *p_attr;
+ tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_INCLUDE_SERVICE}};
GATT_TRACE_DEBUG3("gatts_add_included_service: s_hdl = 0x%04x e_hdl = 0x%04x uuid = 0x%04x",
s_handle, e_handle, service.uu.uuid16);
@@ -446,7 +463,7 @@
return 0;
}
- if ((p_attr = (tGATT_ATTR16 *) allocate_attr_in_db(p_db, GATT_UUID_INCLUDE_SERVICE, NULL, GATT_PERM_READ)) != NULL)
+ if ((p_attr = (tGATT_ATTR16 *) allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL)
{
if (copy_extra_byte_in_db(p_db, (void **)&p_attr->p_value, sizeof(tGATT_INCL_SRVC)))
{
@@ -485,11 +502,11 @@
tBT_UUID * p_char_uuid)
{
tGATT_ATTR16 *p_char_decl, *p_char_val;
- UINT16 uuid16 = (p_char_uuid->len == LEN_UUID_16) ? p_char_uuid->uu.uuid16 : 0;
+ tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
GATT_TRACE_DEBUG2("gatts_add_characteristic perm=0x%0x property=0x%0x", perm, property);
- if ((p_char_decl = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, GATT_UUID_CHAR_DECLARE, NULL, GATT_PERM_READ)) != NULL)
+ if ((p_char_decl = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL)
{
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_decl->p_value, sizeof(tGATT_CHAR_DECL)))
{
@@ -497,7 +514,7 @@
return 0;
}
- p_char_val = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, uuid16, p_char_uuid->uu.uuid128, perm);
+ p_char_val = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, p_char_uuid, perm);
if (p_char_val == NULL)
{
@@ -578,14 +595,12 @@
tBT_UUID * p_descr_uuid)
{
tGATT_ATTR16 *p_char_dscptr;
- UINT16 uuid16 = (p_descr_uuid->len == LEN_UUID_16)? p_descr_uuid->uu.uuid16 : 0;
GATT_TRACE_DEBUG1("gatts_add_char_descr uuid=0x%04x", p_descr_uuid->uu.uuid16);
/* Add characteristic descriptors */
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db,
- uuid16,
- p_descr_uuid->uu.uuid128,
+ p_descr_uuid,
perm))
== NULL)
{
@@ -695,7 +710,7 @@
{
if (p_attr->handle == handle)
{
- status = gatts_check_attr_readability (p_attr,
+ status = gatts_check_attr_readability (p_attr, 0,
is_long,
sec_flag, key_size);
break;
@@ -812,7 +827,8 @@
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))
+ else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)
+ && (perm & GATT_WRITE_ALLOWED) == 0)
{
status = GATT_INSUF_AUTHENTICATION;
GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required");
@@ -842,7 +858,8 @@
break;
}
}
- else if (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128)
+ else if (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128 ||
+ p_attr->uuid_type == GATT_ATTR_UUID_TYPE_32)
{
status = GATT_SUCCESS;
}
@@ -897,25 +914,32 @@
**
**
** Parameter p_db : database pointer.
+** p_uuid: pointer to attribute UUID
** service : type of attribute to be added.
**
** Returns pointer to the newly allocated attribute.
**
*******************************************************************************/
-static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, UINT16 uuid16, UINT8 *uuid128, tGATT_PERM perm)
+static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PERM perm)
{
tGATT_ATTR16 *p_attr16 = NULL, *p_last;
+ tGATT_ATTR32 *p_attr32 = NULL;
tGATT_ATTR128 *p_attr128 = NULL;
- UINT16 len = (uuid16 == 0) ? sizeof(tGATT_ATTR128): sizeof(tGATT_ATTR16);
+ UINT16 len = sizeof(tGATT_ATTR128);
- GATT_TRACE_DEBUG1("allocate attr %d bytes ",len);
-
- if (uuid16 == GATT_ILLEGAL_UUID && uuid128 == NULL)
+ if (p_uuid == NULL)
{
GATT_TRACE_ERROR0("illegal UUID");
return NULL;
}
+ if (p_uuid->len == LEN_UUID_16)
+ len = sizeof(tGATT_ATTR16);
+ else if (p_uuid->len == LEN_UUID_32)
+ len = sizeof(tGATT_ATTR32);
+
+ GATT_TRACE_DEBUG1("allocate attr %d bytes ",len);
+
if (p_db->end_handle <= p_db->next_handle)
{
GATT_TRACE_DEBUG2("handle space full. handle_max = %d next_handle = %d",
@@ -931,21 +955,25 @@
return NULL;
}
}
-
+ memset(p_db->p_free_mem, 0, len);
p_attr16 = (tGATT_ATTR16 *) p_db->p_free_mem;
- p_attr128 = (tGATT_ATTR128 *) p_db->p_free_mem;
- memset(p_attr16, 0, len);
-
- if (uuid16 != GATT_ILLEGAL_UUID)
+ if (p_uuid->len == LEN_UUID_16 && p_uuid->uu.uuid16 != GATT_ILLEGAL_UUID)
{
p_attr16->uuid_type = GATT_ATTR_UUID_TYPE_16;
- p_attr16->uuid = uuid16;
+ p_attr16->uuid = p_uuid->uu.uuid16;
}
- else
+ else if (p_uuid->len == LEN_UUID_32)
{
+ p_attr32 = (tGATT_ATTR32 *) p_db->p_free_mem;
+ p_attr32->uuid_type = GATT_ATTR_UUID_TYPE_32;
+ p_attr32->uuid = p_uuid->uu.uuid32;
+ }
+ else if (p_uuid->len == LEN_UUID_128)
+ {
+ p_attr128 = (tGATT_ATTR128 *) p_db->p_free_mem;
p_attr128->uuid_type = GATT_ATTR_UUID_TYPE_128;
- memcpy(p_attr128->uuid, uuid128, LEN_UUID_128);
+ memcpy(p_attr128->uuid, p_uuid->uu.uuid128, LEN_UUID_128);
}
p_db->p_free_mem += len;
@@ -970,9 +998,14 @@
if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16)
{
- GATT_TRACE_DEBUG3("=====> handle = [0x%04x] uuid = [0x%04x] perm=0x%02x ",
+ GATT_TRACE_DEBUG3("=====> handle = [0x%04x] uuid16 = [0x%04x] perm=0x%02x ",
p_attr16->handle, p_attr16->uuid, p_attr16->permission);
}
+ else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_32)
+ {
+ GATT_TRACE_DEBUG3("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x ",
+ p_attr32->handle, p_attr32->uuid, p_attr32->permission);
+ }
else
{
GATT_TRACE_DEBUG4("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x ",
@@ -1151,21 +1184,44 @@
** Returns void
**
*******************************************************************************/
-static void gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID service, BOOLEAN is_pri)
+static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri)
{
tGATT_ATTR16 *p_attr;
- UINT16 service_type = is_pri ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
+ tBT_UUID uuid = {LEN_UUID_16, {0}};
+ BOOLEAN rt = FALSE;
GATT_TRACE_DEBUG0( "add_service_declaration");
+ if (is_pri)
+ uuid.uu.uuid16 = GATT_UUID_PRI_SERVICE;
+ else
+ uuid.uu.uuid16 = GATT_UUID_SEC_SERVICE;
+
/* add service declration record */
- if ((p_attr = (tGATT_ATTR16 *)(allocate_attr_in_db(p_db, service_type, NULL, GATT_PERM_READ))) != NULL)
+ if ((p_attr = (tGATT_ATTR16 *)(allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ))) != NULL)
{
if (copy_extra_byte_in_db (p_db, (void **)&p_attr->p_value, sizeof(tBT_UUID)))
{
- memcpy (&p_attr->p_value->uuid, &service, sizeof(tBT_UUID));
+ if (p_service->len == LEN_UUID_16)
+ {
+ p_attr->p_value->uuid.len = LEN_UUID_16;
+ p_attr->p_value->uuid.uu.uuid16 = p_service->uu.uuid16;
+ }
+ else if (p_service->len == LEN_UUID_32)
+ {
+ p_attr->p_value->uuid.len = LEN_UUID_128;
+ gatt_convert_uuid32_to_uuid128(p_attr->p_value->uuid.uu.uuid128, p_service->uu.uuid32);
+ }
+ else
+ {
+ p_attr->p_value->uuid.len = LEN_UUID_128;
+ memcpy(p_attr->p_value->uuid.uu.uuid128, p_service->uu.uuid128, LEN_UUID_128);
+ }
+ rt = TRUE;
}
+
}
+ return rt;
}
#endif /* BLE_INCLUDED */
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 1f81d63..b6bb95c 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -21,8 +21,6 @@
#include "bt_target.h"
-#if BLE_INCLUDED == TRUE
-
#include "bt_trace.h"
#include "gatt_api.h"
@@ -169,6 +167,7 @@
*/
#define GATT_ATTR_UUID_TYPE_16 0
#define GATT_ATTR_UUID_TYPE_128 1
+#define GATT_ATTR_UUID_TYPE_32 2
typedef UINT8 tGATT_ATTR_UUID_TYPE;
/* 16 bits UUID Attribute in server database
@@ -184,6 +183,20 @@
UINT16 uuid;
} tGATT_ATTR16;
+/* 32 bits UUID Attribute in server database
+*/
+typedef struct
+{
+ void *p_next; /* pointer to the next attribute,
+ either tGATT_ATTR16, tGATT_ATTR32 or tGATT_ATTR128 */
+ tGATT_ATTR_VALUE *p_value;
+ tGATT_ATTR_UUID_TYPE uuid_type;
+ tGATT_PERM permission;
+ UINT16 handle;
+ UINT32 uuid;
+} tGATT_ATTR32;
+
+
/* 128 bits UUID Attribute in server database
*/
typedef struct
@@ -340,6 +353,7 @@
BUFFER_Q pending_enc_clcb; /* pending encryption channel q */
tGATT_SEC_ACTION sec_act;
BD_ADDR peer_bda;
+ tBT_TRANSPORT transport;
UINT32 trans_id;
UINT16 att_lcid; /* L2CAP channel ID for ATT */
@@ -400,6 +414,7 @@
BOOLEAN in_use;
TIMER_LIST_ENT rsp_timer_ent; /* peer response timer */
UINT8 retry_count;
+
} tGATT_CLCB;
typedef struct
@@ -454,6 +469,7 @@
BOOLEAN in_use;
BOOLEAN connected;
BD_ADDR bda;
+ tBT_TRANSPORT transport;
}tGATT_PROFILE_CLCB;
typedef struct
@@ -524,9 +540,9 @@
extern void gatt_init (void);
/* from gatt_main.c */
-extern BOOLEAN gatt_disconnect (BD_ADDR rem_bda);
-extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr);
-extern BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb);
+extern BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb);
+extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport);
+extern BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb, tBT_TRANSPORT transport);
extern void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf);
extern void gatt_update_app_use_link_flag ( tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link);
@@ -541,9 +557,8 @@
/* from gatt_attr.c */
extern UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR bda);
-extern tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda);
extern BOOLEAN gatt_profile_clcb_dealloc (UINT16 conn_id);
-extern tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda);
+extern tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda, tBT_TRANSPORT transport);
/* Functions provided by att_protocol.c */
@@ -558,7 +573,8 @@
extern BOOLEAN gatt_parse_uuid_from_cmd(tBT_UUID *p_uuid, UINT16 len, UINT8 **p_data);
extern UINT8 gatt_build_uuid_to_stream(UINT8 **p_dst, tBT_UUID uuid);
extern BOOLEAN gatt_uuid_compare(tBT_UUID src, tBT_UUID tar);
-extern void gatt_sr_get_sec_info(BD_ADDR rem_bda, BOOLEAN le_conn, UINT8 *p_sec_flag, UINT8 *p_key_size);
+extern void gatt_convert_uuid32_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT32 uuid_32);
+extern void gatt_sr_get_sec_info(BD_ADDR rem_bda, tBT_TRANSPORT transport, UINT8 *p_sec_flag, UINT8 *p_key_size);
extern void gatt_start_rsp_timer(UINT16 clcb_idx);
extern void gatt_start_conf_timer(tGATT_TCB *p_tcb);
extern void gatt_rsp_timeout(TIMER_LIST_ENT *p_tle);
@@ -573,13 +589,13 @@
extern BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb);
extern tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda);
-extern BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx);
+extern BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx, tBT_TRANSPORT *p_transport);
extern void gatt_set_srv_chg(void);
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);
+extern BOOLEAN 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);
@@ -635,16 +651,16 @@
extern UINT8 gatt_num_apps_hold_link(tGATT_TCB *p_tcb);
extern UINT8 gatt_num_clcb_by_bd_addr(BD_ADDR bda);
extern tGATT_TCB * gatt_find_tcb_by_cid(UINT16 lcid);
-extern tGATT_TCB * gatt_allocate_tcb_by_bdaddr(BD_ADDR bda);
+extern tGATT_TCB * gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport);
extern tGATT_TCB * gatt_get_tcb_by_idx(UINT8 tcb_idx);
-extern tGATT_TCB * gatt_find_tcb_by_addr(BD_ADDR bda);
-
+extern tGATT_TCB * gatt_find_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport);
+extern BOOLEAN gatt_send_ble_burst_data (BD_ADDR remote_bda, BT_HDR *p_buf);
/* GATT client functions */
extern void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb);
extern UINT8 gatt_send_write_msg(tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code, UINT16 handle,
UINT16 len, UINT16 offset, UINT8 *p_data);
-extern void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason);
+extern void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport);
extern void gatt_end_operation(tGATT_CLCB *p_clcb, tGATT_STATUS status, void *p_data);
extern void gatt_act_discovery(tGATT_CLCB *p_clcb);
@@ -667,7 +683,7 @@
extern void gatt_set_sec_act(tGATT_TCB *p_tcb, tGATT_SEC_ACTION sec_act);
/* gatt_db.c */
-extern BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID service, BOOLEAN is_pri, UINT16 s_hdl, UINT16 num_handle);
+extern BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri, UINT16 s_hdl, UINT16 num_handle);
extern UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e_handle, tBT_UUID service);
extern UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, tGATT_CHAR_PROP property, tBT_UUID *p_char_uuid);
extern UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm, tBT_UUID *p_dscp_uuid);
@@ -684,4 +700,4 @@
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 d5e017b..59c6759 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -44,7 +44,7 @@
/********************************************************************************/
/* 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 gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason);
+static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason, tBT_TRANSPORT transport);
static void gatt_le_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
static void gatt_l2cif_connect_ind_cback (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
@@ -143,15 +143,14 @@
** Returns TRUE if connection is started, otherwise return FALSE.
**
*******************************************************************************/
-BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb)
+BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb, tBT_TRANSPORT transport)
{
BOOLEAN gatt_ret = FALSE;
if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN)
gatt_set_ch_state(p_tcb, GATT_CH_CONN);
- /* select the physical link for GATT connection */
- if (BTM_UseLeLink(rem_bda))
+ if (transport == BT_TRANSPORT_LE)
{
p_tcb->att_lcid = L2CAP_ATT_CID;
gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda);
@@ -171,15 +170,14 @@
**
** Description This function is called to disconnect to an ATT device.
**
-** Parameter rem_bda: remote device address to disconnect from.
+** Parameter p_tcb: pointer to the TCB to disconnect.
**
** Returns TRUE: if connection found and to be disconnected; otherwise
** return FALSE.
**
*******************************************************************************/
-BOOLEAN gatt_disconnect (BD_ADDR rem_bda)
+BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb)
{
- tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(rem_bda);
BOOLEAN ret = FALSE;
tGATT_CH_STATE ch_state;
GATT_TRACE_DEBUG0 ("gatt_disconnect ");
@@ -194,12 +192,12 @@
if (ch_state == GATT_CH_OPEN)
{
/* only LCB exist between remote device and local */
- ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, rem_bda);
+ ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, p_tcb->peer_bda);
}
else
{
gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
- ret = L2CA_CancelBleConnectReq (rem_bda);
+ ret = L2CA_CancelBleConnectReq (p_tcb->peer_bda);
}
}
else
@@ -286,13 +284,14 @@
if (check_acl_link &&
p_tcb &&
- (BTM_GetHCIConnHandle(p_tcb->peer_bda) != GATT_INVALID_ACL_HANDLE))
+ p_tcb->att_lcid == L2CAP_ATT_CID && /* only update link idle timer for fixed channel */
+ (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) != GATT_INVALID_ACL_HANDLE))
{
if (is_add)
{
GATT_TRACE_DEBUG0("GATT disables link idle timer");
/* acl link is connected disable the idle timeout */
- GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT);
+ GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
}
else
{
@@ -301,7 +300,7 @@
/* acl link is connected but no application needs to use the link
so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
GATT_TRACE_DEBUG1("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
- GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
+ GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, p_tcb->transport);
}
}
@@ -317,25 +316,22 @@
** Returns void.
**
*******************************************************************************/
-BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr)
+BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport)
{
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)
+ if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, transport)) != NULL)
{
ret = TRUE;
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 &&
- /* only connection on fix channel when the l2cap channel is already open */
- p_tcb->att_lcid == L2CAP_ATT_CID )
+ transport == BT_TRANSPORT_LE )
{
- if (!gatt_connect(bd_addr, p_tcb))
+ if (!gatt_connect(bd_addr, p_tcb, transport))
ret = FALSE;
}
else if(st == GATT_CH_CLOSING)
@@ -346,9 +342,9 @@
}
else
{
- if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL)
+ if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, transport)) != NULL)
{
- if (!gatt_connect(bd_addr, p_tcb))
+ if (!gatt_connect(bd_addr, p_tcb, transport))
{
GATT_TRACE_ERROR0("gatt_connect failed");
memset(p_tcb, 0, sizeof(tGATT_TCB));
@@ -380,19 +376,22 @@
** connected (conn = TRUE)/disconnected (conn = FALSE).
**
*******************************************************************************/
-static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason)
+static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected,
+ UINT16 reason, tBT_TRANSPORT transport)
{
- tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr);
-
+ tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
BOOLEAN check_srv_chg = FALSE;
tGATTS_SRV_CHG *p_srv_chg_clt=NULL;
+ /* ignore all fixed channel connect/disconnect on BR/EDR link for GATT */
+ if (transport == BT_TRANSPORT_BR_EDR)
+ return;
+
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],
(bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected");
-
if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL)
{
check_srv_chg = TRUE;
@@ -405,11 +404,6 @@
if (connected)
{
- GATT_TRACE_DEBUG1("connected is TRUE reason=%d",reason );
- /* BR/EDR lik, ignore this callback */
- if (reason == 0)
- return;
-
/* do we have a channel initiating a connection? */
if (p_tcb)
{
@@ -426,9 +420,10 @@
}
}
/* this is incoming connection or background connection callback */
+
else
{
- if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL)
+ if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_LE)) != NULL)
{
p_tcb->att_lcid = L2CAP_ATT_CID;
@@ -450,7 +445,7 @@
}
else
{
- gatt_cleanup_upon_disc(bd_addr, reason);
+ gatt_cleanup_upon_disc(bd_addr, reason, transport);
GATT_TRACE_DEBUG0 ("ATT disconnected");
}
}
@@ -475,7 +470,7 @@
tGATT_TCB *p_tcb;
/* Find CCB based on bd addr */
- if ((p_tcb = gatt_find_tcb_by_addr (bd_addr)) != NULL &&
+ if ((p_tcb = gatt_find_tcb_by_addr (bd_addr, BT_TRANSPORT_LE)) != NULL &&
gatt_get_ch_state(p_tcb) >= GATT_CH_OPEN)
{
gatt_data_process(p_tcb, p_buf);
@@ -508,7 +503,7 @@
/* do we already have a control channel for this peer? */
UINT8 result = L2CAP_CONN_OK;
tL2CAP_CFG_INFO cfg;
- tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr);
+ tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_BR_EDR);
UNUSED(psm);
GATT_TRACE_ERROR1("Connection indication cid = %d", lcid);
@@ -516,7 +511,7 @@
if (p_tcb == NULL)
{
/* allocate tcb */
- if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) == NULL)
+ if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
/* no tcb available, reject L2CAP connection */
result = L2CAP_CONN_NO_RESOURCES;
@@ -586,7 +581,7 @@
/* else initiating connection failure */
else
{
- gatt_cleanup_upon_disc(p_tcb->peer_bda, GATT_CONN_L2C_FAILURE);
+ gatt_cleanup_upon_disc(p_tcb->peer_bda, result, GATT_TRANSPORT_BR_EDR);
}
}
else /* wrong state, disconnect it */
@@ -701,11 +696,8 @@
}
else
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
- btm_sec_is_le_capable_dev(p_tcb->peer_bda))
- {
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
- }
}
/* send callback */
@@ -738,20 +730,17 @@
/* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid);
}
-
if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL)
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
- btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_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)
+ if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport)) == 0)
reason = GATT_CONN_TERMINATE_PEER_USER;
/* send disconnect callback */
- gatt_cleanup_upon_disc(p_tcb->peer_bda, reason);
+ gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
}
}
@@ -777,17 +766,16 @@
/* If the device is not in the service changed client list, add it... */
if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL)
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
- btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_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)
+ if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport)) == 0)
reason = GATT_CONN_TERMINATE_LOCAL_HOST;
- gatt_cleanup_upon_disc(p_tcb->peer_bda, reason);
+ gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
}
}
@@ -846,16 +834,17 @@
if (p_reg->app_cb.p_conn_cb)
{
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, TRUE, 0);
+ (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id,
+ TRUE, 0, p_tcb->transport);
}
}
}
- if (gatt_num_apps_hold_link(p_tcb))
+ if (gatt_num_apps_hold_link(p_tcb) && p_tcb->att_lcid == L2CAP_ATT_CID )
{
/* disable idle timeout if one or more clients are holding the link disable the idle timer */
- GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT);
+ GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
}
}
@@ -894,7 +883,6 @@
if (op_code == GATT_SIGN_CMD_WRITE)
{
gatt_verify_signature(p_tcb, p_buf);
- return;
}
else
{
@@ -1068,6 +1056,7 @@
BD_ADDR bda;
BOOLEAN srv_chg_ind_pending=FALSE;
tGATT_TCB *p_tcb;
+ tBT_TRANSPORT transport;
GATT_TRACE_DEBUG0 ("gatt_proc_srv_chg");
@@ -1075,7 +1064,7 @@
{
gatt_set_srv_chg();
start_idx =0;
- while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
+ while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport))
{
p_tcb = &gatt_cb.tcb[found_idx];;
srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb);
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index c006dd2..226aad0 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -328,7 +328,7 @@
** Returns void
**
*******************************************************************************/
-static void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT8 *p_data)
+void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
{
UINT8 *p = p_data, flag, i = 0;
UINT32 trans_id = 0;
@@ -336,11 +336,13 @@
tGATT_IF gatt_if;
UINT16 conn_id;
+ UNUSED(len);
+
#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_TRACE_DEBUG1("Conformance tst: forced err rspv for Execute Write: error status=%d",
+ gatt_cb.err_status);
gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, FALSE);
@@ -409,7 +411,7 @@
p_tcb->sr_cmd.multi_req.num_handles = 0;
gatt_sr_get_sec_info(p_tcb->peer_bda,
- (BOOLEAN)(p_tcb->att_lcid == L2CAP_ATT_CID),
+ p_tcb->transport,
&sec_flag,
&key_size);
@@ -527,7 +529,7 @@
*******************************************************************************/
static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_tcb,
UINT8 op_code, UINT16 s_hdl,
- UINT16 e_hdl, tBT_UUID value)
+ UINT16 e_hdl, UINT8 *p_data, tBT_UUID value)
{
tGATT_STATUS status = GATT_NOT_FOUND;
UINT8 handle_len =4, *p ;
@@ -536,6 +538,8 @@
tGATT_SRV_LIST_ELEM *p_srv=NULL;
tBT_UUID *p_uuid;
+ UNUSED(p_data);
+
p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
p_srv = p_list->p_first;
@@ -643,7 +647,7 @@
if (p_attr->handle >= s_hdl)
{
if (p_msg->offset == 0)
- p_msg->offset = (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128) ? GATT_INFO_TYPE_PAIR_128 : GATT_INFO_TYPE_PAIR_16;
+ p_msg->offset = (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) ? GATT_INFO_TYPE_PAIR_16 : GATT_INFO_TYPE_PAIR_128;
if (len >= info_pair_len[p_msg->offset - 1])
{
@@ -652,12 +656,17 @@
UINT16_TO_STREAM(p, p_attr->handle);
UINT16_TO_STREAM(p, p_attr->uuid);
}
- else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 &&
- p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128 )
+ else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128 )
{
UINT16_TO_STREAM(p, p_attr->handle);
ARRAY_TO_STREAM (p, ((tGATT_ATTR128 *) p_attr)->uuid, LEN_UUID_128);
}
+ else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_32)
+ {
+ UINT16_TO_STREAM(p, p_attr->handle);
+ gatt_convert_uuid32_to_uuid128(p, ((tGATT_ATTR32 *) p_attr)->uuid);
+ p += LEN_UUID_128;
+ }
else
{
GATT_TRACE_ERROR0("format mismatch");
@@ -764,6 +773,7 @@
BT_HDR *p_msg = NULL;
UINT16 msg_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
+ memset (&value, 0, sizeof(tBT_UUID));
reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
if (reason == GATT_SUCCESS)
@@ -786,7 +796,7 @@
else
{
memset(p_msg, 0, msg_len);
- reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code, s_hdl, e_hdl, value);
+ reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code, s_hdl, e_hdl, p_data, value);
}
}
}
@@ -1025,7 +1035,7 @@
p_rcb->e_hdl < s_hdl))
{
gatt_sr_get_sec_info(p_tcb->peer_bda,
- (BOOLEAN)(p_tcb->att_lcid == L2CAP_ATT_CID),
+ p_tcb->transport,
&sec_flag,
&key_size);
@@ -1120,7 +1130,7 @@
}
gatt_sr_get_sec_info(p_tcb->peer_bda,
- (BOOLEAN)(p_tcb->att_lcid == L2CAP_ATT_CID),
+ p_tcb->transport,
&sec_flag,
&key_size);
@@ -1173,7 +1183,7 @@
**
*******************************************************************************/
static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code,
- UINT16 handle, UINT8 *p_data)
+ UINT16 handle, UINT16 len, UINT8 *p_data)
{
UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
tGATT_STATUS reason;
@@ -1181,6 +1191,7 @@
UINT8 sec_flag, key_size, *p;
UINT16 offset = 0, value_len = 0;
+ UNUSED (len);
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL)
{
GATT_TRACE_ERROR0("gatts_process_find_info failed. no resources.");
@@ -1199,7 +1210,7 @@
buf_len = p_tcb->payload_size - 1;
gatt_sr_get_sec_info(p_tcb->peer_bda,
- (BOOLEAN)(p_tcb->att_lcid == L2CAP_ATT_CID),
+ p_tcb->transport,
&sec_flag,
&key_size);
@@ -1289,7 +1300,7 @@
{
case GATT_REQ_READ: /* read char/char descriptor value */
case GATT_REQ_READ_BLOB:
- gatts_process_read_req(p_tcb, p_rcb, op_code, handle, p);
+ gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p);
break;
case GATT_REQ_WRITE: /* write char/char descriptor value */
@@ -1506,7 +1517,7 @@
break;
case GATT_REQ_EXEC_WRITE:
- gatt_process_exec_write_req (p_tcb, op_code, p_data);
+ gatt_process_exec_write_req (p_tcb, op_code, len, p_data);
break;
case GATT_REQ_READ_MULTI:
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index 978c88c..d3d4c92 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -705,7 +705,8 @@
** Returns TRUE if found
**
*******************************************************************************/
-BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx)
+BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx,
+ tBT_TRANSPORT *p_transport)
{
UINT8 i;
BOOLEAN found = FALSE;
@@ -717,6 +718,7 @@
{
memcpy( bda, gatt_cb.tcb[i].peer_bda, BD_ADDR_LEN);
*p_found_idx = i;
+ *p_transport = gatt_cb.tcb[i].transport;
found = TRUE;
GATT_TRACE_DEBUG6("gatt_find_the_connected_bda bda :%02x-%02x-%02x-%02x-%02x-%02x",
bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
@@ -833,19 +835,19 @@
** Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
**
*******************************************************************************/
-UINT8 gatt_find_i_tcb_by_addr(BD_ADDR bda)
+UINT8 gatt_find_i_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport)
{
- UINT8 i = 0, j = GATT_INDEX_INVALID;
+ UINT8 i = 0;
for ( ; i < GATT_MAX_PHY_CHANNEL; i ++)
{
- if (!memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN))
+ if (!memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN) &&
+ gatt_cb.tcb[i].transport == transport)
{
- j = i;
- break;
+ return i;
}
}
- return j;
+ return GATT_INDEX_INVALID;
}
@@ -877,12 +879,12 @@
** Returns NULL if not found. Otherwise index to the tcb.
**
*******************************************************************************/
-tGATT_TCB * gatt_find_tcb_by_addr(BD_ADDR bda)
+tGATT_TCB * gatt_find_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport)
{
tGATT_TCB *p_tcb = NULL;
UINT8 i = 0;
- if ((i = gatt_find_i_tcb_by_addr(bda)) != GATT_INDEX_INVALID)
+ if ((i = gatt_find_i_tcb_by_addr(bda, transport)) != GATT_INDEX_INVALID)
p_tcb = &gatt_cb.tcb[i];
return p_tcb;
@@ -919,14 +921,14 @@
** Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
**
*******************************************************************************/
-tGATT_TCB * gatt_allocate_tcb_by_bdaddr(BD_ADDR bda)
+tGATT_TCB * gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport)
{
UINT8 i = 0;
BOOLEAN allocated = FALSE;
tGATT_TCB *p_tcb = NULL;
/* search for existing tcb with matching bda */
- i = gatt_find_i_tcb_by_addr(bda);
+ i = gatt_find_i_tcb_by_addr(bda, transport);
/* find free tcb */
if (i == GATT_INDEX_INVALID)
{
@@ -944,6 +946,7 @@
GKI_init_q (&p_tcb->pending_ind_q);
p_tcb->in_use = TRUE;
p_tcb->tcb_idx = i;
+ p_tcb->transport = transport;
}
memcpy(p_tcb->peer_bda, bda, BD_ADDR_LEN);
}
@@ -970,6 +973,23 @@
/*******************************************************************************
**
+** Function gatt_convert_uuid32_to_uuid128
+**
+** Description Convert a 32 bits UUID to be an standard 128 bits one.
+**
+** Returns TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+void gatt_convert_uuid32_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT32 uuid_32)
+{
+ UINT8 *p = &uuid_128[LEN_UUID_128 - 4];
+
+ memcpy (uuid_128, base_uuid, LEN_UUID_128);
+
+ UINT32_TO_STREAM(p, uuid_32);
+}
+/*******************************************************************************
+**
** Function gatt_uuid_compare
**
** Description Compare two UUID to see if they are the same.
@@ -989,11 +1009,17 @@
}
/* If both are 16-bit, we can do a simple compare */
- if (src.len == 2 && tar.len == 2)
+ if (src.len == LEN_UUID_16 && tar.len == LEN_UUID_16)
{
return src.uu.uuid16 == tar.uu.uuid16;
}
+ /* If both are 32-bit, we can do a simple compare */
+ if (src.len == LEN_UUID_32 && tar.len == LEN_UUID_32)
+ {
+ return src.uu.uuid32 == tar.uu.uuid32;
+ }
+
/* One or both of the UUIDs is 128-bit */
if (src.len == LEN_UUID_16)
{
@@ -1001,6 +1027,11 @@
gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
ps = su;
}
+ else if (src.len == LEN_UUID_32)
+ {
+ gatt_convert_uuid32_to_uuid128(su, src.uu.uuid32);
+ ps = su;
+ }
else
ps = src.uu.uuid128;
@@ -1010,6 +1041,12 @@
gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
pt = tu;
}
+ else if (tar.len == LEN_UUID_32)
+ {
+ /* convert a 32 bits UUID to 128 bits value */
+ gatt_convert_uuid32_to_uuid128(tu, tar.uu.uuid32);
+ pt = tu;
+ }
else
pt = tar.uu.uuid128;
@@ -1035,6 +1072,12 @@
UINT16_TO_STREAM (p, uuid.uu.uuid16);
len = LEN_UUID_16;
}
+ else if (uuid.len == LEN_UUID_32) /* always convert 32 bits into 128 bits as alwats */
+ {
+ gatt_convert_uuid32_to_uuid128(p, uuid.uu.uuid32);
+ p += LEN_UUID_128;
+ len = LEN_UUID_128;
+ }
else if (uuid.len == LEN_UUID_128)
{
ARRAY_TO_STREAM (p, uuid.uu.uuid128, LEN_UUID_128);
@@ -1090,7 +1133,11 @@
STREAM_TO_UINT16(p_uuid_rec->uu.uuid16, p_uuid);
}
else
- is_base_uuid = FALSE;
+ {
+ p_uuid += (LEN_UUID_128 - LEN_UUID_32);
+ p_uuid_rec->len = LEN_UUID_32;
+ STREAM_TO_UINT32(p_uuid_rec->uu.uuid32, p_uuid);
+ }
}
if (!is_base_uuid)
{
@@ -1100,6 +1147,9 @@
*p_data += LEN_UUID_128;
break;
+ /* do not allow 32 bits UUID in ATT PDU now */
+ case LEN_UUID_32:
+ GATT_TRACE_ERROR0("DO NOT ALLOW 32 BITS UUID IN ATT PDU");
case 0:
default:
if (uuid_size != 0) ret = FALSE;
@@ -1200,7 +1250,7 @@
}
GATT_TRACE_WARNING0("gatt_rsp_timeout disconnecting...");
- gatt_disconnect (p_clcb->p_tcb->peer_bda);
+ gatt_disconnect (p_clcb->p_tcb);
}
/*******************************************************************************
@@ -1330,12 +1380,11 @@
** Returns void
**
*******************************************************************************/
-void gatt_sr_get_sec_info(BD_ADDR rem_bda, BOOLEAN le_conn, UINT8 *p_sec_flag, UINT8 *p_key_size)
+void gatt_sr_get_sec_info(BD_ADDR rem_bda, tBT_TRANSPORT transport, UINT8 *p_sec_flag, UINT8 *p_key_size)
{
UINT8 sec_flag = 0;
- UNUSED(le_conn);
- BTM_GetSecurityFlags(rem_bda, &sec_flag);
+ BTM_GetSecurityFlagsByTransport(rem_bda, &sec_flag, transport);
sec_flag &= (GATT_SEC_FLAG_LKEY_UNAUTHED | GATT_SEC_FLAG_LKEY_AUTHED | GATT_SEC_FLAG_ENCRYPTED);
@@ -1438,6 +1487,14 @@
case LEN_UUID_16:
SDP_AddServiceClassIdList(sdp_handle, 1, &p_uuid->uu.uuid16);
break;
+
+ case LEN_UUID_32:
+ UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
+ UINT32_TO_BE_STREAM (p, p_uuid->uu.uuid32);
+ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST, DATA_ELE_SEQ_DESC_TYPE,
+ (UINT32) (p - buff), buff);
+ break;
+
case LEN_UUID_128:
UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
ARRAY_TO_BE_STREAM (p, p_uuid->uu.uuid128, LEN_UUID_128);
@@ -1889,7 +1946,8 @@
tGATT_TCB *p_tcb=NULL;
BOOLEAN status= TRUE;
- p_tcb = gatt_find_tcb_by_addr(bda);
+ p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE);
+
if (p_tcb)
{
if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
@@ -1902,7 +1960,7 @@
gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
if (!gatt_num_apps_hold_link(p_tcb))
{
- gatt_disconnect(p_tcb->peer_bda);
+ gatt_disconnect(p_tcb);
}
}
}
@@ -2131,7 +2189,7 @@
** Returns 16 bits uuid.
**
*******************************************************************************/
-void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason)
+void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
{
tGATT_TCB *p_tcb = NULL;
tGATT_CLCB *p_clcb;
@@ -2142,9 +2200,10 @@
GATT_TRACE_DEBUG0 ("gatt_cleanup_upon_disc ");
- if ((p_tcb = gatt_find_tcb_by_addr(bda)) != NULL)
+ if ((p_tcb = gatt_find_tcb_by_addr(bda, transport)) != NULL)
{
GATT_TRACE_DEBUG0 ("found p_tcb ");
+ gatt_set_ch_state(p_tcb, GATT_CH_CLOSE);
for (i = 0; i < GATT_CL_MAX_LCB; i ++)
{
p_clcb = &gatt_cb.clcb[i];
@@ -2172,7 +2231,7 @@
{
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
GATT_TRACE_DEBUG3 ("found p_reg tcb_idx=%d gatt_if=%d conn_id=0x%x", p_tcb->tcb_idx, p_reg->gatt_if, conn_id);
- (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, FALSE, reason);
+ (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, FALSE, reason, transport);
}
}
memset(p_tcb, 0, sizeof(tGATT_TCB));
@@ -2228,6 +2287,10 @@
{
sprintf(str_buf, "0x%04x", bt_uuid.uu.uuid16);
}
+ else if (bt_uuid.len == LEN_UUID_32)
+ {
+ sprintf(str_buf, "0x%08x", (unsigned int)bt_uuid.uu.uuid32);
+ }
else if (bt_uuid.len == LEN_UUID_128)
{
x += sprintf(&str_buf[x], "0x%02x%02x%02x%02x%02x%02x%02x%02x",
@@ -2406,7 +2469,7 @@
*******************************************************************************/
BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr)
{
- tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr);
+ tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
BOOLEAN status;
if (p_tcb)
@@ -2628,7 +2691,7 @@
{
BOOLEAN ret = FALSE;
tGATT_REG *p_reg;
- tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr);
+ tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
GATT_TRACE_API0 ("gatt_update_auto_connect_dev ");
/* Make sure app is registered */
@@ -2659,54 +2722,6 @@
/*******************************************************************************
**
-** Function gatt_get_conn_id
-**
-** Description This function returns a connecttion handle to a ATT server
-** if the server is already connected
-**
-** Parameters gatt_if: client interface.
-** bd_addr: peer device address.
-**
-** Returns Connection handle or invalid handle value
-**
-*******************************************************************************/
-UINT16 gatt_get_conn_id (tGATT_IF gatt_if, BD_ADDR bd_addr)
-{
- tGATT_REG *p_reg;
- tGATT_CLCB *p_clcb;
- tGATT_TCB *p_tcb;
- UINT8 i;
-
- GATT_TRACE_API1 ("GATTC_GetConnIfConnected gatt_if=%d", gatt_if);
- /* Do we have a transport to the peer ? If not, we are not connected */
- if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) == NULL)
- {
- GATT_TRACE_EVENT0 ("GATTC_GetConnIfConnected - no TCB found");
- return(GATT_INVALID_CONN_ID);
- }
-
- /* Make sure app is registered */
- if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
- {
- GATT_TRACE_ERROR1("GATTC_GetConnIfConnected - gatt_if is not registered", gatt_if);
- return(GATT_INVALID_CONN_ID);
- }
-
- /* Now see if the app already has a client control block to that peer */
- for (i = 0, p_clcb = gatt_cb.clcb; i < GATT_CL_MAX_LCB; i++, p_clcb++)
- {
- if ( p_clcb->in_use && (p_clcb->p_reg == p_reg) && (p_clcb->p_tcb == p_tcb) )
- {
- return(p_clcb->conn_id);
- }
- }
-
- /* If here, failed to allocate a client control block */
- 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
@@ -2736,12 +2751,13 @@
** Returns Pointer to the new service start buffer, NULL no buffer available
**
*******************************************************************************/
-void gatt_update_listen_mode(void)
+BOOLEAN gatt_update_listen_mode(void)
{
UINT8 ii = 0;
tGATT_REG *p_reg = &gatt_cb.cl_rcb[0];
UINT8 listening = 0;
UINT16 connectability, window, interval;
+ BOOLEAN rt = TRUE;
for (; ii < GATT_MAX_APPS; ii ++, p_reg ++)
{
@@ -2757,16 +2773,24 @@
else
BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_WL);
- connectability = BTM_ReadConnectability (&window, &interval);
-
- if (listening != GATT_LISTEN_TO_NONE)
+ if (rt)
{
- connectability |= BTM_BLE_CONNECTABLE;
+ connectability = BTM_ReadConnectability (&window, &interval);
+
+ if (listening != GATT_LISTEN_TO_NONE)
+ {
+ connectability |= BTM_BLE_CONNECTABLE;
+ }
+ else
+ {
+ if ((connectability & BTM_BLE_CONNECTABLE) == 0)
+ connectability &= ~BTM_BLE_CONNECTABLE;
+ }
+ /* turning on the adv now */
+ btm_ble_set_connectability(connectability);
}
- else
- connectability &= ~BTM_BLE_CONNECTABLE;
- /* turning on the adv now */
- BTM_SetConnectability(connectability, window, interval);
+
+ return rt;
}
#endif
diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c
index a4e55da..860fb7a 100644
--- a/stack/hcic/hciblecmds.c
+++ b/stack/hcic/hciblecmds.c
@@ -35,27 +35,6 @@
#if (defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE)
-BOOLEAN btsnd_hcic_ble_reset(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_RESET);
- UINT8_TO_STREAM (pp, 0);
-
- btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
- return (TRUE);
-
-}
-
BOOLEAN btsnd_hcic_ble_set_evt_mask (BT_EVENT_MASK event_mask)
{
BT_HDR *p;
@@ -163,7 +142,7 @@
BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max,
UINT8 adv_type, UINT8 addr_type_own,
UINT8 addr_type_dir, BD_ADDR direct_bda,
- UINT8 channel_map, UINT8 adv_filter_policy)
+ UINT8 channel_map, UINT8 scan_filter_policy)
{
BT_HDR *p;
UINT8 *pp;
@@ -186,7 +165,7 @@
UINT8_TO_STREAM (pp, addr_type_dir);
BDADDR_TO_STREAM (pp, direct_bda);
UINT8_TO_STREAM (pp, channel_map);
- UINT8_TO_STREAM (pp, adv_filter_policy);
+ UINT8_TO_STREAM (pp, scan_filter_policy);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
return (TRUE);
@@ -856,4 +835,62 @@
return (TRUE);
}
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+
+BOOLEAN btsnd_hcic_ble_rc_param_req_reply( UINT16 handle,
+ UINT16 conn_int_min, UINT16 conn_int_max,
+ UINT16 conn_latency, UINT16 conn_timeout,
+ UINT16 min_ce_len, UINT16 max_ce_len )
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_REPLY)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_REPLY;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_RC_PARAM_REQ_REPLY);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_REPLY);
+
+ UINT16_TO_STREAM (pp, handle);
+ UINT16_TO_STREAM (pp, conn_int_min);
+ UINT16_TO_STREAM (pp, conn_int_max);
+ UINT16_TO_STREAM (pp, conn_latency);
+ UINT16_TO_STREAM (pp, conn_timeout);
+ UINT16_TO_STREAM (pp, min_ce_len);
+ UINT16_TO_STREAM (pp, max_ce_len);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_rc_param_req_neg_reply(UINT16 handle, UINT8 reason)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_NEG_REPLY)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_NEG_REPLY;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_RC_PARAM_REQ_NEG_REPLY);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_NEG_REPLY);
+
+ UINT16_TO_STREAM (pp, handle);
+ UINT8_TO_STREAM (pp, reason);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
#endif
+
+#endif
+
diff --git a/stack/hcic/hcicmds.c b/stack/hcic/hcicmds.c
index 09e98fe..a530d2a 100644
--- a/stack/hcic/hcicmds.c
+++ b/stack/hcic/hcicmds.c
@@ -783,13 +783,6 @@
BT_HDR *p;
UINT8 *pp;
- #ifdef BDCFG_OVERRIDE_SNIFF_MODE_MAX
- max_sniff_period = BDCFG_OVERRIDE_SNIFF_MODE_MAX;
- min_sniff_period = BDCFG_OVERRIDE_SNIFF_MODE_MIN;
- sniff_attempt = BDCFG_OVERRIDE_SNIFF_MODE_ATTEMPT;
- sniff_timeout = BDCFG_OVERRIDE_SNIFF_MODE_TIMEOUT;
- #endif
-
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_SNIFF_MODE)) == NULL)
return (FALSE);
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 86b41d3..dd9d9f0 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -98,13 +98,13 @@
/* Now, register with L2CAP */
if (!L2CA_Register (HID_PSM_CONTROL, (tL2CAP_APPL_INFO *) &hst_reg_info))
{
- HIDH_TRACE_ERROR0 ("HID Control Registration failed");
+ HIDH_TRACE_ERROR0 ("HID-Host Control Registration failed");
return (HID_ERR_L2CAP_FAILED) ;
}
if (!L2CA_Register (HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO *) &hst_reg_info))
{
L2CA_Deregister( HID_PSM_CONTROL ) ;
- HIDH_TRACE_ERROR0 ("HID Interrupt Registration failed");
+ HIDH_TRACE_ERROR0 ("HID-Host Interrupt Registration failed");
return (HID_ERR_L2CAP_FAILED) ;
}
@@ -136,11 +136,13 @@
{
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
+ /* Set l2cap idle timeout to 0 (so ACL link is disconnected
+ * immediately after last channel is closed) */
+ L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0);
/* Disconnect both interrupt and control channels */
if (p_hcon->intr_cid)
L2CA_DisconnectReq (p_hcon->intr_cid);
-
- if (p_hcon->ctrl_cid)
+ else if (p_hcon->ctrl_cid)
L2CA_DisconnectReq (p_hcon->ctrl_cid);
}
else
@@ -161,10 +163,11 @@
** send security block L2C connection response.
**
*******************************************************************************/
-void hidh_sec_check_complete_term (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+void hidh_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
tHID_HOST_DEV_CTB *p_dev= (tHID_HOST_DEV_CTB *) p_ref_data;
UNUSED(bd_addr);
+ UNUSED (transport);
if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
{
@@ -314,7 +317,7 @@
** Returns void
**
*******************************************************************************/
-void hidh_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+void hidh_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
tHID_HOST_DEV_CTB *p_dev = (tHID_HOST_DEV_CTB *) p_ref_data;
UINT8 dhandle;
@@ -323,6 +326,7 @@
#endif
UINT32 reason;
UNUSED(bd_addr);
+ UNUSED (transport);
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 )
@@ -330,20 +334,11 @@
HIDH_TRACE_EVENT0 ("HID-Host Originator security pass.");
p_dev->conn.disc_reason = HID_SUCCESS; /* Authentication passed. Reset disc_reason (from HID_ERR_AUTH_FAILED) */
- /* Check if L2CAP started the connection process for interrupt channel */
- if ((p_dev->conn.intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0)
- {
- HIDH_TRACE_WARNING0 ("HID-Host INTR Originate failed");
- reason = HID_L2CAP_REQ_FAIL ;
- hidh_conn_disconnect (dhandle);
- hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
- return;
- }
- else
- {
- /* Transition to the next appropriate state, waiting for connection confirm on control channel. */
- p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR;
- }
+ /* Transition to the next appropriate state, configuration */
+ p_dev->conn.conn_state = HID_CONN_STATE_CONFIG;
+ L2CA_ConfigReq (p_dev->conn.ctrl_cid, &hh_cb.l2cap_cfg);
+ HIDH_TRACE_EVENT1 ("HID-Host Got Control conn cnf, sent cfg req, CID: 0x%x", p_dev->conn.ctrl_cid);
+
}
if( res != BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
@@ -394,7 +389,8 @@
if ((p_hcon == NULL)
|| (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG))
|| ((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL))
- || ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)))
+ || ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)
+ && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING)))
{
HIDH_TRACE_WARNING1 ("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid);
return;
@@ -439,12 +435,11 @@
else
{
p_hcon->conn_state = HID_CONN_STATE_CONFIG;
+ /* Send a Configuration Request. */
+ L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg);
+ HIDH_TRACE_EVENT1 ("HID-Host got Interrupt conn cnf, sent cfg req, CID: 0x%x", l2cap_cid);
}
- /* Send a Configuration Request. */
- L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg);
-
- HIDH_TRACE_EVENT1 ("HID-Host got CTRL conn cnf, sent cfg req, CID: 0x%x", l2cap_cid);
return;
}
@@ -463,6 +458,7 @@
UINT8 dhandle;
tHID_CONN *p_hcon = NULL;
tHID_HOST_DEV_CTB *p_dev;
+ UINT32 reason;
/* Find CCB based on CID */
if( (dhandle = find_conn_by_cid(l2cap_cid)) < HID_HOST_MAX_DEVICES )
@@ -493,7 +489,29 @@
L2CA_ConfigRsp (l2cap_cid, p_cfg);
if (l2cap_cid == p_hcon->ctrl_cid)
+ {
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
+ if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
+ (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE))
+ {
+ /* Connect interrupt channel */
+ p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
+ if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0)
+ {
+ HIDH_TRACE_WARNING0 ("HID-Host INTR Originate failed");
+ reason = HID_L2CAP_REQ_FAIL ;
+ p_hcon->conn_state = HID_CONN_STATE_UNUSED;
+ hidh_conn_disconnect (dhandle);
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+ return;
+ }
+ else
+ {
+ /* Transition to the next appropriate state, waiting for connection confirm on interrupt channel. */
+ p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
+ }
+ }
+ }
else
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_INTR_CFG_DONE;
@@ -502,6 +520,8 @@
&& (p_hcon->conn_state == HID_CONN_STATE_CONFIG))
{
p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
+ /* Reset disconnect reason to success, as connection successful */
+ p_hcon->disc_reason = HID_SUCCESS;
hh_cb.devices[dhandle].state = HID_DEV_CONNECTED;
hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_OPEN, 0, NULL ) ;
@@ -547,7 +567,29 @@
}
if (l2cap_cid == p_hcon->ctrl_cid)
+ {
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
+ if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
+ (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE))
+ {
+ /* Connect interrupt channel */
+ p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
+ if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0)
+ {
+ HIDH_TRACE_WARNING0 ("HID-Host INTR Originate failed");
+ reason = HID_L2CAP_REQ_FAIL ;
+ p_hcon->conn_state = HID_CONN_STATE_UNUSED;
+ hidh_conn_disconnect (dhandle);
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+ return;
+ }
+ else
+ {
+ /* Transition to the next appropriate state, waiting for connection confirm on interrupt channel. */
+ p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
+ }
+ }
+ }
else
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_INTR_CFG_DONE;
@@ -556,6 +598,8 @@
&& (p_hcon->conn_state == HID_CONN_STATE_CONFIG))
{
p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
+ /* Reset disconnect reason to success, as connection successful */
+ p_hcon->disc_reason = HID_SUCCESS;
hh_cb.devices[dhandle].state = HID_DEV_CONNECTED;
hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_OPEN, 0, NULL ) ;
@@ -618,6 +662,7 @@
hh_cb.devices[dhandle].conn_tries = 0;
hh_cb.devices[dhandle].conn.timer_entry.param = (UINT32) dhandle;
btu_start_timer (&(hh_cb.devices[dhandle].conn.timer_entry), BTU_TTYPE_HID_HOST_REPAGE_TO, HID_HOST_REPAGE_WIN);
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, disc_res, NULL);
}
else
#endif
@@ -674,7 +719,14 @@
if (l2cap_cid == p_hcon->ctrl_cid)
p_hcon->ctrl_cid = 0;
else
+ {
p_hcon->intr_cid = 0;
+ if (p_hcon->ctrl_cid)
+ {
+ HIDH_TRACE_EVENT0 ("HID-Host Initiating L2CAP Ctrl disconnection");
+ L2CA_DisconnectReq (p_hcon->ctrl_cid);
+ }
+ }
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0))
{
@@ -831,6 +883,13 @@
UINT8 use_data = 0 ;
BOOLEAN blank_datc = FALSE;
+ if (!BTM_IsAclConnectionUp(hh_cb.devices[dhandle].addr, BT_TRANSPORT_BR_EDR))
+ {
+ if (buf)
+ GKI_freebuf ((void *)buf);
+ return( HID_ERR_NO_CONNECTION );
+ }
+
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED)
{
if (buf)
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index 33fb884..e7a7937 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -497,6 +497,10 @@
#define BLE_ADDR_TYPE_MASK (BLE_ADDR_RANDOM | BLE_ADDR_PUBLIC)
typedef UINT8 tBLE_ADDR_TYPE;
+#define BT_TRANSPORT_BR_EDR 1
+#define BT_TRANSPORT_LE 2
+typedef UINT8 tBT_TRANSPORT;
+
#define BLE_ADDR_IS_STATIC(x) ((x[0] & 0xC0) == 0xC0)
typedef struct
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index f4b17d4..368e70d 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -200,20 +200,20 @@
/* BTM_IsInquiryActive return values (Bit Mask)
* Note: These bit masks are associated with the inquiry modes (BTM_*_INQUIRY) */
#define BTM_INQUIRY_INACTIVE 0x0 /* no inquiry in progress */
-#define BTM_GENERAL_INQUIRY_ACTIVE 0x1 /* a general inquiry is in progress */
-#define BTM_LIMITED_INQUIRY_ACTIVE 0x2 /* a limited inquiry is in progress */
+#define BTM_GENERAL_INQUIRY_ACTIVE BTM_GENERAL_INQUIRY /* a general inquiry is in progress */
+#define BTM_LIMITED_INQUIRY_ACTIVE BTM_LIMITED_INQUIRY /* 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 */
+#define BTM_LE_GENERAL_INQUIRY_ACTIVE BTM_BLE_GENERAL_INQUIRY /* a general inquiry is in progress */
+#define BTM_LE_LIMITED_INQUIRY_ACTIVE BTM_BLE_LIMITED_INQUIRY /* 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 BTM_BR_INQ_ACTIVE_MASK (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE|BTM_PERIODIC_INQUIRY_ACTIVE) /* BR/EDR inquiry activity mask */
+#define BTM_BLE_SCAN_ACTIVE_MASK 0xF0 /* LE scan activity mask */
+#define BTM_BLE_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_BLE_INQ_ACTIVE_MASK) /* inquiry activity mask */
/* Define scan types */
#define BTM_SCAN_TYPE_STANDARD 0
@@ -659,6 +659,7 @@
typedef struct
{
UINT16 status;
+ BD_ADDR bd_addr;
UINT16 length;
BD_NAME remote_bd_name;
} tBTM_REMOTE_DEV_NAME;
@@ -837,6 +838,10 @@
DEV_CLASS_PTR p_dc; /* The device class */
BD_NAME_PTR p_bdn; /* The device name */
UINT8 *p_features; /* pointer to the remote device's features page[0] (supported features page) */
+#if BLE_INCLUDED == TRUE
+ UINT16 handle; /* connection handle */
+ tBT_TRANSPORT transport; /* link is LE or not */
+#endif
} tBTM_BL_CONN_DATA;
/* the data type associated with BTM_BL_DISCN_EVT */
@@ -844,6 +849,10 @@
{
tBTM_BL_EVENT event; /* The event reported. */
BD_ADDR_PTR p_bda; /* The address of the disconnected device */
+#if BLE_INCLUDED == TRUE
+ UINT16 handle; /* disconnected connection handle */
+ tBT_TRANSPORT transport; /* link is LE link or not */
+#endif
} tBTM_BL_DISCN_DATA;
/* Busy-Level shall have the inquiry_paging mask set when
@@ -893,10 +902,16 @@
** changes. First param is BD address, second is if added or removed.
** Registered through BTM_AclRegisterForChanges call.
*/
+#if BLE_INCLUDED == TRUE
+typedef void (tBTM_ACL_DB_CHANGE_CB) (BD_ADDR p_bda, DEV_CLASS p_dc,
+ BD_NAME p_bdn, UINT8 *features,
+ BOOLEAN is_new, UINT16 handle,
+ tBT_TRANSPORT transport);
+#else
typedef void (tBTM_ACL_DB_CHANGE_CB) (BD_ADDR p_bda, DEV_CLASS p_dc,
BD_NAME p_bdn, UINT8 *features,
BOOLEAN is_new);
-
+#endif
/*****************************************************************************
** SCO CHANNEL MANAGEMENT
*****************************************************************************/
@@ -1565,7 +1580,8 @@
** optional data passed in by BTM_SetEncryption
** tBTM_STATUS - result of the operation
*/
-typedef void (tBTM_SEC_CBACK) (BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result);
+typedef void (tBTM_SEC_CBACK) (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
+ void *p_ref_data, tBTM_STATUS result);
/* Bond Cancel complete. Parameters are
** Result of the cancel operation
@@ -1897,73 +1913,6 @@
#define BTM_VSC_NFC_SUPPORTED(x) ((x)[BTM_FEATURE_NFC_OFF] & BTM_FEATURE_NFC_MASK)
-/************************
-** Dual-Stack support
-*************************/
-/* BTM_SYNC_FAIL_EVT reason codes */
-#define BTM_SYNC_SUCCESS 0
-#define BTM_SYNC_FAIL_BTE_SWITCH_REJECTED 1
-#define BTM_SYNC_FAIL_TRANS_PAUSE 2
-#define BTM_SYNC_FAIL_CORE_SYNC 3
-#define BTM_SYNC_FAIL_BTA_SYNC 4
-#define BTM_SYNC_FAIL_TRANS_RESUME 5
-#define BTM_SYNC_FAIL_RESYNC 6
-#define BTM_SYNC_FAIL_ERROR 7
-#define BTM_SYNC_FAIL_UIPC_OPEN 8
-typedef UINT8 tBTM_SYNC_STATUS;
-
-/* Direction of sync (used by BTM_SyncStack) */
-#define BTM_SW_BB_TO_MM 0
-#define BTM_SW_TO_BB 1 /* Switch back to baseband stack (from either MM or BTC host) */
-#define BTM_SW_RESYNC 2
-#define BTM_SW_BB_TO_BTC 3 /* Switch from baseband stack to Bluetooth Controller Host stack */
-#define BTM_SW_MM_TO_BB 4
-#define BTM_SW_BTC_TO_BB 5
-typedef UINT8 tBTM_SW_DIR;
-
-/* Stack synchronization events (returned by tBTM_SYNC_STACK_CBACK callback) */
-#define BTM_SYNC_CPLT_EVT 0
-#define BTM_SYNC_BTA_EVT 1
-#define BTM_RESYNC_CPLT_EVT 2
-#define BTM_UIPC_OPENED_EVT 3
-#define BTM_UIPC_CLOSED_EVT 4
-typedef UINT8 tBTM_SYNC_STACK_EVT;
-
-/* Synchronization info from BTA/application that will be sent when calling BTE sync request functions */
-typedef struct
-{
- tBTM_SW_DIR dir;
- UINT16 lcid[BTM_SYNC_INFO_NUM_STR];
- UINT8 avdt_handle[BTM_SYNC_INFO_NUM_STR];
-} tBTM_SYNC_INFO;
-
-/* Stack synchonization callback function
-** Parameters are
-** event: stack synchronization event
-** status: BTM_SUCCESS if event was successful
-*/
-typedef void (*tBTM_SYNC_STACK_CBACK)(tBTM_SYNC_STACK_EVT event, tBTM_SYNC_STATUS status);
-
-
-/* Sync complete callback function. Called by bte layers after synchronization is complete
-** so that BTM_SYNC can procede with the next step for switching stack to MM
-**
-** Parameters are
-** status: BTM_SUCCESS if synchronization was successful
-*/
-typedef void (*tBTM_SYNC_CPLT_CBACK)(tBTM_STATUS status);
-
-
-
-/* IPC event callback function. Called by BTM when an IPC event is received.
-** These events are currently sent to DM through the callback function.
-**
-** Parameters are
-** status: BTM_SUCCESS if synchronization was successful
-** p_data: Actual message in the IPC
-*/
-typedef void (tBTM_IPC_EVT_CBACK)(tBTM_STATUS status, BT_HDR *p_data);
-
/* MIP evnets, callbacks */
enum
{
@@ -2659,7 +2608,8 @@
**
*******************************************************************************/
BTM_API extern tBTM_STATUS BTM_ReadRemoteDeviceName (BD_ADDR remote_bda,
- tBTM_CMPL_CB *p_cb);
+ tBTM_CMPL_CB *p_cb,
+ tBT_TRANSPORT transport);
/*******************************************************************************
@@ -3187,7 +3137,7 @@
** Returns TRUE if connection is up, else FALSE.
**
*******************************************************************************/
- BTM_API extern BOOLEAN BTM_IsAclConnectionUp (BD_ADDR remote_bda);
+ BTM_API extern BOOLEAN BTM_IsAclConnectionUp (BD_ADDR remote_bda, tBT_TRANSPORT transport);
/*******************************************************************************
@@ -3273,7 +3223,8 @@
** BTM_BUSY if command is already in progress
**
*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb);
+ BTM_API extern tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda,
+ tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb);
/*******************************************************************************
**
@@ -3640,7 +3591,8 @@
** Returns TRUE if registered OK, else FALSE
**
*******************************************************************************/
- BTM_API extern BOOLEAN BTM_SecRegisterLinkKeyNotificationCallback (tBTM_LINK_KEY_CALLBACK *p_callback);
+ BTM_API extern BOOLEAN BTM_SecRegisterLinkKeyNotificationCallback (
+ tBTM_LINK_KEY_CALLBACK *p_callback);
/*******************************************************************************
@@ -3653,7 +3605,8 @@
** Returns TRUE if registered OK, else FALSE
**
*******************************************************************************/
- BTM_API extern BOOLEAN BTM_SecAddRmtNameNotifyCallback (tBTM_RMT_NAME_CALLBACK *p_callback);
+ BTM_API extern BOOLEAN BTM_SecAddRmtNameNotifyCallback (
+ tBTM_RMT_NAME_CALLBACK *p_callback);
/*******************************************************************************
@@ -3666,7 +3619,8 @@
** Returns TRUE if OK, else FALSE
**
*******************************************************************************/
- BTM_API extern BOOLEAN BTM_SecDeleteRmtNameNotifyCallback (tBTM_RMT_NAME_CALLBACK *p_callback);
+ BTM_API extern BOOLEAN BTM_SecDeleteRmtNameNotifyCallback (
+ tBTM_RMT_NAME_CALLBACK *p_callback);
/*******************************************************************************
@@ -3709,6 +3663,22 @@
/*******************************************************************************
**
+** Function BTM_GetSecurityFlagsByTransport
+**
+** Description Get security flags for the device on a particular transport
+**
+** Parameters bd_addr: BD address of remote device
+** p_sec_flags : Out parameter to be filled with security flags for the connection
+** transport : Physical transport of the connection (BR/EDR or LE)
+**
+** Returns BOOLEAN TRUE or FALSE is device found
+**
+*******************************************************************************/
+ BTM_API extern BOOLEAN BTM_GetSecurityFlagsByTransport (BD_ADDR bd_addr,
+ UINT8 * p_sec_flags, tBT_TRANSPORT transport);
+
+/*******************************************************************************
+**
** Function BTM_ReadTrustedMask
**
** Description Get trusted mask for the device
@@ -3789,9 +3759,10 @@
** Returns TRUE if registered OK, else FALSE
**
*******************************************************************************/
- BTM_API extern BOOLEAN BTM_SetUCDSecurityLevel (BOOLEAN is_originator, char *p_name, UINT8 service_id,
- UINT16 sec_level, UINT16 psm, UINT32 mx_proto_id,
- UINT32 mx_chan_id);
+ BTM_API extern BOOLEAN BTM_SetUCDSecurityLevel (BOOLEAN is_originator, char *p_name,
+ UINT8 service_id, UINT16 sec_level,
+ UINT16 psm, UINT32 mx_proto_id,
+ UINT32 mx_chan_id);
/*******************************************************************************
**
@@ -3951,10 +3922,37 @@
**
** 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)
+
** Returns BTM_CMD_STARTED if successfully initiated, otherwise error
**
*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[]);
+ BTM_API extern tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr,
+ UINT8 pin_len, UINT8 *p_pin,
+ UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function BTM_SecBondByTransport
+**
+** Description This function is called to perform bonding by designated transport
+**
+** 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)
+** transport : Physical transport to use for bonding (BR/EDR or LE)
+**
+** Returns BTM_CMD_STARTED if successfully initiated, otherwise error
+**
+*******************************************************************************/
+ BTM_API extern tBTM_STATUS BTM_SecBondByTransport (BD_ADDR bd_addr,
+ tBT_TRANSPORT transport,
+ UINT8 pin_len, UINT8 *p_pin,
+ UINT32 trusted_mask[]);
/*******************************************************************************
**
@@ -3993,8 +3991,8 @@
** BTM_MODE_UNSUPPORTED - if security manager not linked in.
**
*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBTM_SEC_CBACK *p_callback,
- void *p_ref_data);
+ BTM_API extern tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+ tBTM_SEC_CBACK *p_callback, void *p_ref_data);
/*******************************************************************************
**
@@ -4079,7 +4077,8 @@
** r - simple pairing Randomizer C.
**
*******************************************************************************/
- BTM_API extern void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r);
+ BTM_API extern void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr,
+ BT_OCTET16 c, BT_OCTET16 r);
/*******************************************************************************
**
@@ -4232,7 +4231,7 @@
** Returns the handle of the connection, or 0xFFFF if none.
**
*******************************************************************************/
- BTM_API extern UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda);
+ BTM_API extern UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda, tBT_TRANSPORT transport);
/*******************************************************************************
@@ -4419,171 +4418,6 @@
BTM_API extern UINT8 BTM_GetEirUuidList( UINT8 *p_eir, UINT8 uuid_size, UINT8 *p_num_uuid,
UINT8 *p_uuid_list, UINT8 max_num_uuid);
-/*******************************************************************************
-**
-** Function BTM_SyncStack
-**
-** Description For Dual-Stack support. Called to initiate switching to/from
-** main stack (running on phone baseband) to mm stack (light
-** stack running on multi-media chip)
-**
-** Parameters sync_dir: BTM_SW_BB_TO_MM: switch from BB to MM stack
-** BTM_SW_MM_TO_BB: switch from MM to BB stack
-** BTM_SW_RESYNC: resync MM and BB stacks
-**
-** p_sync_cback: callback function for event notification
-** Returns
-**
-*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_SyncStack(tBTM_SW_DIR sync_dir, tBTM_SYNC_STACK_CBACK p_sync_cback);
-
-/*******************************************************************************
-**
-** Function BTM_SyncBtaRsp
-**
-** Description For Dual-Stack support. Called to indicate that upper layers
-** (e.g. BTA or application) have completed synchronizing bta/app
-** specific layers for switching.
-**
-** Called in response to 'BTM_SYNC_BTA_EVT'
-**
-** Parameters status: BTM_SUCESS: bta/app successfully synchronized
-** otherwise: sync was unsuccessfule. Abort switch.
-**
-** p_btm_sync_info: information from bta/app that will be needed
-** by BTE (avdt and l2cap) for switching.
-**
-** Returns void
-**
-*******************************************************************************/
- BTM_API extern void BTM_SyncBtaRsp(tBTM_STATUS status, tBTM_SYNC_INFO *p_btm_sync_info);
-
-/*******************************************************************************
-**
-** Function BTM_OpenUIPC
-**
-** Description For Dual-Stack support. Called to open UIPC between
-** main stack (running on phone baseband) to embedded light stack
-** (running on Multimedia or Bluetooth Controller chip)
-**
-** Parameters sync_dir: BTM_SW_BB_TO_MM: switch from BB to MM stack
-** BTM_SW_BB_TO_BTC:switch from BB to BTC stack
-**
-** p_sync_callback: callback function for event notification
-** Returns
-**
-*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_OpenUIPC(tBTM_SW_DIR sync_dir, tBTM_SYNC_STACK_CBACK p_sync_callback);
-
-/*******************************************************************************
-**
-** Function BTM_CloseUIPC
-**
-** Description For Dual-Stack support. Called to close UIPC between
-** main stack (running on phone baseband) to embedded light stack
-** (running on Multimedia or Bluetooth Controller chip)
-**
-** Parameters
-** p_sync_callback: callback function for event notification
-** Returns
-**
-*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_CloseUIPC(tBTM_SYNC_STACK_CBACK p_sync_callback);
-
-/*******************************************************************************
-**
-** Function BTM_IpcSend
-**
-** Description For Dual-Stack support. Called to send ipc messages from
-** full stack to lite stack and vice-versa. This API is
-** typically called by bta layers e.g. bta_av.
-**
-**
-** Parameters len: Length of the buffer in the ipc message
-**
-** buffer: Pointer to the buffer to be passed in the IPC message
-**
-** Returns void
-**
-*******************************************************************************/
- BTM_API extern void BTM_IpcSend(UINT16 len, UINT8* buffer);
-
-/*******************************************************************************
-**
-** Function BTM_IpcSendBuf
-**
-** Description For Dual-Stack support. Called to send ipc messages from
-** full stack to lite stack and vice-versa. This API is
-** typically called by bta layers e.g. bta_av_sync.
-**
-**
-** Parameters p_buf: Pointer to the buffer to be passed in the IPC message
-**
-** Returns void
-**
-*******************************************************************************/
- BTM_API extern void BTM_IpcSendBuf(BT_HDR* p_buf);
-
-/*******************************************************************************
-**
-** Function BTM_RegIpcEvtHandler
-**
-** Description registers the DM provided handler for IPC events
-**
-**
-** Returns void
-**
-*******************************************************************************/
- BTM_API extern void BTM_RegIpcEvtHandler(tBTM_IPC_EVT_CBACK *p_cback);
-
-/*******************************************************************************
-**
-** Function BTM_RegRTIpcEvtHandler
-**
-** Description registers the RT(Audio Routing) provided handler for IPC events
-**
-**
-** Returns void
-**
-*******************************************************************************/
- BTM_API extern void BTM_RegRTIpcEvtHandler(tBTM_IPC_EVT_CBACK *p_cback);
-
-/*****************************************************************************
-** N2BT
-*****************************************************************************/
-
-/* Data callback for N2BT */
- typedef void (tBTM_N2BT_DATA_CB) (BD_ADDR bd_addr, UINT16 handle, UINT8 *p_data, UINT16 datalen);
-
-/*******************************************************************************
-**
-** Function BTM_N2BtAcquire
-**
-** Description Put controller into acquisition mode
-**
-** Returns void
-**
-*******************************************************************************/
- BTM_API extern void BTM_N2BtAcquire(BD_ADDR bd_addr, UINT16 timeout,
- UINT8 freq, UINT8 src_addrlen, UINT8 sensor_flags,
- UINT8 sensor_type, UINT8 sensor_clk_accuracy,
- UINT16 add_rx_window, UINT16 init_crc,
- UINT32 ac_low, UINT32 ac_high, UINT16 pkt_hdr,
- UINT16 list_dur, UINT16 list_int,
- UINT8 oor_missed_pkts, tBTM_VSC_CMPL_CB *p_cb,
- tBTM_N2BT_DATA_CB *p_data_cback);
-
-/*******************************************************************************
-**
-** Function BTM_N2BtDisconnect
-**
-** Description Disconnects all N2BT devices
-**
-** Returns void
-**
-*******************************************************************************/
- BTM_API extern void BTM_N2BtDisconnect(void);
-
/*****************************************************************************
** SCO OVER HCI
*****************************************************************************/
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 584ce9a..3e1bf7b 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -26,16 +26,22 @@
#define BTM_BLE_API_H
#include "btm_api.h"
+#include "gki.h"
#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
+/* 0x00-0x04 only used for set advertising parameter command */
+#define BTM_BLE_CONNECT_EVT 0x00 /* 0x00-0x04 only used for set advertising
+ parameter command */
+#define BTM_BLE_CONNECT_DIR_EVT 0x01 /* Connectable directed advertising */
+#define BTM_BLE_DISCOVER_EVT 0x02 /* Scannable undirected advertising */
+#define BTM_BLE_NON_CONNECT_EVT 0x03 /* Non connectable undirected advertising */
+#define BTM_BLE_CONNECT_LO_DUTY_DIR_EVT 0x04 /* Connectable low duty
+ cycle directed advertising */
+ /* 0x00 - 0x05 can be received on adv event type */
#define BTM_BLE_SCAN_RSP_EVT 0x04
-#define BTM_BLE_SCAN_REQ_EVT 0x06
+#define BTM_BLE_SCAN_REQ_EVT 0x05
#define BTM_BLE_UNKNOWN_EVT 0xff
#define BTM_BLE_UNKNOWN_EVT 0xff
@@ -157,6 +163,58 @@
#define BTM_BLE_SIMULTANEOUS_HOST 0x01
#endif
+/* Appearance Values Reported with BTM_BLE_AD_TYPE_APPEARANCE */
+#define BTM_BLE_APPEARANCE_UKNOWN 0x0000
+#define BTM_BLE_APPEARANCE_GENERIC_PHONE 0x0040
+#define BTM_BLE_APPEARANCE_GENERIC_COMPUTER 0x0080
+#define BTM_BLE_APPEARANCE_GENERIC_WATCH 0x00C0
+#define BTM_BLE_APPEARANCE_SPORTS_WATCH 0x00C1
+#define BTM_BLE_APPEARANCE_GENERIC_CLOCK 0x0100
+#define BTM_BLE_APPEARANCE_GENERIC_DISPLAY 0x0140
+#define BTM_BLE_APPEARANCE_GENERIC_REMOTE 0x0180
+#define BTM_BLE_APPEARANCE_GENERIC_EYEGLASSES 0x01C0
+#define BTM_BLE_APPEARANCE_GENERIC_TAG 0x0200
+#define BTM_BLE_APPEARANCE_GENERIC_KEYRING 0x0240
+#define BTM_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280
+#define BTM_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0
+#define BTM_BLE_APPEARANCE_GENERIC_THERMOMETER 0x0300
+#define BTM_BLE_APPEARANCE_THERMOMETER_EAR 0x0301
+#define BTM_BLE_APPEARANCE_GENERIC_HEART_RATE 0x0340
+#define BTM_BLE_APPEARANCE_HEART_RATE_BELT 0x0341
+#define BTM_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380
+#define BTM_BLE_APPEARANCE_BLOOD_PRESSURE_ARM 0x0381
+#define BTM_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 0x0382
+#define BTM_BLE_APPEARANCE_GENERIC_HID 0x03C0
+#define BTM_BLE_APPEARANCE_HID_KEYBOARD 0x03C1
+#define BTM_BLE_APPEARANCE_HID_MOUSE 0x03C2
+#define BTM_BLE_APPEARANCE_HID_JOYSTICK 0x03C3
+#define BTM_BLE_APPEARANCE_HID_GAMEPAD 0x03C4
+#define BTM_BLE_APPEARANCE_HID_DIGITIZER_TABLET 0x03C5
+#define BTM_BLE_APPEARANCE_HID_CARD_READER 0x03C6
+#define BTM_BLE_APPEARANCE_HID_DIGITAL_PEN 0x03C7
+#define BTM_BLE_APPEARANCE_HID_BARCODE_SCANNER 0x03C8
+#define BTM_BLE_APPEARANCE_GENERIC_GLUCOSE 0x0400
+#define BTM_BLE_APPEARANCE_GENERIC_WALKING 0x0440
+#define BTM_BLE_APPEARANCE_WALKING_IN_SHOE 0x0441
+#define BTM_BLE_APPEARANCE_WALKING_ON_SHOE 0x0442
+#define BTM_BLE_APPEARANCE_WALKING_ON_HIP 0x0443
+#define BTM_BLE_APPEARANCE_GENERIC_CYCLING 0x0480
+#define BTM_BLE_APPEARANCE_CYCLING_COMPUTER 0x0481
+#define BTM_BLE_APPEARANCE_CYCLING_SPEED 0x0482
+#define BTM_BLE_APPEARANCE_CYCLING_CADENCE 0x0483
+#define BTM_BLE_APPEARANCE_CYCLING_POWER 0x0484
+#define BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485
+#define BTM_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40
+#define BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41
+#define BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42
+#define BTM_BLE_APPEARANCE_GENERIC_WEIGHT 0x0C80
+#define BTM_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440
+#define BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441
+#define BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442
+#define BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD 0x1443
+#define BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444
+
+
/* Structure returned with Rand/Encrypt complete callback */
typedef struct
{
@@ -179,39 +237,36 @@
#define BTM_BLE_POLICY_ALLOW_CONN 0x02 /* relevant to advertiser */
#define BTM_BLE_POLICY_WHITE_ALL 0x03 /* relevant to both */
-typedef struct
-{
- UINT8 adv_int_min;
- UINT8 adv_int_max;
- tBTM_BLE_CHNL_MAP chnl_map;
-
-}tBTM_BLE_ADV_PARAMS;
-
/* ADV data flag bit definition used for BTM_BLE_AD_TYPE_FLAG */
#define BTM_BLE_LIMIT_DISC_FLAG (0x01 << 0)
#define BTM_BLE_GEN_DISC_FLAG (0x01 << 1)
#define BTM_BLE_BREDR_NOT_SPT (0x01 << 2)
+/* 4.1 spec adv flag for simultaneous BR/EDR+LE connection support */
+#define BTM_BLE_DMT_CONTROLLER_SPT (0x01 << 3)
+#define BTM_BLE_DMT_HOST_SPT (0x01 << 4)
#define BTM_BLE_NON_LIMIT_DISC_FLAG (0x00 ) /* lowest bit unset */
#define BTM_BLE_ADV_FLAG_MASK (BTM_BLE_LIMIT_DISC_FLAG | BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG)
#define BTM_BLE_LIMIT_DISC_MASK (BTM_BLE_LIMIT_DISC_FLAG )
-#define BTM_BLE_AD_BIT_DEV_NAME (0x0001 << 0)
-#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_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_DEV_NAME (0x00000001 << 0)
+#define BTM_BLE_AD_BIT_FLAGS (0x00000001 << 1)
+#define BTM_BLE_AD_BIT_MANU (0x00000001 << 2)
+#define BTM_BLE_AD_BIT_TX_PWR (0x00000001 << 3)
+#define BTM_BLE_AD_BIT_INT_RANGE (0x00000001 << 5)
+#define BTM_BLE_AD_BIT_SERVICE (0x00000001 << 6)
+#define BTM_BLE_AD_BIT_SERVICE_SOL (0x00000001 << 7)
+#define BTM_BLE_AD_BIT_SERVICE_DATA (0x00000001 << 8)
+#define BTM_BLE_AD_BIT_SIGN_DATA (0x00000001 << 9)
+#define BTM_BLE_AD_BIT_SERVICE_128SOL (0x00000001 << 10)
+#define BTM_BLE_AD_BIT_APPEARANCE (0x00000001 << 11)
+#define BTM_BLE_AD_BIT_PUBLIC_ADDR (0x00000001 << 12)
+#define BTM_BLE_AD_BIT_RANDOM_ADDR (0x00000001 << 13)
+#define BTM_BLE_AD_BIT_SERVICE_32 (0x00000001 << 4)
+#define BTM_BLE_AD_BIT_SERVICE_32SOL (0x00000001 << 14)
+#define BTM_BLE_AD_BIT_PROPRIETARY (0x00000001 << 15)
+#define BTM_BLE_AD_BIT_SERVICE_128 (0x00000001 << 16) /*128-bit Service UUIDs*/
-#define BTM_BLE_AD_BIT_PROPRIETARY (0x0001 << 15)
-
-typedef UINT16 tBTM_BLE_AD_MASK;
+typedef UINT32 tBTM_BLE_AD_MASK;
#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 */
@@ -233,9 +288,22 @@
#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_ADV_INT 0x1a
+#define BTM_BLE_AD_TYPE_32SOL_SRV_UUID 0x1b
+#define BTM_BLE_AD_TYPE_32SERVICE_DATA 0x1c
+#define BTM_BLE_AD_TYPE_128SERVICE_DATA 0x1d
+
#define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */
typedef UINT8 tBTM_BLE_AD_TYPE;
+/* adv tx power level */
+#define BTM_BLE_ADV_TX_POWER_MIN 0 /* minimum tx power */
+#define BTM_BLE_ADV_TX_POWER_LOW 1 /* low tx power */
+#define BTM_BLE_ADV_TX_POWER_MID 2 /* middle tx power */
+#define BTM_BLE_ADV_TX_POWER_UPPER 3 /* upper tx power */
+#define BTM_BLE_ADV_TX_POWER_MAX 4 /* maximum tx power */
+typedef UINT8 tBTM_BLE_ADV_TX_POWER;
+
/* slave preferred connection interval range */
typedef struct
{
@@ -252,12 +320,35 @@
UINT16 *p_uuid;
}tBTM_BLE_SERVICE;
+/* 32 bits Service supported in the device */
+typedef struct
+{
+ UINT8 num_service;
+ BOOLEAN list_cmpl;
+ UINT32 *p_uuid;
+}tBTM_BLE_32SERVICE;
+
+/* 128 bits Service supported in the device */
+typedef struct
+{
+ BOOLEAN list_cmpl;
+ UINT8 uuid128[MAX_UUID_SIZE];
+}tBTM_BLE_128SERVICE;
+
typedef struct
{
UINT8 len;
UINT8 *p_val;
}tBTM_BLE_MANU;
+
+typedef struct
+{
+ tBT_UUID service_uuid;
+ UINT8 len;
+ UINT8 *p_val;
+}tBTM_BLE_SERVICE_DATA;
+
typedef struct
{
UINT8 adv_type;
@@ -273,14 +364,75 @@
typedef struct
{
- tBTM_BLE_MANU manu; /* manufactuer data */
tBTM_BLE_INT_RANGE int_range; /* slave prefered conn interval range */
- tBTM_BLE_SERVICE services; /* services */
+ tBTM_BLE_MANU *p_manu; /* manufactuer data */
+ tBTM_BLE_SERVICE *p_services; /* services */
+ tBTM_BLE_128SERVICE *p_services_128b; /* 128 bits service */
+ tBTM_BLE_32SERVICE *p_service_32b; /* 32 bits Service UUID */
+ tBTM_BLE_SERVICE *p_sol_services; /* 16 bits services Solicitation UUIDs */
+ tBTM_BLE_32SERVICE *p_sol_service_32b; /* List of 32 bit Service Solicitation UUIDs */
+ tBTM_BLE_128SERVICE *p_sol_service_128b; /* List of 128 bit Service Solicitation UUIDs */
+ tBTM_BLE_PROPRIETARY *p_proprietary;
+ tBTM_BLE_SERVICE_DATA *p_service_data; /* service data */
UINT16 appearance;
UINT8 flag;
- tBTM_BLE_PROPRIETARY *p_proprietary;
+ UINT8 tx_power;
}tBTM_BLE_ADV_DATA;
+#ifndef BTM_BLE_MULTI_ADV_MAX
+#define BTM_BLE_MULTI_ADV_MAX 4
+#endif
+
+#define BTM_BLE_MULTI_ADV_INVALID 0
+
+#define BTM_BLE_MULTI_ADV_ENB_EVT 1
+#define BTM_BLE_MULTI_ADV_DISABLE_EVT 2
+#define BTM_BLE_MULTI_ADV_PARAM_EVT 3
+#define BTM_BLE_MULTI_ADV_DATA_EVT 4
+typedef UINT8 tBTM_BLE_MULTI_ADV_EVT;
+
+#define BTM_BLE_MULTI_ADV_DEFAULT_STD 0
+
+typedef struct
+{
+ UINT16 adv_int_min;
+ UINT16 adv_int_max;
+ UINT8 adv_type;
+ tBTM_BLE_ADV_CHNL_MAP channel_map;
+ tBTM_BLE_AFP adv_filter_policy;
+ tBTM_BLE_ADV_TX_POWER tx_power;
+}tBTM_BLE_ADV_PARAMS;
+
+typedef struct
+{
+ UINT8 sub_code[BTM_BLE_MULTI_ADV_MAX];
+ UINT8 inst_id[BTM_BLE_MULTI_ADV_MAX];
+ UINT8 pending_idx;
+ UINT8 next_idx;
+}tBTM_BLE_MULTI_ADV_OPQ;
+
+typedef void (tBTM_BLE_MULTI_ADV_CBACK)(tBTM_BLE_MULTI_ADV_EVT evt, UINT8 inst_id,
+ void *p_ref, tBTM_STATUS status);
+
+typedef struct
+{
+ UINT8 inst_id;
+ UINT8 adv_evt;
+ BD_ADDR rpa;
+ TIMER_LIST_ENT raddr_timer_ent;
+ void *p_rpa_cback;
+ tBTM_BLE_MULTI_ADV_CBACK *p_cback;
+ void *p_ref;
+}tBTM_BLE_MULTI_ADV_INST;
+
+typedef struct
+{
+ tBTM_BLE_MULTI_ADV_INST adv_inst[BTM_BLE_MULTI_ADV_MAX];
+ tBTM_BLE_MULTI_ADV_OPQ op_q;
+ UINT8 adv_inst_max; /* max adv instance supported in controller */
+}tBTM_BLE_MULTI_ADV_CB;
+
+
/* These are the fields returned in each device adv packet. It
** is returned in the results callback if registered.
*/
@@ -434,19 +586,6 @@
/*******************************************************************************
**
-** Function BTM_BleReset
-**
-** Description This function is called to reset ULP controller.
-**
-** Parameters None.
-**
-** Returns void
-**
-*******************************************************************************/
-BTM_API extern void BTM_BleReset(void);
-
-/*******************************************************************************
-**
** Function BTM_BleObserve
**
** Description This procedure keep the device listening for advertising
@@ -697,6 +836,7 @@
**
*******************************************************************************/
BTM_API extern void BTM_BleSetConnScanParams (UINT16 scan_interval, UINT16 scan_window);
+BTM_API extern void btm_ble_vendor_capability_init(void);
/*******************************************************************************
**
@@ -866,17 +1006,6 @@
/*******************************************************************************
**
-** Function BTM_IsBleLink
-**
-** Description This function is to check the link type is BLE or BR/EDR.
-**
-** Returns TRUE if BLE link; FALSE if BR/EDR.
-**
-*******************************************************************************/
-BTM_API extern BOOLEAN BTM_IsBleLink (BD_ADDR bd_addr);
-
-/*******************************************************************************
-**
** Function BTM_UseLeLink
**
** Description This function is to select the underneath physical link to use.
@@ -886,6 +1015,88 @@
*******************************************************************************/
BTM_API extern BOOLEAN BTM_UseLeLink (BD_ADDR bd_addr);
+/*******************************************************************************
+**
+** Function BTM_BleStackEnable
+**
+** Description Enable/Disable BLE functionality on stack regarless controller
+** capability.
+**
+** Parameters: enable: TRUE to enable, FALSE to disable.
+**
+** Returns TRUE if added OK, else FALSE
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleStackEnable (BOOLEAN enable);
+
+/*******************************************************************************/
+/* Multi ADV API */
+/*******************************************************************************
+**
+** Function BTM_BleEnableAdvInstance
+**
+** Description This function enable a Multi-ADV instance with the specified
+** adv parameters
+**
+** Parameters p_params: pointer to the adv parameter structure, set as default
+** adv parameter when the instance is enabled.
+** p_cback: callback function for the adv instance.
+** p_ref: reference data attach to the adv instance to be enabled.
+**
+** Returns status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
+ tBTM_BLE_MULTI_ADV_CBACK *p_cback,
+ void *p_ref);
+
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvInstParam
+**
+** Description This function update a Multi-ADV instance with the specififed
+** adv parameters.
+**
+** Parameters inst_id: adv instance ID
+** p_params: pointer to the adv parameter structure.
+**
+** Returns status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params);
+
+/*******************************************************************************
+**
+** Function BTM_BleCfgAdvInstData
+**
+** Description This function configure a Multi-ADV instance with the specified
+** adv data or scan response data.
+**
+** Parameters inst_id: adv instance ID
+** is_scan_rsp: is this scacn response, if no set as adv data.
+** data_mask: adv data mask.
+** p_data: pointer to the adv data structure.
+**
+** Returns status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+ tBTM_BLE_AD_MASK data_mask,
+ tBTM_BLE_ADV_DATA *p_data);
+
+/*******************************************************************************
+**
+** Function BTM_BleDisableAdvInstance
+**
+** Description This function disable a Multi-ADV instance.
+**
+** Parameters inst_id: adv instance ID
+**
+** Returns status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id);
+
#ifdef __cplusplus
}
#endif
diff --git a/stack/include/btu.h b/stack/include/btu.h
index 4f0e162..805fea7 100644
--- a/stack/include/btu.h
+++ b/stack/include/btu.h
@@ -153,10 +153,15 @@
#define BTU_TTYPE_ATT_WAIT_FOR_APP_RSP 104
#define BTU_TTYPE_ATT_WAIT_FOR_IND_ACK 105
-#define BTU_TTYPE_UCD_TO 106
+#define BTU_TTYPE_L2CAP_END_CONN_UPD 106
-/* BTU timer event for TBFC */
-#define BTU_TTYPE_TBFC_RESUME 107
+#define BTU_TTYPE_BLE_GAP_FAST_ADV 107
+#define BTU_TTYPE_BLE_OBSERVE 108
+
+
+#define BTU_TTYPE_UCD_TO 109
+
+
/* Define the BTU_TASK APPL events
*/
diff --git a/stack/include/gap_api.h b/stack/include/gap_api.h
index a17510f..645323d 100644
--- a/stack/include/gap_api.h
+++ b/stack/include/gap_api.h
@@ -225,6 +225,9 @@
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);
+#if BLE_PRIVACY_SPT == TRUE
+typedef void (tGAP_BLE_PRIVACY_CBACK)(BOOLEAN status, BD_ADDR addr, BOOLEAN privacy_enabled);
+#endif
/*****************************************************************************
** External Function Declarations
@@ -440,10 +443,16 @@
**
** Description This function is called to initiate 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)
+**
** 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[]);
+GAP_API extern UINT8 GAP_Bond (BD_ADDR bd_addr, UINT8 pin_len,
+ UINT8 *p_pin, UINT32 trusted_mask[]);
/*******************************************************************************
**
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index f3df8b7..9da7d9c 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -25,44 +25,47 @@
** Constants
*****************************************************************************/
/* Success code and error codes */
-#define GATT_SUCCESS 0x0000
-#define GATT_INVALID_HANDLE 0x0001
-#define GATT_READ_NOT_PERMIT 0x0002
-#define GATT_WRITE_NOT_PERMIT 0x0003
-#define GATT_INVALID_PDU 0x0004
-#define GATT_INSUF_AUTHENTICATION 0x0005
-#define GATT_REQ_NOT_SUPPORTED 0x0006
-#define GATT_INVALID_OFFSET 0x0007
-#define GATT_INSUF_AUTHORIZATION 0x0008
-#define GATT_PREPARE_Q_FULL 0x0009
-#define GATT_NOT_FOUND 0x000a
-#define GATT_NOT_LONG 0x000b
-#define GATT_INSUF_KEY_SIZE 0x000c
-#define GATT_INVALID_ATTR_LEN 0x000d
-#define GATT_ERR_UNLIKELY 0x000e
-#define GATT_INSUF_ENCRYPTION 0x000f
-#define GATT_UNSUPPORT_GRP_TYPE 0x0010
-#define GATT_INSUF_RESOURCE 0x0011
+#define GATT_SUCCESS 0x00
+#define GATT_INVALID_HANDLE 0x01
+#define GATT_READ_NOT_PERMIT 0x02
+#define GATT_WRITE_NOT_PERMIT 0x03
+#define GATT_INVALID_PDU 0x04
+#define GATT_INSUF_AUTHENTICATION 0x05
+#define GATT_REQ_NOT_SUPPORTED 0x06
+#define GATT_INVALID_OFFSET 0x07
+#define GATT_INSUF_AUTHORIZATION 0x08
+#define GATT_PREPARE_Q_FULL 0x09
+#define GATT_NOT_FOUND 0x0a
+#define GATT_NOT_LONG 0x0b
+#define GATT_INSUF_KEY_SIZE 0x0c
+#define GATT_INVALID_ATTR_LEN 0x0d
+#define GATT_ERR_UNLIKELY 0x0e
+#define GATT_INSUF_ENCRYPTION 0x0f
+#define GATT_UNSUPPORT_GRP_TYPE 0x10
+#define GATT_INSUF_RESOURCE 0x11
-#define GATT_ILLEGAL_PARAMETER 0x0087
-#define GATT_NO_RESOURCES 0x0080
-#define GATT_INTERNAL_ERROR 0x0081
-#define GATT_WRONG_STATE 0x0082
-#define GATT_DB_FULL 0x0083
-#define GATT_BUSY 0x0084
-#define GATT_ERROR 0x0085
-#define GATT_CMD_STARTED 0x0086
-#define GATT_PENDING 0x0088
-#define GATT_AUTH_FAIL 0x0089
-#define GATT_MORE 0x008a
-#define GATT_INVALID_CFG 0x008b
-#define GATT_SERVICE_STARTED 0x008c
+#define GATT_ILLEGAL_PARAMETER 0x87
+#define GATT_NO_RESOURCES 0x80
+#define GATT_INTERNAL_ERROR 0x81
+#define GATT_WRONG_STATE 0x82
+#define GATT_DB_FULL 0x83
+#define GATT_BUSY 0x84
+#define GATT_ERROR 0x85
+#define GATT_CMD_STARTED 0x86
+#define GATT_PENDING 0x88
+#define GATT_AUTH_FAIL 0x89
+#define GATT_MORE 0x8a
+#define GATT_INVALID_CFG 0x8b
+#define GATT_SERVICE_STARTED 0x8c
#define GATT_ENCRYPED_MITM GATT_SUCCESS
-#define GATT_ENCRYPED_NO_MITM 0x008d
-#define GATT_NOT_ENCRYPTED 0x008e
+#define GATT_ENCRYPED_NO_MITM 0x8d
+#define GATT_NOT_ENCRYPTED 0x8e
-
+ /* 0xE0 ~ 0xFC reserved for future use */
+#define GATT_CCC_CFG_ERR 0xFD /* Client Characteristic Configuration Descriptor Improperly Configured */
+#define GATT_PRC_IN_PROGRESS 0xFE /* Procedure Already in progress */
+#define GATT_OUT_OF_RANGE 0xFF /* Attribute value out of range */
typedef UINT8 tGATT_STATUS;
@@ -325,12 +328,9 @@
} tGATTS_RSP;
/* Transports for the primary service */
-enum
-{
- GATT_TRANSPORT_LE,
- GATT_TRANSPORT_BR_EDR,
- GATT_TRANSPORT_LE_BR_EDR
-};
+#define GATT_TRANSPORT_LE BT_TRANSPORT_LE
+#define GATT_TRANSPORT_BR_EDR BT_TRANSPORT_BR_EDR
+#define GATT_TRANSPORT_LE_BR_EDR (BT_TRANSPORT_LE|BT_TRANSPORT_BR_EDR)
typedef UINT8 tGATT_TRANSPORT;
#define GATT_PREP_WRITE_CANCEL 0x00
@@ -548,26 +548,30 @@
typedef UINT8 tGATT_IF;
-#define GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP 0 /* start a idle timer for this duration when no application
- need to use the link */
+#define GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP 0 /* start a idle timer for this duration
+ when no application need to use the link */
#define GATT_LINK_NO_IDLE_TIMEOUT 0xFFFF
#define GATT_INVALID_ACL_HANDLE 0xFFFF
/* discover result callback function */
-typedef void (tGATT_DISC_RES_CB) (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
+typedef void (tGATT_DISC_RES_CB) (UINT16 conn_id, tGATT_DISC_TYPE disc_type,
+ tGATT_DISC_RES *p_data);
/* discover complete callback function */
typedef void (tGATT_DISC_CMPL_CB) (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
/* Define a callback function for when read/write/disc/config operation is completed. */
-typedef void (tGATT_CMPL_CBACK) (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
+typedef void (tGATT_CMPL_CBACK) (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+ tGATT_CL_COMPLETE *p_data);
/* Define a callback function when an initialized connection is established. */
-typedef void (tGATT_CONN_CBACK) (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+typedef void (tGATT_CONN_CBACK) (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected,
+ tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport);
/* attribute request callback for ATT server */
-typedef void (tGATT_REQ_CBACK )(UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA *p_data);
+typedef void (tGATT_REQ_CBACK )(UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type,
+ tGATTS_DATA *p_data);
/* Define a callback function when encryption is established. */
typedef void (tGATT_ENC_CMPL_CB)(tGATT_IF gatt_if, BD_ADDR bda);
@@ -639,7 +643,8 @@
/* Attibute server handle ranges NV storage callback functions
*/
typedef void (tGATTS_NV_SAVE_CBACK)(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
-typedef BOOLEAN (tGATTS_NV_SRV_CHG_CBACK)(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp);
+typedef BOOLEAN (tGATTS_NV_SRV_CHG_CBACK)(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req,
+ tGATTS_SRV_CHG_RSP *p_rsp);
typedef struct
{
@@ -801,7 +806,8 @@
** Returns TRUE if operation succeed, FALSE if handle block was not found.
**
*******************************************************************************/
- GATT_API extern BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
+ GATT_API extern BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
+ UINT16 svc_inst);
/*******************************************************************************
**
@@ -998,11 +1004,13 @@
**
** Parameter bd_addr: target device bd address.
** idle_tout: timeout value in seconds.
+** transport: trasnport option.
**
** Returns void
**
*******************************************************************************/
- GATT_API extern void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout);
+ GATT_API extern void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout,
+ tGATT_TRANSPORT transport);
/*******************************************************************************
@@ -1058,11 +1066,13 @@
** Parameters gatt_if: applicaiton interface
** bd_addr: peer device address.
** is_direct: is a direct conenection or a background auto connection
+** transport : Physical transport for GATT connection (BR/EDR or LE)
**
** Returns TRUE if connection started; FALSE if connection start failure.
**
*******************************************************************************/
- GATT_API extern BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct);
+ GATT_API extern BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr,
+ BOOLEAN is_direct, tBT_TRANSPORT transport);
/*******************************************************************************
@@ -1080,7 +1090,8 @@
** Returns TRUE if connection started; FALSE if connection start failure.
**
*******************************************************************************/
- GATT_API extern BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct);
+ GATT_API extern BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr,
+ BOOLEAN is_direct);
/*******************************************************************************
**
@@ -1108,11 +1119,13 @@
** Parameters conn_id: connection id (input)
** p_gatt_if: applicaiton interface (output)
** bd_addr: peer device address. (output)
+** transport : physical transport of the GATT connection (BR/EDR or LE)
**
** Returns TRUE the ligical link information is found for conn_id
**
*******************************************************************************/
- GATT_API extern BOOLEAN GATT_GetConnectionInfor(UINT16 conn_id, tGATT_IF *p_gatt_if, BD_ADDR bd_addr);
+ GATT_API extern BOOLEAN GATT_GetConnectionInfor(UINT16 conn_id, tGATT_IF *p_gatt_if,
+ BD_ADDR bd_addr, tBT_TRANSPORT *p_transport);
/*******************************************************************************
@@ -1125,11 +1138,13 @@
** Parameters gatt_if: applicaiton interface (input)
** bd_addr: peer device address. (input)
** p_conn_id: connection id (output)
+** transport : physical transport of the GATT connection (BR/EDR or LE)
**
** Returns TRUE the ligical link is connected
**
*******************************************************************************/
- GATT_API extern BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id);
+ GATT_API extern BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr,
+ UINT16 *p_conn_id, tBT_TRANSPORT transport);
/*******************************************************************************
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index ad31d52..4c0b604 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright (C) 1999-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -231,11 +231,11 @@
#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_SET_RESERVED_LT_ADDR (0x0074 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_DELETE_RESERVED_LT_ADDR (0x0075 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CLB_DATA (0x0076 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SYNC_TRAIN_PARAM (0x0077 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SYNC_TRAIN_PARAM (0x0078 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_CONT_BASEBAND_CMDS_FIRST HCI_SET_EVENT_MASK
#define HCI_CONT_BASEBAND_CMDS_LAST HCI_READ_SYNC_TRAIN_PARAM
@@ -323,12 +323,32 @@
#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)
+ /*0x001D, 0x001E and 0x001F are reserved*/
+
+#define HCI_BLE_RC_PARAM_REQ_REPLY (0x0020 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_RC_PARAM_REQ_NEG_REPLY (0x0021 | 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)
+/* LE Get Vendor Capabilities Command OCF */
+#define HCI_BLE_VENDOR_CAP_OCF (0x0153 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* Multi adv OCF */
+#define HCI_BLE_MULTI_ADV_OCF (0x0154 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* subcode for multi adv feature */
+#define BTM_BLE_MULTI_ADV_SET_PARAM 0x01
+#define BTM_BLE_MULTI_ADV_WRITE_ADV_DATA 0x02
+#define BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA 0x03
+#define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR 0x04
+#define BTM_BLE_MULTI_ADV_ENB 0x05
+
+/* multi adv VSE subcode */
+#define HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG 0x55 /* multi adv instance state change */
/* LE supported states definition */
#define HCI_LE_ADV_STATE 0x00000001
@@ -344,6 +364,214 @@
#define HCI_LE_SCAN_SL_STATE 0x00000400
#define HCI_LE_INIT_MA_STATE 0x00000800
+/* LE Supported States */
+/* Non Connectable Adv state is supported. 0x0000000000000001 */
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_MASK 0x01
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_OFF 0
+#define HCI_LE_STATES_NON_CONN_ADV_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_NON_CONN_ADV_OFF] & HCI_SUPP_LE_STATES_NON_CONN_ADV_MASK)
+
+/*Scanneable Connectable Adv state is supported. 0x0000000000000002 */
+#define HCI_SUPP_LE_STATES_SCAN_ADV_MASK 0x02
+#define HCI_SUPP_LE_STATESSCAN_ADV_OFF 0
+#define HCI_LE_STATES_SCAN_ADV_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATESSCAN_ADV_OFF] & HCI_SUPP_LE_STATES_SCAN_ADV_MASK)
+
+/* Connectable Adv state is supported. 0x0000000000000004 */
+#define HCI_SUPP_LE_STATES_CONN_ADV_MASK 0x04
+#define HCI_SUPP_LE_STATES_CONN_ADV_OFF 0
+#define HCI_LE_STATES_CONN_ADV_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_CONN_ADV_OFF] & HCI_SUPP_LE_STATES_CONN_ADV_MASK)
+
+/* Hi duty Cycle Directed Adv state is supported. 0x0000000000000008 */
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASK 0x08
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_OFF 0
+#define HCI_LE_STATES_HI_DUTY_DIR_ADV_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_OFF] & HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASK)
+
+/* Passive Scan state is supported. 0x0000000000000010 */
+#define HCI_SUPP_LE_STATES_PASS_SCAN_MASK 0x10
+#define HCI_SUPP_LE_STATES_PASS_SCAN_OFF 0
+#define HCI_LE_STATES_PASS_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_PASS_SCAN_OFF] & HCI_SUPP_LE_STATES_PASS_SCAN_MASK)
+
+/* Active Scan state is supported. 0x0000000000000020 */
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASK 0x20
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_OFF 0
+#define HCI_LE_STATES_ACTIVE_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_ACTIVE_SCAN_OFF] & HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASK)
+
+/* Initiating state is supported. 0x0000000000000040 (or connection state in master role is also supported) */
+#define HCI_SUPP_LE_STATES_INIT_MASK 0x40
+#define HCI_SUPP_LE_STATES_INIT_OFF 0
+#define HCI_LE_STATES_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_INIT_OFF] & HCI_SUPP_LE_STATES_INIT_MASK)
+
+/*connection state in slave role is also supported. 0x0000000000000080 */
+#define HCI_SUPP_LE_STATES_SLAVE_MASK 0x80
+#define HCI_SUPP_LE_STATES_SLAVE_OFF 0
+#define HCI_LE_STATES_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_SLAVE_OFF] & HCI_SUPP_LE_STATES_SLAVE_MASK)
+
+/* Non Connectable Adv state and Passive Scanning State combination is supported. 0x0000000000000100 */
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_MASK 0x01
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_OFF 1
+#define HCI_LE_STATES_NON_CONN_ADV_PASS_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_OFF] & HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_MASK)
+
+/*Scannable Adv state and Passive Scanning State combination is supported. 0x0000000000000200 */
+#define HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_MASK 0x02
+#define HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_OFF 1
+#define HCI_LE_STATES_SCAN_ADV_PASS_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_OFF] & HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_MASK)
+
+/*Connectable Adv state and Passive Scanning State combination is supported. 0x0000000000000400 */
+#define HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_MASK 0x04
+#define HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_OFF 1
+#define HCI_LE_STATES_CONN_ADV_PASS_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_OFF] & HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_MASK)
+
+/*High Duty Cycl Directed ADv and Passive Scanning State combination is supported. 0x0000000000000800 */
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_MASK 0x08
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_OFF 1
+#define HCI_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_MASK] & HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_OFF)
+
+/*Non Connectable Adv state and Passive Scanning State combination is supported. 0x0000000000001000 */
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_MASK 0x10
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_OFF 1
+#define HCI_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_OFF] & HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_MASK)
+
+/*Scannable Adv state and Active Scanning State combination is supported. 0x0000000000002000 */
+#define HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_MASK 0x20
+#define HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_OFF 1
+#define HCI_LE_STATES_SCAN_ADV_ACTIVE_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_OFF] & HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_MASK)
+
+/*Connectable Adv state and Active Scanning State combination is supported. 0x0000000000004000 */
+#define HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_MASK 0x40
+#define HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_OFF 1
+#define HCI_LE_STATES_CONN_ADV_ACTIVE_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_OFF] & HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_MASK)
+
+/*High Duty Cycl Directed ADv and ACtive Scanning State combination is supported. 0x0000000000008000 */
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_MASK 0x80
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_OFF 1
+#define HCI_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_MASK] & HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_OFF)
+
+/*Non-Connectable Adv state and Initiating State combination is supported. 0x0000000000010000 */
+#define HCI_SUPP_LE_STATES_NON_CONN_INIT_MASK 0x01
+#define HCI_SUPP_LE_STATES_NON_CONN_INIT_OFF 2
+#define HCI_LE_STATES_NON_CONN_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_NON_CONN_INIT_OFF] & HCI_SUPP_LE_STATES_NON_CONN_INIT_MASK)
+
+/* Scannable Adv state and Initiating State combination is supported. 0x0000000000020000 */
+#define HCI_SUPP_LE_STATES_SCAN_ADV_INIT_MASK 0x02
+#define HCI_SUPP_LE_STATES_SCAN_ADV_INIT_OFF 2
+#define HCI_LE_STATES_SCAN_ADV_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_SCAN_ADV_INIT_OFF] & HCI_SUPP_LE_STATES_SCAN_ADV_INIT_MASK)
+
+/* Non-Connectable Adv state and Master Role combination is supported. 0x0000000000040000 */
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_MASK 0x04
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_OFF 2
+#define HCI_LE_STATES_NON_CONN_ADV_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_OFF] & HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_MASK)
+
+/*Scannable Adv state and Master Role combination is supported. 0x0000000000040000 */
+#define HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_MASK 0x08
+#define HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_OFF 2
+#define HCI_LE_STATES_SCAN_ADV_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_OFF] & HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_MASK)
+
+/* Non-Connectable Adv and Slave Role combination is supported. 0x000000000100000 */
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_MASK 0x10
+#define HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_OFF 2
+#define HCI_LE_STATES_NON_CONN_ADV_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_OFF] & HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_MASK)
+
+/*Scannable Adv and Slave Role combination is supported. 0x000000000200000 */
+#define HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_MASK 0x20
+#define HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_OFF 2
+#define HCI_LE_STATES_SCAN_ADV_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_OFF] & HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_MASK)
+
+/*Passive Scan and Initiating State combination is supported. 0x000000000400000 */
+#define HCI_SUPP_LE_STATES_PASS_SCAN_INIT_MASK 0x40
+#define HCI_SUPP_LE_STATES_PASS_SCAN_INIT_OFF 2
+#define HCI_LE_STATES_PASS_SCAN_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_PASS_SCAN_INIT_OFF] & HCI_SUPP_LE_STATES_PASS_SCAN_INIT_MASK)
+
+/*Active Scan and Initiating State combination is supported. 0x000000000800000 */
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_MASK 0x80
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_OFF 2
+#define HCI_LE_STATES_ACTIVE_SCAN_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_OFF] & HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_MASK)
+
+/*Passive Scan and Master Role combination is supported. 0x000000001000000 */
+#define HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_MASK 0x01
+#define HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_OFF 3
+#define HCI_LE_STATES_PASS_SCAN_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_OFF] & HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_MASK)
+
+/*Active Scan and Master Role combination is supported. 0x000000002000000 */
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_MASK 0x02
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_OFF 3
+#define HCI_LE_STATES_ACTIVE_SCAN_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_OFF] & HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_MASK)
+
+/*Passive Scan and Slave Role combination is supported. 0x000000004000000 */
+#define HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_MASK 0x04
+#define HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_OFF 3
+#define HCI_LE_STATES_PASS_SCAN_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_OFF] & HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_MASK)
+
+/*Active Scan and Slave Role combination is supported. 0x000000008000000 */
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_MASK 0x08
+#define HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_OFF 3
+#define HCI_LE_STATES_ACTIVE_SCAN_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_OFF] & HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_MASK)
+
+/*Link Layer Topology Added States Combo */
+/*Initiating State and Master Role combination supported.
+ Master Role and Master Role combination is also supported. 0x0000000010000000 */
+#define HCI_SUPP_LE_STATES_INIT_MASTER_MASK 0x10
+#define HCI_SUPP_LE_STATES_INIT_MASTER_OFF 3
+#define HCI_LE_STATES_INIT_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_INIT_MASTER_OFF] & HCI_SUPP_LE_STATES_INIT_MASTER_MASK)
+
+/* Connectable Advertising State and Initiating State combination supported. 0x0000000100000000 */
+#define HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK 0x01
+#define HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF 4
+#define HCI_LE_STATES_CONN_ADV_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF] & HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK)
+
+/* High Duty Cycle Directed Advertising State and Initiating State combination supported. */
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_MASK 0x02
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_OFF 4
+#define HCI_LE_STATES_HI_DUTY_DIR_ADV_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_OFF] & HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_MASK)
+
+/* Low Duty Cycle Directed Advertising State and Initiating State combination supported.*/
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_MASK 0x04
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_OFF 4
+#define HCI_LE_STATES_LO_DUTY_DIR_ADV_INIT_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_OFF] & HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_MASK)
+
+/* Connectable Advertising State and Master Role combination supported.*/
+#define HCI_SUPP_LE_STATES_CONN_ADV_MASTER_MASK 0x08
+#define HCI_SUPP_LE_STATES_CONN_ADV_MASTER_OFF 4
+#define HCI_LE_STATES_CONN_ADV_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_CONN_ADV_MASTER_OFF] & HCI_SUPP_LE_STATES_CONN_ADV_MASTER_MASK)
+
+/* High Duty Cycle Directed Advertising State and Master Role combination supported.*/
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_MASK 0x10
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_OFF 4
+#define HCI_LE_STATES_HI_DUTY_DIR_ADV_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_OFF] & HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_MASK)
+
+/* Low Duty Cycle Directed Advertising State and Master Role combination supported.*/
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_MASK 0x20
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_OFF 4
+#define HCI_LE_STATES_LO_DUTY_DIR_ADV_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_OFF] & HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_MASK)
+
+/* Connectable Advertising State and Slave Role combination supported. */
+#define HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK 0x40
+#define HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF 4
+#define HCI_LE_STATES_CONN_ADV_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF] & HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK)
+
+/* High Duty Cycle Directed Advertising State and slave Role combination supported.*/
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_MASK 0x80
+#define HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_OFF 4
+#define HCI_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_OFF] & HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_MASK)
+
+/* Low Duty Cycle Directed Advertising State and slave Role combination supported.*/
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_MASK 0x01
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_OFF 5
+#define HCI_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_OFF] & HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_MASK)
+
+/* Initiating State and Slave Role combination supported.
+ Master Role and Slave Role combination also supported.
+ */
+#define HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK 0x02
+#define HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF 5
+#define HCI_LE_STATES_INIT_MASTER_SLAVE_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF] & HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK)
+
+#define HCI_BRCM_ENABLE_WBS_MODIFIED (0x0102 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* ConnectionLess Broadcast Stream VSC */
+#define HCI_BRCM_SET_CLB_STREAM (0x0111 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_RECEIVE_CLB_STREAM (0x0112 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_WRITE_CLB_STREAM_DATA (0x0113 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_CLB_STREAM_FLUSH (0x0114 | HCI_GRP_VENDOR_SPECIFIC)
+
/*
** Definitions for HCI Events
*/
@@ -411,6 +639,7 @@
#define HCI_NUM_COMPL_DATA_BLOCKS_EVT 0x48
#define HCI_SHORT_RANGE_MODE_COMPLETE_EVT 0x4C
#define HCI_AMP_STATUS_CHANGE_EVT 0x4D
+#define HCI_SET_TRIGGERED_CLOCK_CAPTURE_EVT 0x4E
/* ULP HCI Event */
#define HCI_BLE_EVENT 0x03E
@@ -420,16 +649,11 @@
#define HCI_BLE_LL_CONN_PARAM_UPD_EVT 0x03
#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04
#define HCI_BLE_LTK_REQ_EVT 0x05
+#define HCI_BLE_RC_PARAM_REQ_EVT 0x06
-/* 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
+/* Definitions for LE Channel Map */
+#define HCI_BLE_CHNL_MAP_SIZE 5
+
#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT
#define HCI_EVENT_RSP_LAST HCI_CLB_CHANNEL_CHANGE_EVT
@@ -439,6 +663,9 @@
because conflict w/ TCI_EVT and per
specification compliant */
+/* the event mask for BLE event mask */
+#define HCI_BLE_EVENT_MASK_DEF "\x00\x00\x00\x00\x00\x00\x00\x3f"
+
/*
@@ -1583,6 +1810,10 @@
#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)
+#define HCI_EXT_FEATURE_SC_HOST_MASK 0x08
+#define HCI_EXT_FEATURE_SC_HOST_OFF 0
+#define HCI_SC_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SC_HOST_OFF] & HCI_EXT_FEATURE_SC_HOST_MASK)
+
/*
** LMP features encoding - page 2
*/
@@ -1606,19 +1837,43 @@
#define HCI_EXT_FEATURE_INQ_RESP_NOTIF_OFF 0
#define HCI_INQ_RESP_NOTIF_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_INQ_RESP_NOTIF_OFF] & HCI_EXT_FEATURE_INQ_RESP_NOTIF_MASK)
+#define HCI_EXT_FEATURE_SC_CTRLR_MASK 0x01
+#define HCI_EXT_FEATURE_SC_CTRLR_OFF 1
+#define HCI_SC_CTRLR_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SC_CTRLR_OFF] & HCI_EXT_FEATURE_SC_CTRLR_MASK)
+
+#define HCI_EXT_FEATURE_PING_MASK 0x02
+#define HCI_EXT_FEATURE_PING_OFF 1
+#define HCI_PING_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_PING_OFF] & HCI_EXT_FEATURE_PING_MASK)
+
/*
** LE features encoding - page 0 (the only page for now)
*/
+/* LE Encryption */
#define HCI_LE_FEATURE_LE_ENCRYPTION_MASK 0x01
#define HCI_LE_FEATURE_LE_ENCRYPTION_OFF 0
#define HCI_LE_ENCRYPTION_SUPPORTED(x) ((x)[HCI_LE_FEATURE_LE_ENCRYPTION_OFF] & HCI_LE_FEATURE_LE_ENCRYPTION_MASK)
+/* Connection Parameters Request Procedure */
+#define HCI_LE_FEATURE_CONN_PARAM_REQ_MASK 0x02
+#define HCI_LE_FEATURE_CONN_PARAM_REQ_OFF 0
+#define HCI_LE_CONN_PARAM_REQ_SUPPORTED(x) ((x)[HCI_LE_FEATURE_CONN_PARAM_REQ_OFF] & HCI_LE_FEATURE_CONN_PARAM_REQ_MASK)
+
+/* Extended Reject Indication */
+#define HCI_LE_FEATURE_EXT_REJ_IND_MASK 0x04
+#define HCI_LE_FEATURE_EXT_REJ_IND_OFF 0
+#define HCI_LE_EXT_REJ_IND_SUPPORTED(x) ((x)[HCI_LE_FEATURE_EXT_REJ_IND_OFF] & HCI_LE_FEATURE_EXT_REJ_IND_MASK)
+
+/* Slave-initiated Features Exchange */
+#define HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_MASK 0x08
+#define HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF 0
+#define HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(x) ((x)[HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF] & HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_MASK)
/*
** Local Supported Commands encoding
*/
#define HCI_NUM_SUPP_COMMANDS_BYTES 64
+/* Supported Commands Byte 0 */
#define HCI_SUPP_COMMANDS_INQUIRY_MASK 0x01
#define HCI_SUPP_COMMANDS_INQUIRY_OFF 0
#define HCI_INQUIRY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_INQUIRY_OFF] & HCI_SUPP_COMMANDS_INQUIRY_MASK)
@@ -2398,8 +2653,42 @@
#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)
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY_MASK 0x02
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY_OFF 32
+#define HCI_REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY_MASK)
+#define HCI_SUPP_COMMANDS_READ_SECURE_CONNS_SUPPORT_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_SECURE_CONNS_SUPPORT_OFF 32
+#define HCI_READ_SECURE_CONNS_SUPPORT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SECURE_CONNS_SUPPORT_OFF] & HCI_SUPP_COMMANDS_READ_SECURE_CONNS_SUPPORT_MASK)
+#define HCI_SUPP_COMMANDS_WRITE_SECURE_CONNS_SUPPORT_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_SECURE_CONNS_SUPPORT_OFF 32
+#define HCI_WRITE_SECURE_CONNS_SUPPORT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SECURE_CONNS_SUPPORT_OFF] & HCI_SUPP_COMMANDS_WRITE_SECURE_CONNS_SUPPORT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AUTHENT_PAYLOAD_TOUT_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_AUTHENT_PAYLOAD_TOUT_OFF 32
+#define HCI_READ_AUTHENT_PAYLOAD_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AUTHENT_PAYLOAD_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_AUTHENT_PAYLOAD_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_AUTHENT_PAYLOAD_TOUT_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_AUTHENT_PAYLOAD_TOUT_OFF 32
+#define HCI_WRITE_AUTHENT_PAYLOAD_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_AUTHENT_PAYLOAD_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_AUTHENT_PAYLOAD_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_OOB_EXTENDED_DATA_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_LOCAL_OOB_EXTENDED_DATA_OFF 32
+#define HCI_READ_LOCAL_OOB_EXTENDED_DATA_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_OOB_EXTENDED_DATA_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_OOB_EXTENDED_DATA_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SECURE_CONNECTIONS_TEST_MODE_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_SECURE_CONNECTIONS_TEST_MODE_OFF 32
+#define HCI_WRITE_SECURE_CONNECTIONS_TEST_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SECURE_CONNECTIONS_TEST_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_SECURE_CONNECTIONS_TEST_MODE_MASK)
+
+/* supported LE remote control connection parameter request reply */
+#define HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_RPY_MASK 0x10
+#define HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_RPY_OFF 33
+#define HCI_LE_RC_CONN_PARAM_UPD_RPY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_RPY_OFF] & HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_RPY_MASK)
+
+#define HCI_SUPP_COMMANDS_RLE_RC_CONN_PARAM_UPD_NEG_RPY_MASK 0x20
+#define HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_NEG_RPY_OFF 33
+#define HCI_LE_RC_CONN_PARAM_UPD_NEG_RPY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_NEG_RPY_OFF] & HCI_SUPP_COMMANDS_RLE_RC_CONN_PARAM_UPD_NEG_RPY_MASK)
/*
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 cb85cb1..3201f75 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -1252,8 +1252,6 @@
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31
/* ULP HCI command */
-HCI_API extern BOOLEAN btsnd_hcic_ble_reset(void);
-
HCI_API extern BOOLEAN btsnd_hcic_ble_set_evt_mask (BT_EVENT_MASK event_mask);
HCI_API extern BOOLEAN btsnd_hcic_ble_read_buffer_size (void);
@@ -1267,7 +1265,7 @@
HCI_API extern BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max,
UINT8 adv_type, UINT8 addr_type_own,
UINT8 addr_type_dir, BD_ADDR direct_bda,
- UINT8 channel_map, UINT8 adv_filter_policy);
+ UINT8 channel_map, UINT8 scan_filter_policy);
HCI_API extern BOOLEAN btsnd_hcic_ble_read_adv_chnl_tx_power (void);
@@ -1331,6 +1329,20 @@
UINT8 payload);
HCI_API extern BOOLEAN btsnd_hcic_ble_test_end(void);
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+
+#define HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_REPLY 14
+HCI_API extern BOOLEAN btsnd_hcic_ble_rc_param_req_reply(UINT16 handle,
+ UINT16 conn_int_min, UINT16 conn_int_max,
+ UINT16 conn_latency, UINT16 conn_timeout,
+ UINT16 min_ce_len, UINT16 max_ce_len);
+
+#define HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_NEG_REPLY 3
+HCI_API extern BOOLEAN btsnd_hcic_ble_rc_param_req_neg_reply(UINT16 handle, UINT8 reason);
+
+#endif /* BLE_LLT_INCLUDED */
+
+
#endif /* BLE_INCLUDED */
#ifdef __cplusplus
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 7679d26..54c7ddb 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -647,7 +647,7 @@
** Returns TRUE if valid Channel, else FALSE
**
*******************************************************************************/
-L2C_API extern BOOLEAN L2CA_SendTestSFrame (UINT16 cid, BOOLEAN rr_or_rej,
+L2C_API extern BOOLEAN L2CA_SendTestSFrame (UINT16 cid, UINT8 sup_type,
UINT8 back_track);
/*******************************************************************************
@@ -919,8 +919,9 @@
** BD Address of remote
** TRUE if channel is connected, FALSE if disconnected
** Reason for connection failure
+** transport : physical transport, BR/EDR or LE
*/
-typedef void (tL2CA_FIXED_CHNL_CB) (BD_ADDR, BOOLEAN, UINT16);
+typedef void (tL2CA_FIXED_CHNL_CB) (BD_ADDR, BOOLEAN, UINT16, tBT_TRANSPORT);
/* Signalling data received. Parameters are
** BD Address of remote
@@ -1128,7 +1129,8 @@
** Return value: TRUE if update started
**
*******************************************************************************/
-L2C_API extern BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bdRa, UINT16 min_int, UINT16 max_int, UINT16 latency, UINT16 timeout);
+L2C_API extern BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bdRa, UINT16 min_int,
+ UINT16 max_int, UINT16 latency, UINT16 timeout);
/*******************************************************************************
**
@@ -1146,18 +1148,6 @@
/*******************************************************************************
**
-** Function L2CA_HandleConnUpdateEvent
-**
-** Description This function enables the connection update request from remote
-** after a successful connection update response is received.
-**
-** Returns void
-**
-*******************************************************************************/
-L2C_API void L2CA_HandleConnUpdateEvent (UINT16 handle, UINT8 status);
-
-/*******************************************************************************
-**
** Function L2CA_GetBleConnRole
**
** Description This function returns the connection role.
@@ -1173,10 +1163,13 @@
**
** Description This function returns the disconnect reason code.
**
+** Parameters: BD Address of remote
+** Physical transport for the L2CAP connection (BR/EDR or LE)
+**
** Returns disconnect reason
**
*******************************************************************************/
-L2C_API extern UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda);
+L2C_API extern UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport);
#endif /* (BLE_INCLUDED == TRUE) */
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index 68c9ebf..e47cce3 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -134,9 +134,9 @@
typedef struct
{
- UINT8 reason;
- UINT8 sec_level;
- BOOLEAN is_pair_cancel;
+ tSMP_STATUS reason;
+ tSMP_SEC_LEVEL sec_level;
+ BOOLEAN is_pair_cancel;
} tSMP_CMPL;
typedef union
diff --git a/stack/include/uipc_msg.h b/stack/include/uipc_msg.h
index 6a9a4ae..53cdccf 100644
--- a/stack/include/uipc_msg.h
+++ b/stack/include/uipc_msg.h
@@ -105,231 +105,6 @@
} tUIPC_LOG_MSG;
#define UIPC_LOG_MSGLEN (IPC_LOG_MSG_LEN + 4)
-/********************************
-
- H5 Sync Message
-
-********************************/
-
-/* op_code */
-#define SLIP_SYNC_TO_LITE_REQ 0
-#define SLIP_SYNC_TO_LITE_RESP 1
-#define SLIP_SYNC_TO_FULL_REQ 2
-#define SLIP_SYNC_TO_FULL_RESP 3
-#define SLIP_SYNC_NOTIFY 4
-
-/* status */
-#define SLIP_SYNC_SUCCESS 0
-#define SLIP_SYNC_FAILURE 1
-
-typedef struct
-{
- UINT8 op_code;
- UINT8 status;
- UINT16 acl_pkt_size;
- UINT8 state;
- UINT8 lp_state; /* Low Power state */
- UINT8 next_seqno; /* next send seq */
- UINT8 ack; /* next ack seq, expected seq from peer */
- UINT8 sent_ack; /* last sent ack */
- UINT8 sliding_window_size;/* window size */
- BOOLEAN oof_flow_control; /* Out of Frame SW Flow Control */
- BOOLEAN data_integrity_type;/* Level of Data Integrity Check */
- UINT8 rx_state; /* rx state for incoming packet processing */
-} tSLIP_SYNC_INFO;
-
-/********************************
-
- L2CAP Sync Message
-
-********************************/
-
-/* op_code */
-#define L2C_SYNC_TO_LITE_REQ 0
-#define L2C_SYNC_TO_LITE_RESP 1
-#define L2C_REMOVE_TO_LITE_REQ 2
-#define L2C_REMOVE_TO_LITE_RESP 3
-#define L2C_FLUSH_TO_FULL_IND 4
-
-/* status */
-#define L2C_SYNC_SUCCESS 0
-#define L2C_SYNC_FAILURE 1
-
-typedef struct t_l2c_stream_info
-{
- UINT16 local_cid; /* Local CID */
- UINT16 remote_cid; /* Remote CID */
- UINT16 out_mtu; /* Max MTU we will send */
- UINT16 handle; /* The handle used with LM */
- UINT16 link_xmit_quota; /* Num outstanding pkts allowed */
- BOOLEAN is_flushable; /* TRUE if flushable channel */
-} tL2C_STREAM_INFO;
-
-typedef struct t_l2c_sync_to_lite_req
-{
- UINT8 op_code; /* L2C_SYNC_TO_LITE_REQ */
- UINT16 light_xmit_quota; /* Total quota for light stack */
- UINT16 acl_data_size; /* Max ACL data size across HCI transport */
- UINT16 non_flushable_pbf; /* L2CAP_PKT_START_NON_FLUSHABLE if controller supports */
- /* Otherwise, L2CAP_PKT_START */
- UINT8 multi_av_data_cong_start; /* Multi-AV queue size to start congestion */
- UINT8 multi_av_data_cong_end; /* Multi-AV queue size to end congestion */
- UINT8 multi_av_data_cong_discard; /* Multi-AV queue size to discard */
- UINT8 num_stream;
- tL2C_STREAM_INFO stream[BTM_SYNC_INFO_NUM_STR];
-} tL2C_SYNC_TO_LITE_REQ;
-
-typedef struct t_l2c_sync_to_lite_resp_stream
-{
- UINT16 lcid;
- UINT8 status;
-} tL2C_SYNC_TO_LITE_RESP_STREAM;
-
-typedef struct t_l2c_sync_to_lite_resp
-{
- UINT8 op_code; /* L2C_SYNC_TO_LITE_RESP */
- UINT16 light_xmit_unacked; /* unacked packet more than quota in light stack */
- UINT8 num_stream;
- tL2C_SYNC_TO_LITE_RESP_STREAM stream[BTM_SYNC_INFO_NUM_STR];
-} tL2C_SYNC_TO_LITE_RESP;
-
-typedef struct t_l2c_remove_to_lite_req
-{
- UINT8 op_code; /* L2C_REMOVE_TO_LITE_REQ */
- UINT16 light_xmit_quota; /* Total quota for light stack */
- UINT8 num_stream;
- UINT16 lcid[BTM_SYNC_INFO_NUM_STR];
-} tL2C_REMOVE_TO_LITE_REQ;
-
-typedef tL2C_SYNC_TO_LITE_RESP tL2C_REMOVE_TO_LITE_RESP;
-typedef tL2C_REMOVE_TO_LITE_REQ tL2C_FLUSH_TO_FULL_IND;
-
-typedef union t_l2c_sync_msg
-{
- UINT8 op_code;
- tL2C_SYNC_TO_LITE_REQ sync_req;
- tL2C_SYNC_TO_LITE_RESP sync_resp;
- tL2C_REMOVE_TO_LITE_REQ remove_req;
- tL2C_REMOVE_TO_LITE_RESP remove_resp;
- tL2C_FLUSH_TO_FULL_IND flush_ind;
-} tL2C_SYNC_MSG;
-
-/********************************
-
- AVDTP Sync Message
-
-********************************/
-
-/* op_code */
-#define AVDT_SYNC_TO_LITE_REQ 0
-#define AVDT_SYNC_TO_LITE_RESP 1
-#define AVDT_RESYNC_TO_LITE_REQ 2
-#define AVDT_RESYNC_TO_LITE_RESP 3
-#define AVDT_SYNC_TO_FULL_REQ 4
-#define AVDT_SYNC_TO_FULL_RESP 5
-#define AVDT_REMOVE_TO_LITE_REQ 6
-#define AVDT_REMOVE_TO_LITE_RESP 7
-#define AVDT_SYNC_TO_BTC_LITE_REQ 8
-#define AVDT_SYNC_TO_BTC_LITE_RESP 9
-
-/* status */
-#define AVDT_SYNC_SUCCESS 0
-#define AVDT_SYNC_FAILURE 1
-
-typedef struct
-{
- UINT16 lcid;
- UINT32 ssrc;
-} tAVDT_SYNC_TO_BTC_LITE_REQ_STREAM;
-
-typedef struct
-{
- UINT8 opcode; /* AVDT_SYNC_TO_BTC_LITE_REQ */
- UINT8 num_stream;
- tAVDT_SYNC_TO_BTC_LITE_REQ_STREAM stream[BTM_SYNC_INFO_NUM_STR];
-} tAVDT_SYNC_TO_BTC_LITE_REQ;
-
-typedef struct
-{
- UINT8 opcode; /* AVDT_SYNC_TO_BTC_LITE_RESP */
- UINT8 status;
-} tAVDT_SYNC_TO_BTC_LITE_RESP;
-
-typedef struct t_avdt_scb_sync_info
-{
- UINT8 handle; /* SCB handle */
- BD_ADDR peer_addr; /* BD address of peer */
- UINT16 local_cid; /* Local CID */
- UINT16 peer_mtu; /* L2CAP mtu of the peer device */
- UINT8 mux_tsid_media; /* TSID for media transport session */
- UINT16 media_seq; /* media packet sequence number */
-} tAVDT_SCB_SYNC_INFO;
-
-typedef struct t_avdt_sync_info
-{
- UINT8 op_code;
- UINT8 status;
-
- tAVDT_SCB_SYNC_INFO scb_info[BTM_SYNC_INFO_NUM_STR];
-
-} tAVDT_SYNC_INFO;
-
-typedef union t_avdt_sync_msg
-{
- UINT8 op_code;
- tAVDT_SYNC_INFO sync_info;
- tAVDT_SYNC_TO_BTC_LITE_REQ btc_sync_req;
- tAVDT_SYNC_TO_BTC_LITE_RESP btc_sync_resp;
-} tAVDT_SYNC_MSG;
-
-/********************************
-
- BTA AV Sync Message
-
-********************************/
-
-/* op_code for MM light stack */
-#define BTA_AV_SYNC_TO_LITE_REQ 0
-#define BTA_AV_SYNC_TO_LITE_RESP 1
-#define BTA_AV_STR_START_TO_LITE_REQ 2
-#define BTA_AV_STR_START_TO_LITE_RESP 3
-#define BTA_AV_STR_STOP_TO_LITE_REQ 4
-#define BTA_AV_STR_STOP_TO_LITE_RESP 5
-#define BTA_AV_STR_CLEANUP_TO_LITE_REQ 6
-#define BTA_AV_STR_CLEANUP_TO_LITE_RESP 7
-#define BTA_AV_STR_SUSPEND_TO_LITE_REQ 8
-#define BTA_AV_STR_SUSPEND_TO_LITE_RESP 9
-#define BTA_AV_SYNC_ERROR_RESP 10
-
-/* op_code for BTC light stack */
-#define A2DP_START_REQ 11
-#define A2DP_START_RESP 12
-#define A2DP_STOP_REQ 13
-#define A2DP_STOP_RESP 14
-#define A2DP_CLEANUP_REQ 15
-#define A2DP_CLEANUP_RESP 16
-#define A2DP_SUSPEND_REQ 17
-#define A2DP_SUSPEND_RESP 18
-
-#define A2DP_JITTER_DONE_IND 41 /* For BTSNK */
-
-#define AUDIO_CODEC_CONFIG_REQ 19
-#define AUDIO_CODEC_CONFIG_RESP 20
-#define AUDIO_CODEC_SET_BITRATE_REQ 21
-#define AUDIO_CODEC_FLUSH_REQ 22
-#define AUDIO_ROUTE_CONFIG_REQ 23
-#define AUDIO_ROUTE_CONFIG_RESP 24
-#define AUDIO_MIX_CONFIG_REQ 25
-#define AUDIO_MIX_CONFIG_RESP 26
-#define AUDIO_BURST_FRAMES_IND 27
-#define AUDIO_BURST_END_IND 28
-#define AUDIO_EQ_MODE_CONFIG_REQ 29
-#define AUDIO_SCALE_CONFIG_REQ 30
-
-/* For TIVO, only applicable for I2S -> DAC */
-#define AUDIO_SUB_ROUTE_REQ 51
-#define AUDIO_SUB_ROUTE_RESP 52
-
typedef struct
{
UINT8 opcode; /* A2DP_START_REQ */
@@ -789,96 +564,5 @@
tMIX_SCALE_CONFIG mix_scale;
} tAUDIO_SCALE_CONFIG_REQ;
-typedef UINT8 tBTA_AV_DUAL_STACK_EVT;
-
-typedef struct
-{
- UINT8 avdt_handle; /* AVDTP handle */
- UINT8 chnl; /* the channel: audio/video */
- UINT8 codec_type; /* codec type */
- BOOLEAN cong; /* TRUE if AVDTP congested */
- UINT8 hdi; /* the index to SCB[] */
- UINT8 hndl; /* the handle: ((hdi + 1)|chnl) */
- UINT8 l2c_bufs; /* the number of buffers queued to L2CAP */
- UINT16 l2c_cid; /* L2CAP channel ID */
- BD_ADDR peer_addr; /* peer BD address */
-}tBTA_AV_SYNC_INFO;
-
-typedef struct
-{
- tBTA_AV_DUAL_STACK_EVT event;
- tBTA_AV_SYNC_INFO sync_info;
- UINT16 curr_mtu; /* common mtu shared by all active streams */
- UINT8 multi_av_supported; /* Whether multi-av is supported */
-}tBTA_AV_SYNC_INFO_REQ; /* SYNC_TO_LITE_REQ */
-
-/* Dual stack stream events */
-typedef struct
-{
- tBTA_AV_DUAL_STACK_EVT event;
- UINT8 scb_idx;
-}tBTA_AV_SCB_EVT;
-
-/* data type for the Audio Codec Information*/
-typedef struct
-{
- UINT16 bit_rate; /* SBC encoder bit rate in kbps */
- UINT16 bit_rate_busy; /* SBC encoder bit rate in kbps */
- UINT16 bit_rate_swampd; /* SBC encoder bit rate in kbps */
- UINT8 busy_level; /* Busy level indicating the bit-rate to be used */
- UINT8 codec_info[AVDT_CODEC_SIZE];
- UINT8 codec_type; /* Codec type */
-} tBTA_AV_AUDIO_CODEC_SYNC_INFO;
-
-/* Dual stack stream events */
-typedef struct
-{
- tBTA_AV_DUAL_STACK_EVT event;
- UINT8 scb_idx;
- UINT8 audio_open_cnt;
- tBTA_AV_AUDIO_CODEC_SYNC_INFO p_codec_cfg;
- UINT8 start_stop_flag;
-}tBTA_AV_SCB_REQ;
-
-typedef struct
-{
- tBTA_AV_DUAL_STACK_EVT event;
- UINT8 scb_idx;
- UINT8 audio_open_cnt;
- UINT16 curr_mtu; /* common mtu shared by all active streams */
-}tBTA_AV_SCB_CLEANUP_REQ;
-
-/* Add request/response structures if needed ...
-typedef struct
-{
- event;
- data;
-}tBTA_AV_SYNC_*_REQ/RESP;
-*/
-
-typedef union
-{
- /* MM light stack */
- tBTA_AV_DUAL_STACK_EVT event;
- tBTA_AV_SYNC_INFO_REQ sync_info_req;
- tBTA_AV_SCB_EVT scb_evt;
- tBTA_AV_SCB_REQ scb_req;
- tBTA_AV_SCB_CLEANUP_REQ scb_cleanup_req;
-
- /* BTC light stack */
- UINT8 opcode;
- tA2DP_START_REQ btc_start_req;
- tA2DP_STOP_REQ btc_stop_req;
- tA2DP_CLEANUP_REQ btc_cleanup_req;
- tA2DP_SUSPEND_REQ btc_suspend_req;
-
- tAUDIO_CODEC_CONFIG_REQ codec_config_req;
- tAUDIO_CODEC_SET_BITRATE_REQ codec_bitrate_req;
- tAUDIO_CODEC_FLUSH_REQ codec_flush_req;
- tAUDIO_ROUTE_CONFIG_REQ route_config_req;
- tAUDIO_MIX_CONFIG_REQ mix_config_req;
- tAUDIO_EQ_MODE_CONFIG_REQ eq_mode_req;
- tAUDIO_SCALE_CONFIG_REQ scale_config_req;
-}tBTA_DUAL_STACK_MSG;
-
#endif /* UIPC_MSG_H */
+
diff --git a/stack/l2cap/l2c_api.c b/stack/l2cap/l2c_api.c
index 30249a4..338a7cd 100644
--- a/stack/l2cap/l2c_api.c
+++ b/stack/l2cap/l2c_api.c
@@ -223,6 +223,10 @@
** connection establishment gets started. The callback function
** will be invoked when connection establishes or fails.
**
+** Parameters: PSM: L2CAP PSM for the connection
+** BD address of the peer
+** Enhaced retransmission mode configurations
+
** Returns the CID of the connection, or 0 if it failed to start
**
*******************************************************************************/
@@ -232,10 +236,12 @@
tL2C_CCB *p_ccb;
tL2C_RCB *p_rcb;
- L2CAP_TRACE_API6 ("L2CA_ErtmConnectReq() PSM: 0x%04x BDA: %08x%04x p_ertm_info: 0x%08x allowed:0x%x preferred:%d", psm,
+ L2CAP_TRACE_API6 ("L2CA_ErtmConnectReq() PSM: 0x%04x BDA: %08x%04x p_ertm_info"
+ ": 0x%08x allowed:0x%x preferred:%d", psm,
(p_bd_addr[0]<<24)+(p_bd_addr[1]<<16)+(p_bd_addr[2]<<8)+p_bd_addr[3],
(p_bd_addr[4]<<8)+p_bd_addr[5], p_ertm_info,
- (p_ertm_info) ? p_ertm_info->allowed_modes : 0, (p_ertm_info) ? p_ertm_info->preferred_mode : 0);
+ (p_ertm_info) ? p_ertm_info->allowed_modes : 0,
+ (p_ertm_info) ? p_ertm_info->preferred_mode : 0);
/* Fail if we have not established communications with the controller */
if (!BTM_IsDeviceUp())
@@ -251,13 +257,16 @@
}
/* First, see if we already have a link to the remote */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr)) == NULL)
+ /* assume all ERTM l2cap connection is going over BR/EDR for now */
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
/* No link. Get an LCB and start link establishment */
- if ( ((p_lcb = l2cu_allocate_lcb (p_bd_addr, FALSE)) == NULL)
- || (l2cu_create_conn(p_lcb) == FALSE) )
+ if ( ((p_lcb = l2cu_allocate_lcb (p_bd_addr, FALSE, BT_TRANSPORT_BR_EDR)) == NULL)
+ /* currently use BR/EDR for ERTM mode l2cap connection */
+ || (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE) )
{
- L2CAP_TRACE_WARNING2 ("L2CAP - conn not started for PSM: 0x%04x p_lcb: 0x%08x", psm, p_lcb);
+ L2CAP_TRACE_WARNING2 ("L2CAP - conn not started for PSM: 0x%04x p_lcb: 0x%08x",
+ psm, p_lcb);
return (0);
}
}
@@ -289,7 +298,8 @@
if (p_ccb->ertm_info.user_tx_pool_id == L2CAP_DEFAULT_ERM_POOL_ID)
p_ccb->ertm_info.user_tx_pool_id = HCI_ACL_POOL_ID;
- p_ccb->max_rx_mtu = GKI_get_pool_bufsize (p_ertm_info->user_rx_pool_id) - (L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET + L2CAP_FCS_LEN);
+ p_ccb->max_rx_mtu = GKI_get_pool_bufsize (p_ertm_info->user_rx_pool_id) -
+ (L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET + L2CAP_FCS_LEN);
}
/* If link is up, start the L2CAP connection */
@@ -312,7 +322,8 @@
p_lcb->p_pending_ccb = p_ccb;
}
- L2CAP_TRACE_API2 ("L2CAP - L2CA_conn_req(psm: 0x%04x) returned CID: 0x%04x", psm, p_ccb->local_cid);
+ L2CAP_TRACE_API2 ("L2CAP - L2CA_conn_req(psm: 0x%04x) returned CID: 0x%04x",
+ psm, p_ccb->local_cid);
/* Return the local CID as our handle */
return (p_ccb->local_cid);
@@ -330,7 +341,8 @@
** Returns TRUE for success, FALSE for failure
**
*******************************************************************************/
-BOOLEAN L2CA_ConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 result, UINT16 status)
+BOOLEAN L2CA_ConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid,
+ UINT16 result, UINT16 status)
{
return L2CA_ErtmConnectRsp (p_bd_addr, id, lcid, result, status, NULL);
}
@@ -353,13 +365,14 @@
tL2C_LCB *p_lcb;
tL2C_CCB *p_ccb;
- L2CAP_TRACE_API6 ("L2CA_ErtmConnectRsp() CID: 0x%04x Result: %d Status: %d BDA: %08x%04x p_ertm_info:0x%08x",
+ L2CAP_TRACE_API6 ("L2CA_ErtmConnectRsp() CID: 0x%04x Result: %d Status: %d BDA: %08x%04x"
+ " p_ertm_info:0x%08x",
lcid, result, status,
(p_bd_addr[0]<<24)+(p_bd_addr[1]<<16)+(p_bd_addr[2]<<8)+p_bd_addr[3],
(p_bd_addr[4]<<8)+p_bd_addr[5], p_ertm_info);
/* First, find the link control block */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
/* No link. Get an LCB and start link establishment */
L2CAP_TRACE_WARNING0 ("L2CAP - no LCB for L2CA_conn_rsp");
@@ -594,15 +607,15 @@
return (FALSE);
/* First, see if we already have a link to the remote */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
/* No link. Get an LCB and start link establishment */
- if ((p_lcb = l2cu_allocate_lcb (p_bd_addr, FALSE)) == NULL)
+ if ((p_lcb = l2cu_allocate_lcb (p_bd_addr, FALSE, BT_TRANSPORT_BR_EDR)) == NULL)
{
L2CAP_TRACE_WARNING0 ("L2CAP - no LCB for L2CA_ping");
return (FALSE);
}
- if (l2cu_create_conn(p_lcb) == FALSE)
+ if (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE)
{
return (FALSE);
}
@@ -670,7 +683,7 @@
}
/* We assume the upper layer will call this function only when the link is established. */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
L2CAP_TRACE_ERROR0 ("L2CA_Echo ERROR : link not established");
return FALSE;
@@ -767,7 +780,7 @@
if (memcmp (BT_BD_ANY, bd_addr, BD_ADDR_LEN))
{
- p_lcb = l2cu_find_lcb_by_bd_addr( bd_addr );
+ p_lcb = l2cu_find_lcb_by_bd_addr( bd_addr, BT_TRANSPORT_BR_EDR);
if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED))
p_lcb->idle_timeout = timeout;
else
@@ -880,7 +893,7 @@
return (0);
}
- if ((p_lcb = l2cu_allocate_lcb (p_bd_addr, FALSE)) == NULL)
+ if ((p_lcb = l2cu_allocate_lcb (p_bd_addr, FALSE, BT_TRANSPORT_BR_EDR)) == NULL)
{
L2CAP_TRACE_WARNING0 ("L2CAP - no LCB for L2CA_conn_req");
return (0);
@@ -1129,7 +1142,7 @@
if (memcmp (BT_BD_ANY, bd_addr, BD_ADDR_LEN))
{
- p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr);
+ p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_BR_EDR);
if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED))
{
@@ -1195,7 +1208,7 @@
tL2C_LCB *p_lcb;
/* We must already have a link to the remote */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
L2CAP_TRACE_WARNING2 ("L2CA_GetPeerFeatures() No BDA: %08x%04x",
(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
@@ -1307,9 +1320,8 @@
BOOLEAN L2CA_ConnectFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda)
{
tL2C_LCB *p_lcb;
-#if BLE_INCLUDED == TRUE
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
UINT16 reason;
-#endif
L2CAP_TRACE_API3 ("L2CA_ConnectFixedChnl() CID: 0x%04x BDA: %08x%04x", fixed_cid,
(rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
@@ -1329,39 +1341,58 @@
return (FALSE);
}
+#if BLE_INCLUDED == TRUE
+ if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
+ transport = BT_TRANSPORT_LE;
+#endif
+
/* If we already have a link to the remote, check if it supports that CID */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) != NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, transport)) != NULL)
{
if (!(p_lcb->peer_chnl_mask[0] & (1 << fixed_cid)))
{
- L2CAP_TRACE_EVENT3 ("L2CA_ConnectFixedChnl() CID: 0x%04x BDA: %08x%04x not supported", fixed_cid,
- (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
+ L2CAP_TRACE_EVENT3 ("L2CA_ConnectFixedChnl() CID:0x%04x BDA: %08x%04x not supported",
+ fixed_cid,(rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+ (rem_bda[4]<<8)+rem_bda[5]);
return (FALSE);
}
/* Get a CCB and link the lcb to it */
- if (!l2cu_initialize_fixed_ccb (p_lcb, fixed_cid, &l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
+ if (!l2cu_initialize_fixed_ccb (p_lcb, fixed_cid,
+ &l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
{
L2CAP_TRACE_WARNING1 ("L2CA_ConnectFixedChnl(0x%04x) - LCB but no CCB", fixed_cid);
return (FALSE);
}
+
+ /* racing with disconnecting, queue the connection request */
+ if (p_lcb->link_state == LST_DISCONNECTING)
+ {
+ L2CAP_TRACE_DEBUG0 ("L2CAP API - link disconnecting: RETRY LATER");
+ /* Save ccb so it can be started after disconnect is finished */
+ p_lcb->p_pending_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
+ return (TRUE);
+ }
+
#if BLE_INCLUDED == TRUE
- reason = (p_lcb->is_ble_link) ? 1: 0;
- (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, reason);
+ (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)
+ (p_lcb->remote_bd_addr, TRUE, 0, p_lcb->transport);
#else
- (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, 0);
+ (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)
+ (p_lcb->remote_bd_addr, TRUE, 0, BT_TRANSPORT_BR_EDR);
#endif
return (TRUE);
}
/* No link. Get an LCB and start link establishment */
- if ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE)) == NULL)
+ if ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE, transport)) == NULL)
{
L2CAP_TRACE_WARNING1 ("L2CA_ConnectFixedChnl(0x%04x) - no LCB", fixed_cid);
return (FALSE);
}
/* Get a CCB and link the lcb to it */
- if (!l2cu_initialize_fixed_ccb (p_lcb, fixed_cid, &l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
+ if (!l2cu_initialize_fixed_ccb (p_lcb, fixed_cid,
+ &l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
{
p_lcb->disc_reason = L2CAP_CONN_NO_RESOURCES;
L2CAP_TRACE_WARNING1 ("L2CA_ConnectFixedChnl(0x%04x) - no CCB", fixed_cid);
@@ -1369,7 +1400,7 @@
return (FALSE);
}
- return (l2cu_create_conn(p_lcb));
+ return (l2cu_create_conn(p_lcb, transport));
}
/*******************************************************************************
@@ -1389,10 +1420,16 @@
UINT16 L2CA_SendFixedChnlData (UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf)
{
tL2C_LCB *p_lcb;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
L2CAP_TRACE_API3 ("L2CA_SendFixedChnlData() CID: 0x%04x BDA: %08x%04x", fixed_cid,
(rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
+#if BLE_INCLUDED == TRUE
+ if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
+ transport = BT_TRANSPORT_LE;
+#endif
+
/* Check CID is valid and registered */
if ( (fixed_cid < L2CAP_FIRST_FIXED_CHNL) || (fixed_cid > L2CAP_LAST_FIXED_CHNL)
|| (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb == NULL) )
@@ -1409,7 +1446,9 @@
}
/* We need to have a link up */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, transport)) == NULL ||
+ /* if link is disconnecting, also report data sending failure */
+ p_lcb->link_state == LST_DISCONNECTING)
{
L2CAP_TRACE_WARNING1 ("L2CA_SendFixedChnlData(0x%04x) - no LCB", fixed_cid);
return (L2CAP_DW_FAILED);
@@ -1463,6 +1502,7 @@
{
tL2C_LCB *p_lcb;
tL2C_CCB *p_ccb;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
/* Check CID is valid and registered */
if ( (fixed_cid < L2CAP_FIRST_FIXED_CHNL) || (fixed_cid > L2CAP_LAST_FIXED_CHNL)
@@ -1472,8 +1512,14 @@
return (FALSE);
}
+#if BLE_INCLUDED == TRUE
+ if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
+ transport = BT_TRANSPORT_LE;
+#endif
+
/* Is a fixed channel connected to the remote BDA ?*/
- p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, transport);
+
if ( ((p_lcb) == NULL) || (!p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]) )
{
L2CAP_TRACE_WARNING3 ("L2CA_RemoveFixedChnl() CID: 0x%04x BDA: %08x%04x not connected", fixed_cid,
@@ -1491,7 +1537,14 @@
p_lcb->disc_reason = HCI_ERR_CONN_CAUSE_LOCAL_HOST;
#if BLE_INCLUDED == TRUE
- if (fixed_cid == L2CAP_ATT_CID && !p_lcb->ccb_queue.p_first_ccb)
+ /* retain the link for a few more seconds after SMP pairing is done, since Android
+ platformalways do service discovery after pairing complete. This way would avoid
+ the link down (pairing is complete) and an immediate reconnection for service
+ discovery. Some devices do not do auto advertising when link is dropped, thus fail
+ the second connection and service discovery.
+ BEFORE :if ((fixed_cid == L2CAP_ATT_CID || fixed_cid == L2CAP_SMP_CID)
+ && !p_lcb->ccb_queue.p_first_ccb)*/
+ if ((fixed_cid == L2CAP_ATT_CID ) && !p_lcb->ccb_queue.p_first_ccb)
p_lcb->idle_timeout = 0;
#endif
@@ -1520,9 +1573,15 @@
BOOLEAN L2CA_SetFixedChannelTout (BD_ADDR rem_bda, UINT16 fixed_cid, UINT16 idle_tout)
{
tL2C_LCB *p_lcb;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+
+#if BLE_INCLUDED == TRUE
+ if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
+ transport = BT_TRANSPORT_LE;
+#endif
/* Is a fixed channel connected to the remote BDA ?*/
- p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, transport);
if ( ((p_lcb) == NULL) || (!p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]) )
{
L2CAP_TRACE_WARNING3 ("L2CA_SetFixedChannelTout() CID: 0x%04x BDA: %08x%04x not connected", fixed_cid,
@@ -1614,7 +1673,7 @@
tL2C_LCB *p_lcb;
/* Find the link that is associated with this remote bdaddr */
- p_lcb = l2cu_find_lcb_by_bd_addr (p_bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
/* If no link for this handle, nothing to do. */
if (!p_lcb)
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index ba0d7ec..2d7d9e0 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -32,7 +32,13 @@
#include "hcimsgs.h"
#if (BLE_INCLUDED == TRUE)
+#define L2CA_GET_UPD_ST(x) ((x) & UPD_ST_MASK)
+#define L2CA_SET_UPD_ST(x, y) x = (((x) & ~UPD_ST_MASK) | (y))
+
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+#include "vendor_ble.h"
+#endif
/*******************************************************************************
**
** Function L2CA_CancelBleConnectReq
@@ -68,7 +74,7 @@
if (btsnd_hcic_ble_create_conn_cancel())
{
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) != NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE)) != NULL)
{
p_lcb->disc_reason = L2CAP_CONN_CANCEL;
l2cu_release_lcb (p_lcb);
@@ -84,57 +90,6 @@
/*******************************************************************************
**
-** Function L2CA_InternalBleConnUpdate
-**
-** Description update BLE connection based on status
-**
-** Parameters: lcb
-**
-** Return value: none
-**
-*******************************************************************************/
-static void L2CA_InternalBleConnUpdate (tL2C_LCB *p_lcb)
-{
- if (p_lcb->upd_status & L2C_BLE_UPDATE_PENDING) return;
-
- if (p_lcb->upd_status & L2C_BLE_CONN_UPDATE_DISABLE)
- {
- /* application requests to disable parameters update.
- If parameters are already updated, lets set them
- up to what has been requested during connection establishement */
- if (p_lcb->upd_status & L2C_BLE_NOT_DEFAULT_PARAM)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
-
- 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 : 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_status &= ~L2C_BLE_NOT_DEFAULT_PARAM;
- p_lcb->upd_status |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NEW_CONN_PARAM);
- }
- }
- else
- {
- /* application allows to do update, if we were delaying one do it now */
- if (p_lcb->upd_status & L2C_BLE_NEW_CONN_PARAM)
- {
- btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
- p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
- p_lcb->upd_status &= ~L2C_BLE_NEW_CONN_PARAM;
- p_lcb->upd_status |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NOT_DEFAULT_PARAM);
- }
- }
-}
-
-/*******************************************************************************
-**
** Function L2CA_UpdateBleConnParams
**
** Description Update BLE connection parameters.
@@ -144,41 +99,54 @@
** Return value: TRUE if update started
**
*******************************************************************************/
-BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int, UINT16 latency, UINT16 timeout)
+BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
+ UINT16 latency, UINT16 timeout)
{
- tL2C_LCB *p_lcb;
+ tL2C_LCB *p_lcb;
+ tACL_CONN *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
- /* See if we have a link control block for the remote device */
- p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda);
+ /* See if we have a link control block for the remote device */
+ p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
- /* If we don't have one, create one and accept the connection. */
- if (!p_lcb)
- {
- L2CAP_TRACE_WARNING2 ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
- (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
- return(FALSE);
- }
+ /* If we don't have one, create one and accept the connection. */
+ if (!p_lcb || !p_acl_cb)
+ {
+ L2CAP_TRACE_WARNING2 ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
+ (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+ (rem_bda[4]<<8)+rem_bda[5]);
+ return(FALSE);
+ }
- if (!p_lcb->is_ble_link)
- {
- L2CAP_TRACE_WARNING2 ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
- (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
- return(FALSE);
- }
+ if (p_lcb->transport != BT_TRANSPORT_LE)
+ {
+ L2CAP_TRACE_WARNING2 ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
+ (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+ (rem_bda[4]<<8)+rem_bda[5]);
+ return(FALSE);
+ }
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+ /* if both 4.1 compliant */
+ if ((HCI_LE_CONN_PARAM_REQ_SUPPORTED(btm_cb.devcb.local_le_features) &&
+ HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features)))
+ {
+ /* TODO: CE length selection ?? */
+ btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int,
+ latency, timeout, 0, 0);
+ }
+ else
+ /* if either side does not support Connection Parameters Request
+ Link Layer Control Procedure,
+ use Link Layer Connection Update procedure */
+#endif
+ {
+ if (p_lcb->link_role == HCI_ROLE_MASTER)
+ btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int,
+ latency, timeout, 0, 0);
+ else
+ l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout);
+ }
+ return(TRUE);
- if (p_lcb->link_role == HCI_ROLE_MASTER)
- {
- p_lcb->min_interval = min_int;
- p_lcb->max_interval = max_int;
- p_lcb->latency = latency;
- p_lcb->timeout = timeout;
- p_lcb->upd_status |= L2C_BLE_NEW_CONN_PARAM;
- L2CA_InternalBleConnUpdate(p_lcb);
- }
- else
- l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout);
-
- return(TRUE);
}
@@ -198,76 +166,68 @@
tL2C_LCB *p_lcb;
/* See if we have a link control block for the remote device */
- p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
- /* If we don't have one, create one and accept the connection. */
if (!p_lcb)
{
L2CAP_TRACE_WARNING2 ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
- (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
+ (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+ (rem_bda[4]<<8)+rem_bda[5]);
return (FALSE);
}
- L2CAP_TRACE_API4 ("L2CA_EnableUpdateBleConnParams - BD_ADDR %08x%04x enable %d upd state %d",
- (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5],
- enable, p_lcb->upd_status);
+ L2CAP_TRACE_API5 ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x",__FUNCTION__,
+ (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+ (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->conn_update_mask);
- if (!p_lcb->is_ble_link || (p_lcb->link_role != HCI_ROLE_MASTER))
+ if (p_lcb->transport != BT_TRANSPORT_LE || (p_lcb->link_role != HCI_ROLE_MASTER))
{
- L2CAP_TRACE_WARNING3 ("L2CA_EnableUpdateBleConnParams - BD_ADDR %08x%04x not LE or not master %d",
- (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
+ L2CAP_TRACE_WARNING4 ("%s - BD_ADDR %08x%04x not LE or not master %d", __FUNCTION__,
+ (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+ (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
return (FALSE);
}
if (enable)
{
- p_lcb->upd_status &= ~L2C_BLE_CONN_UPDATE_DISABLE;
+ if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) == UPD_DISABLED)
+ {
+ p_lcb->conn_param_enb.param = (TIMER_PARAM_TYPE)p_lcb;
+ btu_start_timer (&p_lcb->conn_param_enb, BTU_TTYPE_L2CAP_END_CONN_UPD,
+ L2CAP_BLE_ENB_CONN_PARAM_TOUT);
+ L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENB_TOUT);
+ }
}
- else
+ else if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) != UPD_DISABLED)
{
- p_lcb->upd_status |= L2C_BLE_CONN_UPDATE_DISABLE;
- }
+ btu_stop_timer(&p_lcb->conn_param_enb);
- L2CA_InternalBleConnUpdate(p_lcb);
+ if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
+ {
+
+ /*
+ application requests to disable parameters update.If parameters are already updated,
+ lets set them up to what has been requested during connection establishement
+ */
+ if ((p_lcb->conn_update_mask & UPD_REQUEST) != 0)
+ {
+ /* revert back to default */
+ btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
+ BTM_BLE_CONN_INT_MIN_DEF,
+ BTM_BLE_CONN_INT_MAX_DEF,
+ BTM_BLE_CONN_SLAVE_LATENCY_DEF,
+ BTM_BLE_CONN_TIMEOUT_DEF,
+ 0, 0);
+ }
+ }
+ L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_DISABLED);
+
+ }
return (TRUE);
+
}
-/*******************************************************************************
-**
-** Function L2CA_HandleConnUpdateEvent
-**
-** Description This function enables the connection update request from remote
-** after a successful connection update response is received.
-**
-** Returns void
-**
-*******************************************************************************/
-void L2CA_HandleConnUpdateEvent (UINT16 handle, UINT8 status)
-{
- tL2C_LCB *p_lcb;
-
- L2CAP_TRACE_DEBUG0("L2CA_HandleConnUpdateEvent");
-
- /* See if we have a link control block for the remote device */
- p_lcb = l2cu_find_lcb_by_handle(handle);
- if (!p_lcb)
- {
- L2CAP_TRACE_WARNING1("L2CA_EnableUpdateBleConnParams: Invalid handle: %d", handle);
- return;
- }
-
- p_lcb->upd_status &= ~L2C_BLE_UPDATE_PENDING;
-
- if (status != HCI_SUCCESS)
- {
- L2CAP_TRACE_WARNING1("L2CA_EnableUpdateBleConnParams: Error status: %d", status);
- }
-
- L2CA_InternalBleConnUpdate(p_lcb);
-
- L2CAP_TRACE_DEBUG1("L2CA_HandleConnUpdateEvent: upd_status=%d", p_lcb->upd_status);
-}
/*******************************************************************************
**
@@ -284,7 +244,7 @@
tL2C_LCB *p_lcb;
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr)) != NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL)
role = p_lcb->link_role;
return role;
@@ -298,12 +258,12 @@
** Returns disconnect reason
**
*******************************************************************************/
-UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda)
+UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
{
tL2C_LCB *p_lcb;
UINT16 reason = 0;
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda)) != NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL)
reason = p_lcb->disc_reason;
L2CAP_TRACE_DEBUG1 ("L2CA_GetDisconnectReason=%d ",reason);
@@ -333,12 +293,12 @@
l2cb.is_ble_connecting = FALSE;
/* See if we have a link control block for the remote device */
- p_lcb = l2cu_find_lcb_by_bd_addr (bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
/* If we don't have one, create one. this is auto connection complete. */
if (!p_lcb)
{
- p_lcb = l2cu_allocate_lcb (bda, FALSE);
+ p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
if (!p_lcb)
{
btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
@@ -368,7 +328,7 @@
/* Connected OK. Change state to connected, we were scanning so we are master */
p_lcb->link_state = LST_CONNECTED;
p_lcb->link_role = HCI_ROLE_MASTER;
- p_lcb->is_ble_link = TRUE;
+ p_lcb->transport = BT_TRANSPORT_LE;
/* If there are any preferred connection parameters, set them now */
if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
@@ -394,21 +354,16 @@
p_dev_rec->conn_params.slave_latency,
p_dev_rec->conn_params.supervision_tout,
0, 0);
- p_lcb->upd_status |= L2C_BLE_UPDATE_PENDING;
}
/* Tell BTM Acl management about the link */
- btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE);
-
- if (p_lcb->p_echo_rsp_cb)
- {
- L2CAP_TRACE_ERROR0 ("l2cu_send_peer_echo_req");
- l2cu_send_peer_echo_req (p_lcb, NULL, 0);
- }
+ btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
l2cu_process_fixed_chnl_resp (p_lcb);
+
+ btm_ble_set_conn_st(BLE_CONN_IDLE);
}
@@ -433,12 +388,12 @@
UNUSED(conn_timeout);
/* See if we have a link control block for the remote device */
- p_lcb = l2cu_find_lcb_by_bd_addr (bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
/* If we don't have one, create one and accept the connection. */
if (!p_lcb)
{
- p_lcb = l2cu_allocate_lcb (bda, FALSE);
+ p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
if (!p_lcb)
{
btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
@@ -462,16 +417,22 @@
/* Connected OK. Change state to connected, we were advertising, so we are slave */
p_lcb->link_state = LST_CONNECTED;
p_lcb->link_role = HCI_ROLE_SLAVE;
- p_lcb->is_ble_link = TRUE;
+ p_lcb->transport = BT_TRANSPORT_LE;
/* Tell BTM Acl management about the link */
p_dev_rec = btm_find_or_alloc_dev (bda);
- btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE);
+ btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
l2cu_process_fixed_chnl_resp (p_lcb);
+
+ /* when adv and initiating are both active, cancel the direct connection */
+ if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0)
+ {
+ L2CA_CancelBleConnectReq(bda);
+ }
}
/*******************************************************************************
@@ -561,12 +522,22 @@
l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
- p_lcb->min_interval = min_interval;
- p_lcb->max_interval = max_interval;
- p_lcb->latency = latency;
- p_lcb->timeout = timeout;
- p_lcb->upd_status |= L2C_BLE_NEW_CONN_PARAM;
- L2CA_InternalBleConnUpdate(p_lcb);
+ p_lcb->min_interval = min_interval;
+ p_lcb->max_interval = max_interval;
+ p_lcb->latency = latency;
+ p_lcb->timeout = timeout;
+ p_lcb->conn_update_mask |= UPD_REQUEST;
+
+ if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
+ {
+ btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_interval, max_interval,
+ latency, timeout, 0, 0);
+ }
+ else
+ {
+ L2CAP_TRACE_EVENT0 ("L2CAP - LE - update currently disabled");
+ }
+
}
}
else
@@ -583,8 +554,47 @@
return;
}
}
+/*******************************************************************************
+**
+** Function l2c_enable_conn_param_timeout
+**
+** Description This function process the connection parameter enabling timeout
+**
+** Returns None.
+**
+*******************************************************************************/
+void l2c_enable_conn_param_timeout(tL2C_LCB * p_lcb)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
+ /* application allows to do update, if we were delaying one do it now, otherwise
+ just mark lcb that updates are enabled */
+ if (p_lcb->conn_update_mask & UPD_REQUEST)
+ {
+ btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, p_lcb->min_interval, p_lcb->max_interval,
+ p_lcb->latency, p_lcb->timeout, 0, 0);
+ }
+ else
+ {
+ /* if preferred number has been set, set to preferred conn parameter */
+ if (p_dev_rec && p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF)
+ {
+ 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 : 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);
+ }
+ }
+ L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENABLED);
+
+}
/*******************************************************************************
**
** Function l2cble_init_direct_conn
@@ -606,7 +616,7 @@
/* There can be only one BLE connection request outstanding at a time */
if (p_dev_rec == NULL)
{
- BTM_TRACE_WARNING0 ("unknown device, can not initate connection");
+ L2CAP_TRACE_WARNING0 ("unknown device, can not initate connection");
return(FALSE);
}
@@ -616,14 +626,32 @@
init_addr_type = p_lcb->ble_addr_type;
memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
-#if BTM_BLE_PRIVACY_SPT == TRUE
+#if BLE_PRIVACY_SPT == TRUE
if (p_dev_rec->ble.active_addr_type == BTM_BLE_ADDR_RRA)
{
init_addr_type = BLE_ADDR_RANDOM;
- memcpy(init_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
+ //memcpy(init_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
}
+ /* if privacy is on and current do not consider using reconnection address */
+ if (btm_cb.ble_ctr_cb.privacy ) /* && p_dev_rec->ble.use_reconn_addr */
+ own_addr_type = BLE_ADDR_RANDOM;
#endif
+ if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
+ {
+ l2cu_release_lcb (p_lcb);
+ L2CAP_TRACE_ERROR0("initate direct connection fail, topology limitation");
+ return FALSE;
+ }
+#if BLE_PRIVACY_SPT == TRUE
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+ extern tBTM_STATUS BTM_BleEnableIRKFeature(BOOLEAN enable);
+ if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
+ BTM_BleEnableIRKFeature(TRUE);
+
+ btm_random_pseudo_to_public(init_addr, &init_addr_type);
+#endif
+#endif
if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
scan_win, /* UINT16 scan_win */
FALSE, /* UINT8 white_list */
@@ -712,4 +740,47 @@
l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
}
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function l2cble_process_rc_param_request_evt
+**
+** Description process LE Remote Connection Parameter Request Event.
+**
+** Returns void
+**
+*******************************************************************************/
+void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
+ UINT16 latency, UINT16 timeout)
+{
+ tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle (handle);
+
+ if (p_lcb != NULL)
+ {
+ p_lcb->min_interval = int_min;
+ p_lcb->max_interval = int_max;
+ p_lcb->latency = latency;
+ p_lcb->timeout = timeout;
+ p_lcb->conn_update_mask |= UPD_REQUEST;
+
+ /* TODO: revisit: if update is enabled, always accept connection parameter update */
+ if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
+ {
+ btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
+ }
+ else
+ {
+ L2CAP_TRACE_EVENT0 ("L2CAP - LE - update currently disabled");
+ btsnd_hcic_ble_rc_param_req_neg_reply (handle,HCI_ERR_UNACCEPT_CONN_INTERVAL);
+ }
+
+ }
+ else
+ {
+ L2CAP_TRACE_WARNING0("No link to update connection parameter")
+ }
+}
+#endif
+
+
#endif /* (BLE_INCLUDED == TRUE) */
diff --git a/stack/l2cap/l2c_csm.c b/stack/l2cap/l2c_csm.c
index 4e24c23..d8c4ed3 100644
--- a/stack/l2cap/l2c_csm.c
+++ b/stack/l2cap/l2c_csm.c
@@ -1015,6 +1015,7 @@
#if BTM_PWR_MGR_INCLUDED == TRUE
{
tBTM_PM_PWR_MD settings;
+ memset((void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
}
@@ -1038,6 +1039,7 @@
#if BTM_PWR_MGR_INCLUDED == TRUE
{
tBTM_PM_PWR_MD settings;
+ memset((void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
}
diff --git a/stack/l2cap/l2c_fcr.c b/stack/l2cap/l2c_fcr.c
index 9685f77..f2e72ad 100644
--- a/stack/l2cap/l2c_fcr.c
+++ b/stack/l2cap/l2c_fcr.c
@@ -2246,7 +2246,7 @@
p_ccb->out_cfg_fcr_present = TRUE;
}
- if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE)
+ if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE || p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE)
{
/* Always respond with FCR ERTM parameters */
p_ccb->out_cfg_fcr_present = TRUE;
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 72d5544..272d318 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -52,6 +52,8 @@
#define L2CAP_WAIT_UNPARK_TOUT 2 /* 2 seconds */
#define L2CAP_LINK_INFO_RESP_TOUT 2 /* 2 seconds */
#define L2CAP_BLE_LINK_CONNECT_TOUT 30 /* 30 seconds */
+#define L2CAP_BLE_CONN_PARAM_UPD_TOUT 30 /* 30 seconds */
+#define L2CAP_BLE_ENB_CONN_PARAM_TOUT 1 /* 1 seconds */
/* quick timer uses millisecond unit */
#define L2CAP_DEFAULT_RETRANS_TOUT 2000 /* 2000 milliseconds */
@@ -393,6 +395,7 @@
UINT8 link_role; /* Master or slave */
UINT8 id;
+ UINT8 cur_echo_id; /* Current id value for echo request */
tL2CA_ECHO_RSP_CB *p_echo_rsp_cb; /* Echo response callback */
UINT16 idle_timeout; /* Idle timeout */
BOOLEAN is_bonding; /* True - link active only for bonding */
@@ -431,16 +434,17 @@
UINT16 disc_reason;
#endif
+ tBT_TRANSPORT transport;
#if (BLE_INCLUDED == TRUE)
- BOOLEAN is_ble_link;
tBLE_ADDR_TYPE ble_addr_type;
+ TIMER_LIST_ENT conn_param_enb; /* Timer entry for enabling connection parameter update */
-#define L2C_BLE_CONN_UPDATE_DISABLE 0x1 /* disable update connection parameters */
-#define L2C_BLE_NEW_CONN_PARAM 0x2 /* new connection parameter to be set */
-#define L2C_BLE_UPDATE_PENDING 0x4 /* waiting for connection update finished */
-#define L2C_BLE_NOT_DEFAULT_PARAM 0x8 /* not using default connection parameters */
- UINT8 upd_status;
-
+#define UPD_ENABLED 0 /* If peer requests update, we will change params */
+#define UPD_DISABLED 1 /* application requested not to update */
+#define UPD_ENB_TOUT 2 /* while updates are disabled, peer requested new parameters */
+#define UPD_ST_MASK 0x0f
+#define UPD_REQUEST 0x10 /* remote device set preferred conn param */
+ UINT8 conn_update_mask;
UINT16 min_interval; /* parameters as requested by peripheral */
UINT16 max_interval;
UINT16 latency;
@@ -578,14 +582,14 @@
/* Functions provided by l2c_utils.c
************************************
*/
-extern tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding);
+extern tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPORT transport);
extern BOOLEAN l2cu_start_post_bond_timer (UINT16 handle);
extern void l2cu_release_lcb (tL2C_LCB *p_lcb);
-extern tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr);
+extern tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport);
extern tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle);
extern void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding);
-extern UINT8 l2cu_get_conn_role (BD_ADDR bd_addr);
+extern UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb);
extern BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_after_rs);
extern void l2cu_enqueue_ccb (tL2C_CCB *p_ccb);
@@ -597,6 +601,7 @@
extern tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid);
extern tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid);
extern void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask);
+extern BOOLEAN l2c_is_cmd_rejected (UINT8 cmd_code, UINT8 id, tL2C_LCB *p_lcb);
extern void l2cu_send_peer_cmd_reject (tL2C_LCB *p_lcb, UINT16 reason,
UINT8 rem_id,UINT16 p1, UINT16 p2);
@@ -676,7 +681,7 @@
extern tL2C_LCB *l2cu_find_lcb_by_state (tL2C_LINK_STATE state);
extern BOOLEAN l2cu_lcb_disconnecting (void);
-extern BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb);
+extern BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport);
extern BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb);
extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb);
extern void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda);
@@ -699,7 +704,7 @@
extern void l2c_link_processs_num_bufs (UINT16 num_lm_acl_bufs);
extern UINT8 l2c_link_pkts_rcvd (UINT16 *num_pkts, UINT16 *handles);
extern void l2c_link_role_changed (BD_ADDR bd_addr, UINT8 new_role, UINT8 hci_status);
-extern void l2c_link_sec_comp (BD_ADDR p_bda, void *p_ref_data, UINT8 status);
+extern void l2c_link_sec_comp (BD_ADDR p_bda, tBT_TRANSPORT trasnport, void *p_ref_data, UINT8 status);
extern void l2c_link_segments_xmitted (BT_HDR *p_msg);
extern void l2c_pin_code_request (BD_ADDR bd_addr);
extern void l2c_link_adjust_chnl_allocation (void);
@@ -762,8 +767,13 @@
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);
-
+extern void l2c_enable_conn_param_timeout(tL2C_LCB * p_lcb);
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+extern void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
+ UINT16 latency, UINT16 timeout);
#endif
+#endif
+extern void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb);
#ifdef __cplusplus
}
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index fd38ca2..f5e8294 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -65,12 +65,12 @@
BOOLEAN no_links;
/* See if we have a link control block for the remote device */
- p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr);
+ p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_BR_EDR);
/* If we don't have one, create one and accept the connection. */
if (!p_lcb)
{
- p_lcb = l2cu_allocate_lcb (bd_addr, FALSE);
+ p_lcb = l2cu_allocate_lcb (bd_addr, FALSE, BT_TRANSPORT_BR_EDR);
if (!p_lcb)
{
btsnd_hcic_reject_conn (bd_addr, HCI_ERR_HOST_REJECT_RESOURCES);
@@ -99,7 +99,7 @@
if (!btm_dev_support_switch (bd_addr))
p_lcb->link_role = HCI_ROLE_SLAVE;
else
- p_lcb->link_role = l2cu_get_conn_role(bd_addr);
+ p_lcb->link_role = l2cu_get_conn_role(p_lcb);
}
/* Tell the other side we accept the connection */
@@ -120,7 +120,7 @@
if (!btm_dev_support_switch (bd_addr))
p_lcb->link_role = HCI_ROLE_SLAVE;
else
- p_lcb->link_role = l2cu_get_conn_role(bd_addr);
+ p_lcb->link_role = l2cu_get_conn_role(p_lcb);
btsnd_hcic_accept_conn (bd_addr, p_lcb->link_role);
@@ -168,7 +168,7 @@
memcpy (ci.bd_addr, p_bda, BD_ADDR_LEN);
/* See if we have a link control block for the remote device */
- p_lcb = l2cu_find_lcb_by_bd_addr (ci.bd_addr);
+ p_lcb = l2cu_find_lcb_by_bd_addr (ci.bd_addr, BT_TRANSPORT_BR_EDR);
/* If we don't have one, this is an error */
if (!p_lcb)
@@ -202,9 +202,9 @@
if ((p_dev_info = btm_find_dev (p_bda)) != NULL)
btm_acl_created (ci.bd_addr, p_dev_info->dev_class,
p_dev_info->sec_bd_name, handle,
- p_lcb->link_role, FALSE);
+ p_lcb->link_role, BT_TRANSPORT_BR_EDR);
else
- btm_acl_created (ci.bd_addr, NULL, NULL, handle, p_lcb->link_role, FALSE);
+ btm_acl_created (ci.bd_addr, NULL, NULL, handle, p_lcb->link_role, BT_TRANSPORT_BR_EDR);
BTM_SetLinkSuperTout (ci.bd_addr, btm_cb.btm_def_link_super_tout);
@@ -272,7 +272,7 @@
}
else
{
- l2cu_create_conn(p_lcb);
+ l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR);
}
}
}
@@ -290,7 +290,7 @@
** Returns void
**
*******************************************************************************/
-void l2c_link_sec_comp (BD_ADDR p_bda, void *p_ref_data, UINT8 status)
+void l2c_link_sec_comp (BD_ADDR p_bda, tBT_TRANSPORT transport, void *p_ref_data, UINT8 status)
{
tL2C_CONN_INFO ci;
tL2C_LCB *p_lcb;
@@ -298,6 +298,8 @@
tL2C_CCB *p_next_ccb;
UINT8 event;
+ UNUSED(transport);
+
L2CAP_TRACE_DEBUG2 ("l2c_link_sec_comp: %d, 0x%x", status, p_ref_data);
if (status == BTM_SUCCESS_NO_SECURITY)
@@ -307,7 +309,7 @@
ci.status = status;
memcpy (ci.bd_addr, p_bda, BD_ADDR_LEN);
- p_lcb = l2cu_find_lcb_by_bd_addr (p_bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
/* If we don't have one, this is an error */
if (!p_lcb)
@@ -361,6 +363,7 @@
tL2C_CCB *p_ccb;
BOOLEAN status = TRUE;
BOOLEAN lcb_is_free = TRUE;
+ tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
/* See if we have a link control block for the connection */
p_lcb = l2cu_find_lcb_by_handle (handle);
@@ -401,35 +404,53 @@
p_ccb = pn;
}
-#if BTM_SCO_INCLUDED == TRUE
- /* Tell SCO management to drop any SCOs on this ACL */
- btm_sco_acl_removed (p_lcb->remote_bd_addr);
+#if (BTM_SCO_INCLUDED == TRUE)
+#if (BLE_INCLUDED == TRUE)
+ if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
+#endif
+ /* Tell SCO management to drop any SCOs on this ACL */
+ btm_sco_acl_removed (p_lcb->remote_bd_addr);
#endif
/* If waiting for disconnect and reconnect is pending start the reconnect now
race condition where layer above issued connect request on link that was
disconnecting
*/
- if (p_lcb->ccb_queue.p_first_ccb != NULL)
+ if (p_lcb->ccb_queue.p_first_ccb != NULL || p_lcb->p_pending_ccb)
{
#if (L2CAP_NUM_FIXED_CHNLS > 0)
/* If we are going to re-use the LCB without dropping it, release all fixed channels here */
int xx;
-
for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
{
- if (p_lcb->p_fixed_ccbs[xx])
+ if (p_lcb->p_fixed_ccbs[xx] && p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb)
{
- (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason);
+#if BLE_INCLUDED == TRUE
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE,
+ p_lcb->disc_reason, p_lcb->transport);
+#else
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE,
+ p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
+#endif
l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
p_lcb->p_fixed_ccbs[xx] = NULL;
}
+#if BLE_INCLUDED == TRUE
+ else if (p_lcb->p_fixed_ccbs[xx] && p_lcb->p_fixed_ccbs[xx] ==
+ p_lcb->p_pending_ccb)
+ {
+ if (p_lcb->p_fixed_ccbs[xx]->local_cid >= L2CAP_ATT_CID &&
+ p_lcb->p_fixed_ccbs[xx]->local_cid <= L2CAP_SMP_CID)
+ transport = BT_TRANSPORT_LE;
+ }
+#endif
+
}
#endif
L2CAP_TRACE_DEBUG0("l2c_link_hci_disc_comp: Restarting pending ACL request");
- if (l2cu_create_conn(p_lcb))
+ if (l2cu_create_conn(p_lcb, transport))
lcb_is_free = FALSE; /* still using this lcb */
}
@@ -444,7 +465,7 @@
if (lcb_is_free && ((p_lcb = l2cu_find_lcb_by_state(LST_CONNECT_HOLDING)) != NULL))
{
/* we found one-- create a connection */
- l2cu_create_conn(p_lcb);
+ l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR);
}
return status;
@@ -576,6 +597,7 @@
}
else if (rc == BTM_SUCCESS)
{
+ l2cu_process_fixed_disc_cback(p_lcb);
/* BTM SEC will make sure that link is release (probably after pairing is done) */
p_lcb->link_state = LST_DISCONNECTING;
timeout = 0xFFFF;
@@ -588,6 +610,7 @@
else if ((p_lcb->is_bonding)
&& (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)))
{
+ l2cu_process_fixed_disc_cback(p_lcb);
p_lcb->link_state = LST_DISCONNECTING;
timeout = L2CAP_LINK_DISCONNECT_TOUT;
}
@@ -977,7 +1000,7 @@
if (bd_addr)
{
/* If here came form hci role change event */
- p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr);
+ p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_BR_EDR);
if (p_lcb)
{
p_lcb->link_role = new_role;
@@ -1013,7 +1036,7 @@
*******************************************************************************/
void l2c_pin_code_request (BD_ADDR bd_addr)
{
- tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr);
+ tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_BR_EDR);
if ( (p_lcb) && (!p_lcb->ccb_queue.p_first_ccb) )
{
@@ -1129,11 +1152,11 @@
/* If controller window is full, nothing to do */
if ( (l2cb.controller_xmit_window == 0
#if (BLE_INCLUDED == TRUE)
- && !p_lcb->is_ble_link
+ && (p_lcb->transport == BT_TRANSPORT_BR_EDR)
#endif
)
#if (BLE_INCLUDED == TRUE)
- || (p_lcb->is_ble_link && l2cb.controller_le_xmit_window == 0 )
+ || (p_lcb->transport == BT_TRANSPORT_LE && l2cb.controller_le_xmit_window == 0 )
#endif
|| (l2cb.round_robin_unacked >= l2cb.round_robin_quota) )
break;
@@ -1168,8 +1191,8 @@
/* If we finished without using up our quota, no need for a safety check */
#if (BLE_INCLUDED == TRUE)
- if ( ((l2cb.controller_xmit_window > 0 && !p_lcb->is_ble_link) ||
- (l2cb.controller_le_xmit_window > 0 && p_lcb->is_ble_link))
+ if ( ((l2cb.controller_xmit_window > 0 && (p_lcb->transport == BT_TRANSPORT_BR_EDR)) ||
+ (l2cb.controller_le_xmit_window > 0 && (p_lcb->transport == BT_TRANSPORT_LE)))
&& (l2cb.round_robin_unacked < l2cb.round_robin_quota) )
#else
if ( (l2cb.controller_xmit_window > 0)
@@ -1188,8 +1211,8 @@
/* See if we can send anything from the link queue */
#if (BLE_INCLUDED == TRUE)
- while ( ((l2cb.controller_xmit_window != 0 && !p_lcb->is_ble_link) ||
- (l2cb.controller_le_xmit_window != 0 && p_lcb->is_ble_link))
+ while ( ((l2cb.controller_xmit_window != 0 && (p_lcb->transport == BT_TRANSPORT_BR_EDR)) ||
+ (l2cb.controller_le_xmit_window != 0 && (p_lcb->transport == BT_TRANSPORT_LE)))
&& (p_lcb->sent_not_acked < p_lcb->link_xmit_quota))
#else
while ( (l2cb.controller_xmit_window != 0)
@@ -1207,8 +1230,8 @@
{
/* See if we can send anything for any channel */
#if (BLE_INCLUDED == TRUE)
- while ( ((l2cb.controller_xmit_window != 0 && !p_lcb->is_ble_link) ||
- (l2cb.controller_le_xmit_window != 0 && p_lcb->is_ble_link))
+ while ( ((l2cb.controller_xmit_window != 0 && (p_lcb->transport == BT_TRANSPORT_BR_EDR)) ||
+ (l2cb.controller_le_xmit_window != 0 && (p_lcb->transport == BT_TRANSPORT_LE)))
&& (p_lcb->sent_not_acked < p_lcb->link_xmit_quota))
#else
while ((l2cb.controller_xmit_window != 0) && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota))
@@ -1245,12 +1268,14 @@
UINT16 num_segs;
UINT16 xmit_window, acl_data_size;
+ if ((p_buf->len <= btu_cb.hcit_acl_pkt_size
#if (BLE_INCLUDED == TRUE)
- if ((!p_lcb->is_ble_link && (p_buf->len <= btu_cb.hcit_acl_pkt_size)) ||
- (p_lcb->is_ble_link && (p_buf->len <= btu_cb.hcit_ble_acl_pkt_size)))
+ && (p_lcb->transport == BT_TRANSPORT_BR_EDR)) ||
+ ((p_lcb->transport == BT_TRANSPORT_LE) && (p_buf->len <= btu_cb.hcit_ble_acl_pkt_size))
#else
- if (p_buf->len <= btu_cb.hcit_acl_pkt_size)
+ )
#endif
+ )
{
if (p_lcb->link_xmit_quota == 0)
l2cb.round_robin_unacked++;
@@ -1259,7 +1284,7 @@
p_buf->layer_specific = 0;
#if (BLE_INCLUDED == TRUE)
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
l2cb.controller_le_xmit_window--;
L2C_LINK_SEND_BLE_ACL_DATA (p_buf);
@@ -1274,7 +1299,7 @@
else
{
#if BLE_INCLUDED == TRUE
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
acl_data_size = btu_cb.hcit_ble_acl_data_size;
xmit_window = l2cb.controller_le_xmit_window;
@@ -1313,7 +1338,7 @@
p_buf->layer_specific = num_segs;
#if BLE_INCLUDED == TRUE
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
l2cb.controller_le_xmit_window -= num_segs;
@@ -1327,7 +1352,7 @@
p_lcb->sent_not_acked += num_segs;
#if BLE_INCLUDED == TRUE
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
L2C_LINK_SEND_BLE_ACL_DATA(p_buf);
}
@@ -1340,7 +1365,7 @@
#if (L2CAP_HCI_FLOW_CONTROL_DEBUG == TRUE)
#if (BLE_INCLUDED == TRUE)
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
L2CAP_TRACE_DEBUG6 ("TotalWin=%d,Hndl=0x%x,Quota=%d,Unack=%d,RRQuota=%d,RRUnack=%d",
l2cb.controller_le_xmit_window,
@@ -1400,11 +1425,9 @@
if (p_lcb)
{
#if (BLE_INCLUDED == TRUE)
- if (p_lcb->is_ble_link)
- {
- l2cb.controller_le_xmit_window += num_sent;
- }
- else
+ if (p_lcb && (p_lcb->transport == BT_TRANSPORT_LE))
+ l2cb.controller_le_xmit_window += num_sent;
+ else
#endif
{
/* Maintain the total window to the controller */
@@ -1441,7 +1464,7 @@
if (p_lcb)
{
#if (BLE_INCLUDED == TRUE)
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
L2CAP_TRACE_DEBUG5 ("TotalWin=%d,LinkUnack(0x%x)=%d,RRCheck=%d,RRUnack=%d",
l2cb.controller_le_xmit_window,
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index 49dd811..2795d8c 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -320,17 +320,29 @@
tL2CAP_CFG_INFO cfg_info;
UINT16 rej_reason, rej_mtu, lcid, rcid, info_type;
tL2C_CCB *p_ccb;
- tL2C_RCB *p_rcb;
- BOOLEAN cfg_rej;
+ tL2C_RCB *p_rcb, *p_rcb2;
+ BOOLEAN cfg_rej, pkt_size_rej = FALSE;
UINT16 cfg_rej_len, cmd_len;
UINT16 result;
tL2C_CONN_INFO ci;
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
/* if l2cap command received in CID 1 on top of an LE link, ignore this command */
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
return;
#endif
+
+ /* Reject the packet if it exceeds the default Signalling Channel MTU */
+ if (pkt_len > L2CAP_DEFAULT_MTU)
+ {
+ /* Core Spec requires a single response to the first command found in a multi-command
+ ** L2cap packet. If only responses in the packet, then it will be ignored.
+ ** Here we simply mark the bad packet and decide which cmd ID to reject later
+ */
+ pkt_size_rej = TRUE;
+ L2CAP_TRACE_ERROR1 ("L2CAP SIG MTU Pkt Len Exceeded (672) -> pkt_len: %d", pkt_len);
+ }
+
p_next_cmd = p;
p_pkt_end = p + pkt_len;
@@ -355,6 +367,18 @@
break;
}
+ L2CAP_TRACE_DEBUG3 ("cmd_code: %d, id:%d, cmd_len:%d", cmd_code, id, cmd_len);
+
+ /* Bad L2CAP packet length, look or cmd to reject */
+ if (pkt_size_rej)
+ {
+ /* If command found rejected it and we're done, otherwise keep looking */
+ if (l2c_is_cmd_rejected(cmd_code, id, p_lcb))
+ return;
+ else
+ continue; /* Look for next cmd/response in current packet */
+ }
+
switch (cmd_code)
{
case L2CAP_CMD_REJECT:
@@ -911,6 +935,11 @@
l2c_info_timeout((tL2C_LCB *)p_tle->param);
break;
+#if (BLE_INCLUDED == TRUE)
+ case BTU_TTYPE_L2CAP_END_CONN_UPD:
+ l2c_enable_conn_param_timeout((tL2C_LCB *)p_tle->param);
+ break;
+#endif
}
}
diff --git a/stack/l2cap/l2c_ucd.c b/stack/l2cap/l2c_ucd.c
index 4dfc804..4f907ad 100644
--- a/stack/l2cap/l2c_ucd.c
+++ b/stack/l2cap/l2c_ucd.c
@@ -343,7 +343,7 @@
/* First, see if we already have a link to the remote */
/* then find the channel control block for UCD. */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) == NULL)
+ if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
{
if ( l2c_ucd_connect (rem_bda) == FALSE )
@@ -411,7 +411,7 @@
/* First, see if we already have a link to the remote */
/* then find the channel control block for UCD */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) == NULL)
+ if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
{
if ( l2c_ucd_connect (rem_bda) == FALSE )
@@ -421,7 +421,7 @@
}
/* If we still don't have lcb and ccb after connect attempt, then can't proceed */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) == NULL)
+ if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
|| ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
{
GKI_freebuf (p_buf);
@@ -490,7 +490,7 @@
/* First, see if we already have a link to the remote */
/* then find the channel control block. */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) == NULL)
+ if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
{
L2CAP_TRACE_WARNING0 ("L2CAP - no UCD channel");
@@ -521,7 +521,7 @@
(rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
(rem_bda[4]<<8)+rem_bda[5]);
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
{
L2CAP_TRACE_WARNING0 ("L2CAP - no LCB for L2CA_UCDSetTxPriority");
return (FALSE);
@@ -569,11 +569,11 @@
}
/* First, see if we already have a link to the remote */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
{
/* No link. Get an LCB and start link establishment */
- if ( ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE)) == NULL)
- || (l2cu_create_conn(p_lcb) == FALSE) )
+ if ( ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE, BT_TRANSPORT_BR_EDR)) == NULL)
+ || (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE) )
{
L2CAP_TRACE_WARNING0 ("L2CAP - conn not started l2c_ucd_connect");
return (FALSE);
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index 05d5e5d..23b7584 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -37,6 +37,7 @@
#include "btm_int.h"
#include "hcidefs.h"
#include "bd.h"
+#include "bt_utils.h"
/*******************************************************************************
**
@@ -47,7 +48,7 @@
** Returns LCB address or NULL if none found
**
*******************************************************************************/
-tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding)
+tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPORT transport)
{
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
@@ -69,7 +70,9 @@
p_lcb->idle_timeout = l2cb.idle_timeout;
p_lcb->id = 1; /* spec does not allow '0' */
p_lcb->is_bonding = is_bonding;
-
+#if BLE_INCLUDED == TRUE
+ p_lcb->transport = transport;
+#endif
l2cb.num_links_active++;
l2c_link_adjust_allocation();
@@ -93,7 +96,7 @@
*******************************************************************************/
void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding)
{
- tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr);
+ tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR);
if (p_lcb)
{
@@ -133,14 +136,17 @@
}
#if BTM_SCO_INCLUDED == TRUE
- /* Release all SCO links */
- btm_remove_sco_links(p_lcb->remote_bd_addr);
+#if (BLE_INCLUDED == TRUE)
+ if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
+#endif
+ /* Release all SCO links */
+ btm_remove_sco_links(p_lcb->remote_bd_addr);
#endif
if (p_lcb->sent_not_acked > 0)
{
#if (BLE_INCLUDED == TRUE)
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs)
@@ -160,7 +166,6 @@
}
#if (BLE_INCLUDED == TRUE)
- p_lcb->is_ble_link = FALSE;
l2cb.is_ble_connecting = FALSE;
#endif
@@ -174,11 +179,11 @@
{
l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
p_lcb->p_fixed_ccbs[xx] = NULL;
- (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason);
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
}
else if ( (p_lcb->peer_chnl_mask[0] & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
&& (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) )
- (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason);
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
}
}
#endif
@@ -191,8 +196,11 @@
/* Tell BTM Acl management the link was removed */
if ((p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_DISCONNECTING))
- btm_acl_removed (p_lcb->remote_bd_addr);
-
+#if (BLE_INCLUDED == TRUE)
+ btm_acl_removed (p_lcb->remote_bd_addr, p_lcb->transport);
+#else
+ btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_BR_EDR);
+#endif
/* Release any held buffers */
while (p_lcb->link_xmit_data_q.p_first)
GKI_freebuf (GKI_dequeue (&p_lcb->link_xmit_data_q));
@@ -231,14 +239,18 @@
** Returns pointer to matched LCB, or NULL if no match
**
*******************************************************************************/
-tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr)
+tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport)
{
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++)
{
- if ((p_lcb->in_use) && (!memcmp (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN)))
+ if ((p_lcb->in_use) &&
+#if BLE_INCLUDED == TRUE
+ p_lcb->transport == transport &&
+#endif
+ (!memcmp (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN)))
{
return (p_lcb);
}
@@ -253,8 +265,6 @@
** Function l2cu_get_conn_role
**
** Description Determine the desired role (master or slave) of a link.
-** If it is the previous connected remote device, use the same
-** role as previous used role.
** If already got a slave link, this one must be a master. If
** already got at least 1 link where we are the master, make this
** also a master.
@@ -262,12 +272,12 @@
** Returns HCI_ROLE_MASTER or HCI_ROLE_SLAVE
**
*******************************************************************************/
-UINT8 l2cu_get_conn_role (BD_ADDR bd_addr)
+UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb)
{
UINT8 i;
for (i = 0; i < BTM_ROLE_DEVICE_NUM; i++) {
if ((btm_cb.previous_connected_role[i] != BTM_ROLE_UNDEFINED) &&
- (!bdcmp(bd_addr, btm_cb.previous_connected_remote_addr[i]))) {
+ (!bdcmp(p_this_lcb->remote_bd_addr, btm_cb.previous_connected_remote_addr[i]))) {
L2CAP_TRACE_WARNING1 ("l2cu_get_conn_role %d",
btm_cb.previous_connected_role[i]);
return btm_cb.previous_connected_role[i];
@@ -278,6 +288,39 @@
/*******************************************************************************
**
+** Function l2c_is_cmd_rejected
+**
+** Description Checks if cmd_code is command or response
+** If a command it will be rejected per spec.
+** This function is used when a illegal packet length is detected
+**
+** Returns BOOLEAN - TRUE if cmd_code is a command and it is rejected,
+** FALSE if response code. (command not rejected)
+**
+*******************************************************************************/
+BOOLEAN l2c_is_cmd_rejected (UINT8 cmd_code, UINT8 id, tL2C_LCB *p_lcb)
+{
+ switch(cmd_code)
+ {
+ case L2CAP_CMD_CONN_REQ:
+ case L2CAP_CMD_CONFIG_REQ:
+ case L2CAP_CMD_DISC_REQ:
+ case L2CAP_CMD_ECHO_REQ:
+ case L2CAP_CMD_INFO_REQ:
+ case L2CAP_CMD_AMP_CONN_REQ:
+ case L2CAP_CMD_AMP_MOVE_REQ:
+ case L2CAP_CMD_BLE_UPDATE_REQ:
+ l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id, L2CAP_DEFAULT_MTU, 0);
+ L2CAP_TRACE_WARNING1 ("Dumping first Command (%d)", cmd_code);
+ return TRUE;
+
+ default: /* Otherwise a response */
+ return FALSE;
+ }
+}
+
+/*******************************************************************************
+**
** Function l2cu_build_header
**
** Description Builds the L2CAP command packet header
@@ -311,7 +354,7 @@
UINT16_TO_STREAM (p, len + L2CAP_CMD_OVERHEAD);
#if (BLE_INCLUDED == TRUE)
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
UINT16_TO_STREAM (p, L2CAP_BLE_SIGNALLING_CID);
}
@@ -717,11 +760,24 @@
*******************************************************************************/
void l2cu_send_peer_config_rej (tL2C_CCB *p_ccb, UINT8 *p_data, UINT16 data_len, UINT16 rej_len)
{
- BT_HDR *p_buf = (BT_HDR *)GKI_getpoolbuf (L2CAP_CMD_POOL_ID);
- UINT16 len, cfg_len;
+ BT_HDR *p_buf;
+ UINT16 len, cfg_len, buf_space, len1;
UINT8 *p, *p_hci_len, *p_data_end;
UINT8 cfg_code;
+ L2CAP_TRACE_DEBUG2("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d", data_len, rej_len);
+
+
+ len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
+ len1 = 0xFFFF - len;
+ if (rej_len > len1)
+ {
+ L2CAP_TRACE_ERROR0 ("L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
+ return;
+ }
+
+ p_buf = (BT_HDR *)GKI_getbuf (len + rej_len);
+
if (!p_buf)
{
L2CAP_TRACE_ERROR0 ("L2CAP - no buffer for cfg_rej");
@@ -761,6 +817,8 @@
UINT16_TO_STREAM (p, 0); /* Flags = 0 (no continuation) */
UINT16_TO_STREAM (p, L2CAP_CFG_UNKNOWN_OPTIONS);
+ buf_space = rej_len;
+
/* Now, put the rejected options */
p_data_end = p_data + data_len;
while (p_data < p_data_end)
@@ -784,8 +842,18 @@
{
if ((cfg_code & 0x80) == 0)
{
- memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
- p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
+ if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD))
+ {
+ memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
+ p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
+ buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
+ }
+ else
+ {
+ L2CAP_TRACE_WARNING0("L2CAP - cfg_rej exceeds allocated buffer");
+ p_data = p_data_end; /* force loop exit */
+ break;
+ }
}
p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
}
@@ -803,6 +871,9 @@
p_buf->len = len + 4;
+ L2CAP_TRACE_DEBUG2 ("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d",
+ len, (L2CAP_CMD_OVERHEAD+L2CAP_CONFIG_RSP_LEN+rej_len));
+
l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
}
@@ -941,6 +1012,21 @@
BT_HDR *p_buf;
UINT8 *p;
UINT16 maxlen;
+ /* Filter out duplicate IDs or if available buffers are low (intruder checking) */
+ if (!id || id == p_lcb->cur_echo_id)
+ {
+ /* Dump this request since it is illegal */
+ L2CAP_TRACE_WARNING1 ("L2CAP ignoring duplicate echo request (%d)", id);
+ return;
+ }
+ else
+ p_lcb->cur_echo_id = id;
+ /* Don't respond if we more than 10% of our buffers are used */
+ if (GKI_poolutilization (L2CAP_CMD_POOL_ID) > 10)
+ {
+ L2CAP_TRACE_WARNING0 ("L2CAP gki pool used up to more than 10%%, ignore echo response");
+ return;
+ }
/* Don't return data if it does not fit in ACL and L2CAP MTU */
maxlen = (GKI_get_pool_bufsize(L2CAP_CMD_POOL_ID) > btu_cb.hcit_acl_pkt_size) ?
@@ -1069,7 +1155,7 @@
{
UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
#if (BLE_INCLUDED == TRUE)
- if (p_lcb->is_ble_link)
+ if (p_lcb->transport == BT_TRANSPORT_LE)
{
/* optional data are not added for now */
UINT32_TO_STREAM (p, L2CAP_BLE_EXTFEA_MASK);
@@ -2104,7 +2190,7 @@
** Returns TRUE if successful, FALSE if gki get buffer fails.
**
*******************************************************************************/
-BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb)
+BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
{
int xx;
tL2C_LCB *p_lcb_cur = &l2cb.lcb_pool[0];
@@ -2116,15 +2202,16 @@
tBT_DEVICE_TYPE dev_type;
tBLE_ADDR_TYPE addr_type;
+
BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
- if (dev_type == BT_DEVICE_TYPE_BLE)
+ if (transport == BT_TRANSPORT_LE)
{
if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
return FALSE;
p_lcb->ble_addr_type = addr_type;
- p_lcb->is_ble_link = TRUE;
+ p_lcb->transport = BT_TRANSPORT_LE;
return (l2cble_create_conn(p_lcb));
}
@@ -2154,7 +2241,7 @@
if (is_sco_active == TRUE)
continue; /* No Master Slave switch not allowed when SCO Active */
#endif
-
+ /*4_1_TODO check if btm_cb.devcb.local_features to be used instead */
if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures()))
{
/* mark this lcb waiting for switch to be completed and
@@ -2394,7 +2481,7 @@
APPL_TRACE_EVENT1("SET ACL PRIORITY %d", priority);
/* Find the link control block for the acl channel */
- if ((p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr)) == NULL)
+ if ((p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
{
L2CAP_TRACE_WARNING0 ("L2CAP - no LCB for L2CA_SetAclPriority");
return (FALSE);
@@ -2468,7 +2555,7 @@
/* If we are called with a BDA, only resubmit for that BDA */
if (p_bda)
{
- p_lcb = l2cu_find_lcb_by_bd_addr (p_bda);
+ p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
/* If we don't have one, this is an error */
if (p_lcb)
@@ -2663,11 +2750,13 @@
rc = btm_sec_disconnect (p_lcb->handle, HCI_ERR_PEER_USER);
if (rc == BTM_CMD_STARTED)
{
+ l2cu_process_fixed_disc_cback(p_lcb);
p_lcb->link_state = LST_DISCONNECTING;
timeout = L2CAP_LINK_DISCONNECT_TOUT;
}
else if (rc == BTM_SUCCESS)
{
+ l2cu_process_fixed_disc_cback(p_lcb);
/* BTM SEC will make sure that link is release (probably after pairing is done) */
p_lcb->link_state = LST_DISCONNECTING;
timeout = 0xFFFF;
@@ -2675,6 +2764,7 @@
else if ( (p_lcb->is_bonding)
&& (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) )
{
+ l2cu_process_fixed_disc_cback(p_lcb);
p_lcb->link_state = LST_DISCONNECTING;
timeout = L2CAP_LINK_DISCONNECT_TOUT;
}
@@ -2709,27 +2799,43 @@
void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
{
int xx;
-#if BLE_INCLUDED == TRUE
- UINT16 reason = (p_lcb->is_ble_link ) ? 1 : 0;
-#else
- UINT16 reason =0;
+#if (BLE_INCLUDED == TRUE)
+ /* always exclude LE fixed channel on BR/EDR fix channel capability */
+ if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
+ p_lcb->peer_chnl_mask[0] &= ~(L2CAP_FIXED_CHNL_ATT_BIT| \
+ L2CAP_FIXED_CHNL_BLE_SIG_BIT| \
+ L2CAP_FIXED_CHNL_SMP_BIT);
#endif
/* Tell all registered fixed channels about the connection */
for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
{
+#if BLE_INCLUDED == TRUE
+ /* skip sending LE fix channel callbacks on BR/EDR links */
+ if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
+ xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
+ xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID)
+ continue;
+#endif
if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL)
{
if (p_lcb->peer_chnl_mask[0] & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
{
if (p_lcb->p_fixed_ccbs[xx])
p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
-
- (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, reason);
+#if BLE_INCLUDED == TRUE
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, 0, p_lcb->transport);
+#else
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, 0, BT_TRANSPORT_BR_EDR);
+#endif
}
else
{
- (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason);
+#if BLE_INCLUDED == TRUE
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
+#else
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
+#endif
if (p_lcb->p_fixed_ccbs[xx])
{
@@ -2742,6 +2848,45 @@
}
#endif
+
+/*******************************************************************************
+**
+** Function l2cu_process_fixed_disc_cback
+**
+** Description send l2cap fixed channel disconnection callback to application
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb)
+{
+#if (L2CAP_NUM_FIXED_CHNLS > 0)
+ int xx;
+
+ for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
+ {
+ if (p_lcb->p_fixed_ccbs[xx])
+ {
+ l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
+ p_lcb->p_fixed_ccbs[xx] = NULL;
+#if BLE_INCLUDED == TRUE
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
+#else
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
+#endif
+ }
+ else if ( (p_lcb->peer_chnl_mask[0] & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
+ && (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) )
+#if BLE_INCLUDED == TRUE
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
+#else
+ (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
+#endif
+ }
+#endif
+}
+
#if (BLE_INCLUDED == TRUE)
/*******************************************************************************
**
@@ -3193,7 +3338,7 @@
UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
#endif
#if (BLE_INCLUDED == TRUE)
- if (p_ccb->p_lcb->is_ble_link)
+ if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
{
/* The HCI transport will segment the buffers. */
if (p_buf->len > btu_cb.hcit_ble_acl_data_size)
diff --git a/stack/mcap/mca_l2c.c b/stack/mcap/mca_l2c.c
index bc6fe09..d792bfc 100644
--- a/stack/mcap/mca_l2c.c
+++ b/stack/mcap/mca_l2c.c
@@ -70,12 +70,14 @@
** Returns void
**
*******************************************************************************/
-static void mca_sec_check_complete_term (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+static void mca_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
tMCA_TC_TBL *p_tbl = (tMCA_TC_TBL *)p_ref_data;
tL2CAP_CFG_INFO cfg;
tL2CAP_ERTM_INFO ertm_info;
+ UNUSED(transport);
+
MCA_TRACE_DEBUG1("mca_sec_check_complete_term res: %d", res);
if ( res == BTM_SUCCESS )
@@ -115,11 +117,12 @@
** Returns void
**
*******************************************************************************/
-static void mca_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+static void mca_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
tMCA_TC_TBL *p_tbl = (tMCA_TC_TBL *)p_ref_data;
tL2CAP_CFG_INFO cfg;
UNUSED(bd_addr);
+ UNUSED(transport);
MCA_TRACE_DEBUG1("mca_sec_check_complete_orig res: %d", res);
diff --git a/stack/pan/pan_api.c b/stack/pan/pan_api.c
index d08e527..e6275ea 100644
--- a/stack/pan/pan_api.c
+++ b/stack/pan/pan_api.c
@@ -492,7 +492,9 @@
** Description This sends data over the PAN connections. If this is called
** on GN or NAP side and the packet is multicast or broadcast
** it will be sent on all the links. Otherwise the correct link
-** is found based on the destination address and forwarded on it.
+** is found based on the destination address and forwarded on it
+** If the return value is not PAN_SUCCESS the application should
+** take care of releasing the message buffer
**
** Parameters: handle - handle for the connection
** dst - MAC or BD Addr of the destination device
@@ -507,39 +509,89 @@
** there is an error in sending data
**
*******************************************************************************/
-tPAN_RESULT PAN_Write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, UINT8 *p_data, UINT16 len, BOOLEAN ext)
+tPAN_RESULT PAN_Write (UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, UINT8 *p_data, UINT16 len, BOOLEAN ext)
{
- BT_HDR *buffer;
+ tPAN_CONN *pcb;
+ UINT16 i;
+ tBNEP_RESULT result;
- if (pan_cb.role == PAN_ROLE_INACTIVE || !pan_cb.num_conns) {
- PAN_TRACE_ERROR1("%s PAN is not active, data write failed.", __func__);
+ if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
+ {
+ PAN_TRACE_ERROR0 ("PAN is not active Data write failed");
return PAN_FAILURE;
}
- // If the packet is broadcast or multicast, we're going to have to create
- // a copy of the packet for each connection. We can save one extra copy
- // by fast-pathing here and calling BNEP_Write instead of placing the packet
- // in a BT_HDR buffer, calling BNEP_Write, and then freeing the buffer.
- if (dst[0] & 0x01) {
- int i;
- for (i = 0; i < MAX_PAN_CONNS; ++i) {
+ /* Check if it is broadcast or multicast packet */
+ if (dst[0] & 0x01)
+ {
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
}
+
return PAN_SUCCESS;
}
- buffer = (BT_HDR *)GKI_getpoolbuf(PAN_POOL_ID);
- if (!buffer) {
- PAN_TRACE_ERROR1("%s unable to acquire buffer from pool.", __func__);
- return PAN_NO_RESOURCES;
+ if (pan_cb.active_role == PAN_ROLE_CLIENT)
+ {
+ /* Data write is on PANU connection */
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
+ pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU)
+ break;
+ }
+
+ if (i == MAX_PAN_CONNS)
+ {
+ PAN_TRACE_ERROR0 ("PAN Don't have any user connections");
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
+ if (result == BNEP_IGNORE_CMD)
+ {
+ PAN_TRACE_DEBUG0 ("PAN ignored data for PANU connection");
+ return result;
+ }
+ else if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR0 ("PAN failed to write data for the PANU connection");
+ return result;
+ }
+
+ PAN_TRACE_DEBUG0 ("PAN successfully wrote data for the PANU connection");
+ return PAN_SUCCESS;
}
- buffer->len = len;
- buffer->offset = PAN_MINIMUM_OFFSET;
- memcpy((UINT8 *)buffer + sizeof(BT_HDR) + buffer->offset, p_data, buffer->len);
+ pcb = pan_get_pcb_by_handle (handle);
+ if (!pcb)
+ {
+ PAN_TRACE_ERROR0 ("PAN Data write for wrong addr");
+ return PAN_FAILURE;
+ }
- return PAN_WriteBuf(handle, dst, src, protocol, buffer, ext);
+ if (pcb->con_state != PAN_STATE_CONNECTED)
+ {
+ PAN_TRACE_ERROR0 ("PAN Data write when conn is not active");
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_Write (pcb->handle, dst, p_data, len, protocol, src, ext);
+ if (result == BNEP_IGNORE_CMD)
+ {
+ PAN_TRACE_DEBUG0 ("PAN ignored data write to PANU");
+ return result;
+ }
+ else if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR0 ("PAN failed to send data to the PANU");
+ return result;
+ }
+
+ PAN_TRACE_DEBUG0 ("PAN successfully sent data to the PANU");
+ return PAN_SUCCESS;
}
@@ -572,6 +624,19 @@
UINT16 i;
tBNEP_RESULT result;
+ /* Check if it is broadcast or multicast packet */
+ if (dst[0] & 0x01)
+ {
+ UINT8 *p_data;
+ UINT16 len;
+
+ p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
+ len = p_buf->len;
+ PAN_Write (handle, dst, src, protocol, p_data, len, ext);
+ GKI_freebuf (p_buf);
+ return PAN_SUCCESS;
+ }
+
if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
{
PAN_TRACE_ERROR0 ("PAN is not active Data write failed");
@@ -579,18 +644,6 @@
return PAN_FAILURE;
}
- /* Check if it is broadcast or multicast packet */
- if (dst[0] & 0x01)
- {
- UINT8 *data = (UINT8 *)p_buf + sizeof(BT_HDR) + p_buf->offset;
- for (i = 0; i < MAX_PAN_CONNS; ++i) {
- if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
- BNEP_Write(pan_cb.pcb[i].handle, dst, data, p_buf->len, protocol, src, ext);
- }
- GKI_freebuf(p_buf);
- return PAN_SUCCESS;
- }
-
/* Check if the data write is on PANU side */
if (pan_cb.active_role == PAN_ROLE_CLIENT)
{
diff --git a/stack/rfcomm/rfc_int.h b/stack/rfcomm/rfc_int.h
index 83a63e3..302a8af 100644
--- a/stack/rfcomm/rfc_int.h
+++ b/stack/rfcomm/rfc_int.h
@@ -315,7 +315,7 @@
extern void rfc_save_lcid_mcb (tRFC_MCB *p_rfc_mcb, UINT16 lcid);
extern void rfc_check_mcb_active (tRFC_MCB *p_mcb);
extern void rfc_port_closed (tPORT *p_port);
-extern void rfc_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 res);
+extern void rfc_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT transport,void *p_ref_data, UINT8 res);
extern void rfc_inc_credit (tPORT *p_port, UINT8 credit);
extern void rfc_dec_credit (tPORT *p_port);
extern void rfc_check_send_cmd(tRFC_MCB *p_mcb, BT_HDR *p_buf);
diff --git a/stack/rfcomm/rfc_utils.c b/stack/rfcomm/rfc_utils.c
index d2b02fc..47b093f 100644
--- a/stack/rfcomm/rfc_utils.c
+++ b/stack/rfcomm/rfc_utils.c
@@ -350,10 +350,11 @@
** Returns void
**
*******************************************************************************/
-void rfc_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+void rfc_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
tPORT *p_port = (tPORT *)p_ref_data;
UNUSED(bd_addr);
+ UNUSED(transport);
/* Verify that PORT is still waiting for Security to complete */
if (!p_port->in_use
diff --git a/stack/sdp/sdp_server.c b/stack/sdp/sdp_server.c
index 5d11cb4..84dd957 100644
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -380,8 +380,14 @@
else
{
/* Get a scratch buffer to store response */
- if (!p_ccb->rsp_list)
+ if (!p_ccb->rsp_list || (GKI_get_buf_size(p_ccb->rsp_list) < max_list_len))
{
+ /* Free and reallocate if the earlier allocated buffer is small */
+ if (p_ccb->rsp_list)
+ {
+ GKI_freebuf (p_ccb->rsp_list);
+ }
+
p_ccb->rsp_list = (UINT8 *)GKI_getbuf (max_list_len);
if (p_ccb->rsp_list == NULL)
{
@@ -624,8 +630,14 @@
else
{
/* Get a scratch buffer to store response */
- if (!p_ccb->rsp_list)
+ if (!p_ccb->rsp_list || (GKI_get_buf_size(p_ccb->rsp_list) < max_list_len))
{
+ /* Free and reallocate if the earlier allocated buffer is small */
+ if (p_ccb->rsp_list)
+ {
+ GKI_freebuf (p_ccb->rsp_list);
+ }
+
p_ccb->rsp_list = (UINT8 *)GKI_getbuf (max_list_len);
if (p_ccb->rsp_list == NULL)
{
diff --git a/stack/smp/aes.c b/stack/smp/aes.c
index 65cddf5..d3d8ff6 100644
--- a/stack/smp/aes.c
+++ b/stack/smp/aes.c
@@ -510,6 +510,7 @@
keylen = 24;
break;
case 32:
+ /* case 256: length in bits (256 = 8*32) */
keylen = 32;
break;
default:
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index 47cd2c9..7543eb7 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -26,6 +26,7 @@
#include "l2c_api.h"
#include "smp_int.h"
+#define MAX_KEY_DISTRIBUTION_TYPES 3
const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
{
@@ -108,6 +109,7 @@
{
p_cb->loc_auth_req = cb_data.io_req.auth_req;
p_cb->loc_io_caps = cb_data.io_req.io_cap;
+
#if (defined(BLE_PERIPHERAL_DISPLAYONLY) && (BLE_PERIPHERAL_DISPLAYONLY == TRUE))
if (p_cb->role == HCI_ROLE_SLAVE)
{
@@ -165,7 +167,11 @@
some peripherals are not able to revert to fast connection parameters
during the start of service discovery. Connection paramter updates
get enabled again once service discovery completes. */
- L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+ if (L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE) == FALSE)
+ {
+ SMP_TRACE_ERROR0 ("smp pair failed...!");
+ return;
+ }
#endif
/* erase all keys when master sends pairing req*/
@@ -616,7 +622,7 @@
*******************************************************************************/
void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- BOOLEAN cmd;
+ tBTM_STATUS cmd;
UINT8 reason = SMP_ENC_FAIL;
SMP_TRACE_DEBUG0 ("smp_start_enc ");
@@ -625,7 +631,7 @@
else
cmd = btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
- if (!cmd)
+ if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY)
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
}
@@ -729,7 +735,7 @@
UINT8 i = 0;
SMP_TRACE_DEBUG1 ("smp_key_pick_key key_to_dist=0x%x", key_to_dist);
- while (i < 3)
+ while (i < MAX_KEY_DISTRIBUTION_TYPES)
{
SMP_TRACE_DEBUG2("key to send = %02x, i = %d", key_to_dist, i);
@@ -899,6 +905,7 @@
SMP_TRACE_DEBUG0 ("smp_pairing_cmpl ");
+ (void)L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, TRUE);
if ((p_cb->status == SMP_SUCCESS) ||
(p_cb->status <= SMP_REPEATED_ATTEMPTS && p_cb->status != SMP_SUCCESS))
{
@@ -960,6 +967,18 @@
smp_proc_pairing_cmpl(p_cb);
}
}
+
+/*******************************************************************************
+** Function smp_fast_conn_param
+** Description apply default connection parameter for pairing process
+*******************************************************************************/
+void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ /* disable connection parameter update */
+ (void)L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+}
+
+
/*******************************************************************************
**
** Function smp_link_encrypted
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 51cdbb3..70c09a5 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -202,6 +202,8 @@
BD_ADDR local_bda;
BOOLEAN is_pair_cancel;
BOOLEAN discard_sec_req;
+ UINT8 rcvd_cmd_code;
+ UINT8 rcvd_cmd_len;
#if SMP_CONFORMANCE_TESTING == TRUE
BOOLEAN enable_test_confirm_val;
BT_OCTET16 test_confirm;
@@ -288,6 +290,8 @@
extern void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+
/* smp_l2c */
extern void smp_l2cap_if_init (void);
@@ -314,6 +318,7 @@
/* smp main util */
extern void smp_set_state(tSMP_STATE state);
extern tSMP_STATE smp_get_state(void);
+extern void smp_reject_unexp_pair_req(BD_ADDR bd_addr);
#endif /* SMP_INT_H */
diff --git a/stack/smp/smp_l2c.c b/stack/smp/smp_l2c.c
index 54b78b4..02ec38e 100644
--- a/stack/smp/smp_l2c.c
+++ b/stack/smp/smp_l2c.c
@@ -34,7 +34,7 @@
-static void smp_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason);
+static void smp_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason, tBT_TRANSPORT transport);
static void smp_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
/*******************************************************************************
@@ -73,13 +73,20 @@
** connected (conn = TRUE)/disconnected (conn = FALSE).
**
*******************************************************************************/
-static void smp_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason)
+static void smp_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
+ tBT_TRANSPORT transport)
{
tSMP_CB *p_cb = &smp_cb;
tSMP_INT_DATA int_data;
SMP_TRACE_EVENT0 ("SMDBG l2c smp_connect_cback ");
+ if (transport == BT_TRANSPORT_BR_EDR)
+ {
+ SMP_TRACE_ERROR0 ("smp_connect_cback : Wrong transport");
+ return;
+ }
+
if (memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0)
{
SMP_TRACE_EVENT3 ("smp_connect_cback() for pairing BDA: %08x%04x Event: %s",
@@ -132,6 +139,13 @@
STREAM_TO_UINT8(cmd, p);
+ /* sanity check */
+ if ((SMP_OPCODE_MAX <= cmd) || (cmd == 0))
+ {
+ SMP_TRACE_WARNING1( "Ignore received command with RESERVED code 0x%02x", cmd);
+ GKI_freebuf (p_buf);
+ return;
+ }
/* reject the pairing request if there is an on-going SMP pairing */
if (SMP_OPCODE_PAIRING_REQ == cmd || SMP_OPCODE_SEC_REQ == cmd)
@@ -143,14 +157,21 @@
}
else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN))
{
- p_cb->failure = SMP_PAIR_NOT_SUPPORT;
- smp_send_cmd(SMP_OPCODE_PAIRING_FAILED, p_cb);
+ GKI_freebuf (p_buf);
+ smp_reject_unexp_pair_req(bd_addr);
+ return;
}
+ /* else, out of state pairing request/security request received, passed into SM */
}
if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0)
{
- btu_stop_timer (&p_cb->rsp_timer_ent);
+ if (p_cb->state != SMP_ST_RELEASE_DELAY)
+ {
+ btu_stop_timer (&p_cb->rsp_timer_ent);
+ }
+ p_cb->rcvd_cmd_code = cmd;
+ p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
smp_sm_event(p_cb, cmd, p);
}
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index f8e450c..dd40a71 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -114,6 +114,8 @@
SMP_PROC_REL_DELAY,
SMP_PROC_REL_DELAY_TOUT,
SMP_DELAY_TERMINATE,
+ SMP_IDLE_TERMINATE,
+ SMP_FAST_CONN_PARAM,
SMP_SM_NO_ACTION
};
@@ -156,6 +158,8 @@
smp_proc_release_delay,
smp_proc_release_delay_tout,
smp_delay_terminate,
+ smp_idle_terminate,
+ smp_fast_conn_param
};
/************ SMP Master FSM State/Event Indirection Table **************/
static const UINT8 smp_ma_entry_map[][SMP_ST_MAX] =
@@ -176,7 +180,7 @@
/* 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 */{ 0x83, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 3 },
+/* L2C_DISC */{ 3, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 3 },
/* 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 },
@@ -198,15 +202,16 @@
static const UINT8 smp_ma_idle_table[][SMP_SM_NUM_COLS] = {
/* Event Action Next State */
/* L2C_CONN */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_ST_WAIT_APP_RSP},
-/* SEC_REQ */ {SMP_PROC_SEC_REQ, SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP}
+/* SEC_REQ */ {SMP_PROC_SEC_REQ, SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP},
+/* L2C_DISC */ {SMP_IDLE_TERMINATE, SMP_SM_NO_ACTION, SMP_ST_IDLE}
};
static const UINT8 smp_ma_wait_app_rsp_table[][SMP_SM_NUM_COLS] = {
/* Event Action Next State */
/* SEC_GRANT */ { SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP},
-/* IO_RSP */ { SMP_SEND_PAIR_REQ, SMP_SM_NO_ACTION, SMP_ST_PAIR_REQ_RSP},
+/* IO_RSP */ { SMP_SEND_PAIR_REQ, SMP_FAST_CONN_PARAM, SMP_ST_PAIR_REQ_RSP},
/* KEY_READY */ { SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION, SMP_ST_WAIT_CONFIRM},/* TK ready */
-/* ENC_REQ */ { SMP_START_ENC, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING},/* start enc mode setup */
+/* ENC_REQ */ { SMP_START_ENC, SMP_FAST_CONN_PARAM, SMP_ST_ENC_PENDING},/* start enc mode setup */
/* DISCARD_SEC_REQ */ { SMP_PROC_DISCARD, SMP_SM_NO_ACTION, SMP_ST_IDLE}
};
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index dac0cc0..38b2be8 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -621,6 +621,35 @@
smp_reset_control_value(p_cb);
}
+/*******************************************************************************
+**
+** Function smp_reject_unexp_pair_req
+**
+** Description send pairing failure to an unexpected pairing request during
+** an active pairing process.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_reject_unexp_pair_req(BD_ADDR bd_addr)
+{
+ BT_HDR *p_buf;
+ UINT8 *p;
+
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIR_FAIL_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+ {
+ p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+ UINT8_TO_STREAM (p, SMP_OPCODE_PAIRING_FAILED);
+ UINT8_TO_STREAM (p, SMP_PAIR_NOT_SUPPORT);
+
+ p_buf->offset = L2CAP_MIN_OFFSET;
+ p_buf->len = SMP_PAIR_FAIL_SIZE;
+
+ smp_send_msg_to_L2CAP(bd_addr, p_buf);
+ }
+}
+
#if SMP_CONFORMANCE_TESTING == TRUE
/*******************************************************************************
**
diff --git a/stack/srvc/srvc_dis.c b/stack/srvc/srvc_dis.c
index 90b4acd..73be84b 100644
--- a/stack/srvc/srvc_dis.c
+++ b/stack/srvc/srvc_dis.c
@@ -427,6 +427,9 @@
{
UINT16 conn_id;
+ /* Initialize the DIS client if it hasn't been initialized already. */
+ srvc_eng_init();
+
/* For now we only handle one at a time */
if (dis_cb.dis_read_uuid_idx != 0xff)
return(FALSE);
@@ -443,14 +446,14 @@
(peer_bda[4]<<8)+peer_bda[5], dis_attr_uuid[dis_cb.dis_read_uuid_idx]);
- GATT_GetConnIdIfConnected(srvc_eng_cb.gatt_if, peer_bda, &conn_id);
+ GATT_GetConnIdIfConnected(srvc_eng_cb.gatt_if, peer_bda, &conn_id, BT_TRANSPORT_LE);
/* need to enhance it as multiple service is needed */
srvc_eng_request_channel(peer_bda, SRVC_ID_DIS);
if (conn_id == GATT_INVALID_CONN_ID)
{
- return GATT_Connect(srvc_eng_cb.gatt_if, peer_bda, TRUE);
+ return GATT_Connect(srvc_eng_cb.gatt_if, peer_bda, TRUE, BT_TRANSPORT_LE);
}
return dis_gatt_c_read_dis_req(conn_id);
diff --git a/stack/srvc/srvc_eng.c b/stack/srvc/srvc_eng.c
index 4598738..bf730aa 100644
--- a/stack/srvc/srvc_eng.c
+++ b/stack/srvc/srvc_eng.c
@@ -30,7 +30,8 @@
#include "srvc_battery_int.h"
static void srvc_eng_s_request_cback (UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
-static void srvc_eng_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void srvc_eng_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected,
+ tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport);
static void srvc_eng_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
static tGATT_CBACK srvc_gatt_cback =
@@ -341,9 +342,10 @@
**
*******************************************************************************/
static void srvc_eng_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
- BOOLEAN connected, tGATT_DISCONN_REASON reason)
+ BOOLEAN connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport)
{
UNUSED(gatt_if);
+ UNUSED (transport);
GATT_TRACE_EVENT5 ("srvc_eng_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
(bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
diff --git a/test/bluedroidtest/Android.mk b/test/bluedroidtest/Android.mk
index 6bf8da5..36ef8fe 100644
--- a/test/bluedroidtest/Android.mk
+++ b/test/bluedroidtest/Android.mk
@@ -24,6 +24,8 @@
LOCAL_C_INCLUDES :=
LOCAL_CFLAGS := -Wno-unused-parameter
+LOCAL_CFLAGS += -std=c99
+
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE:= bdt
@@ -33,4 +35,6 @@
libhardware \
libhardware_legacy
+LOCAL_MULTILIB := 32
+
include $(BUILD_EXECUTABLE)
diff --git a/test/bluedroidtest/bluedroidtest.c b/test/bluedroidtest/bluedroidtest.c
index 1e39b98..4fc1559 100644
--- a/test/bluedroidtest/bluedroidtest.c
+++ b/test/bluedroidtest/bluedroidtest.c
@@ -58,6 +58,8 @@
#define CASE_RETURN_STR(const) case const: return #const;
+#define UNUSED __attribute__((unused))
+
/************************************************************************************
** Local type definitions
************************************************************************************/
@@ -469,7 +471,7 @@
}
}
-static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len)
+static void dut_mode_recv(uint16_t UNUSED opcode, uint8_t UNUSED *buf, uint8_t UNUSED len)
{
bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
}
@@ -611,7 +613,7 @@
** Console commands
*******************************************************************************/
-void do_help(char *p)
+void do_help(char UNUSED *p)
{
int i = 0;
int max = 0;
@@ -626,7 +628,7 @@
}
}
-void do_quit(char *p)
+void do_quit(char UNUSED *p)
{
bdt_shutdown();
}
@@ -639,17 +641,17 @@
*
*/
-void do_init(char *p)
+void do_init(char UNUSED *p)
{
bdt_init();
}
-void do_enable(char *p)
+void do_enable(char UNUSED *p)
{
bdt_enable();
}
-void do_disable(char *p)
+void do_disable(char UNUSED *p)
{
bdt_disable();
}
@@ -663,7 +665,7 @@
bdt_le_test_mode(p);
}
-void do_cleanup(char *p)
+void do_cleanup(char UNUSED *p)
{
bdt_cleanup();
}
@@ -731,7 +733,7 @@
do_help(NULL);
}
-int main (int argc, char * argv[])
+int main (int UNUSED argc, char UNUSED *argv[])
{
int opt;
char cmd[128];
diff --git a/test/suite/Android.mk b/test/suite/Android.mk
new file mode 100644
index 0000000..2f45180
--- /dev/null
+++ b/test/suite/Android.mk
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2014 Google, Inc.
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := bdtest
+
+LOCAL_SRC_FILES := \
+ cases/adapter.c \
+ cases/cases.c \
+ cases/pan.c \
+ support/adapter.c \
+ support/callbacks.c \
+ support/hal.c \
+ support/pan.c \
+ support/property.c \
+ main.c
+
+LOCAL_SHARED_LIBRARIES += \
+ libhardware \
+ libhardware_legacy
+
+LOCAL_CFLAGS += -std=c99 -Wall -Wno-unused-parameter -Wno-missing-field-initializers -Werror
+
+LOCAL_MULTILIB := 32
+
+include $(BUILD_EXECUTABLE)
diff --git a/test/suite/base.h b/test/suite/base.h
new file mode 100644
index 0000000..2d51af8
--- /dev/null
+++ b/test/suite/base.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_pan.h>
+#include <hardware/hardware.h>
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#define TASSERT(c, ...) if (!(c)) { fprintf(stderr, "%s:%d: ", __func__, __LINE__); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); return false; }
+
+extern const bt_interface_t *bt_interface;
+extern bt_bdaddr_t bt_remote_bdaddr;
diff --git a/test/suite/cases/adapter.c b/test/suite/cases/adapter.c
new file mode 100644
index 0000000..492d8f4
--- /dev/null
+++ b/test/suite/cases/adapter.c
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "support/adapter.h"
+#include "support/callbacks.h"
+#include "support/property.h"
+
+bool adapter_enable_disable() {
+ int error;
+
+ CALL_AND_WAIT(error = bt_interface->enable(), adapter_state_changed);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error enabling Bluetooth: %d", error);
+ TASSERT(adapter_get_state() == BT_STATE_ON, "Adapter did not turn on.");
+
+ CALL_AND_WAIT(error = bt_interface->disable(), adapter_state_changed);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error disabling Bluetooth: %d", error);
+ TASSERT(adapter_get_state() == BT_STATE_OFF, "Adapter did not turn off.");
+
+ return true;
+}
+
+bool adapter_repeated_enable_disable() {
+ for (int i = 0; i < 10; ++i) {
+ if (!adapter_enable_disable()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool adapter_set_name() {
+ int error;
+ bt_property_t *name = property_new_name("set_name");
+
+ CALL_AND_WAIT(error = bt_interface->set_adapter_property(name), adapter_properties);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error setting device name.");
+ TASSERT(adapter_get_property_count() == 1, "Expected 1 adapter property change, found %d instead.", adapter_get_property_count());
+ TASSERT(adapter_get_property(BT_PROPERTY_BDNAME), "The Bluetooth name property did not change.");
+ TASSERT(property_equals(adapter_get_property(BT_PROPERTY_BDNAME), name), "Bluetooth name '%s' does not match test value", property_extract_name(adapter_get_property(BT_PROPERTY_BDNAME)));
+
+ property_free(name);
+
+ return true;
+}
+
+bool adapter_get_name() {
+ int error;
+ bt_property_t *name = property_new_name("get_name");
+
+ CALL_AND_WAIT(bt_interface->set_adapter_property(name), adapter_properties);
+ CALL_AND_WAIT(error = bt_interface->get_adapter_property(BT_PROPERTY_BDNAME), adapter_properties);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error getting device name.");
+ TASSERT(adapter_get_property_count() == 1, "Expected 1 adapter property change, found %d instead.", adapter_get_property_count());
+ TASSERT(adapter_get_property(BT_PROPERTY_BDNAME), "The Bluetooth name property did not change.");
+ TASSERT(property_equals(adapter_get_property(BT_PROPERTY_BDNAME), name), "Bluetooth name '%s' does not match test value", property_extract_name(adapter_get_property(BT_PROPERTY_BDNAME)));
+
+ property_free(name);
+ return true;
+}
+
+bool adapter_start_discovery() {
+ int error;
+
+ CALL_AND_WAIT(error = bt_interface->start_discovery(), discovery_state_changed);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error calling start_discovery: %d", error);
+ TASSERT(adapter_get_discovery_state() == BT_DISCOVERY_STARTED, "Unable to start discovery.");
+
+ return true;
+}
+
+bool adapter_cancel_discovery() {
+ int error;
+
+ CALL_AND_WAIT(bt_interface->start_discovery(), discovery_state_changed);
+ CALL_AND_WAIT(error = bt_interface->cancel_discovery(), discovery_state_changed);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error calling cancel_discovery: %d", error);
+ TASSERT(adapter_get_discovery_state() == BT_DISCOVERY_STOPPED, "Unable to stop discovery.");
+
+ return true;
+}
diff --git a/test/suite/cases/cases.c b/test/suite/cases/cases.c
new file mode 100644
index 0000000..20d941f
--- /dev/null
+++ b/test/suite/cases/cases.c
@@ -0,0 +1,53 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "cases/cases.h"
+
+TEST_CASE_DECL(adapter_enable_disable);
+TEST_CASE_DECL(adapter_repeated_enable_disable);
+TEST_CASE_DECL(adapter_set_name);
+TEST_CASE_DECL(adapter_get_name);
+TEST_CASE_DECL(adapter_start_discovery);
+TEST_CASE_DECL(adapter_cancel_discovery);
+
+TEST_CASE_DECL(pan_enable);
+TEST_CASE_DECL(pan_connect);
+TEST_CASE_DECL(pan_disconnect);
+TEST_CASE_DECL(pan_quick_reconnect);
+
+// These are run with the Bluetooth adapter disabled.
+const test_case_t sanity_suite[] = {
+ TEST_CASE(adapter_enable_disable),
+ TEST_CASE(adapter_repeated_enable_disable),
+};
+
+// The normal test suite is run with the adapter enabled.
+const test_case_t test_suite[] = {
+ TEST_CASE(adapter_set_name),
+ TEST_CASE(adapter_get_name),
+ TEST_CASE(adapter_start_discovery),
+ TEST_CASE(adapter_cancel_discovery),
+
+ TEST_CASE(pan_enable),
+ TEST_CASE(pan_connect),
+ TEST_CASE(pan_disconnect),
+};
+
+const size_t sanity_suite_size = ARRAY_SIZE(sanity_suite);
+const size_t test_suite_size = ARRAY_SIZE(test_suite);
diff --git a/test/suite/cases/cases.h b/test/suite/cases/cases.h
new file mode 100644
index 0000000..b20950b
--- /dev/null
+++ b/test/suite/cases/cases.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "base.h"
+
+#define TEST_CASE_DECL(x) bool x()
+#define TEST_CASE(x) { x, #x }
+
+typedef struct {
+ bool (*function)();
+ const char *function_name;
+} test_case_t;
+
+extern const test_case_t test_suite[];
+extern const test_case_t sanity_suite[];
+extern const size_t test_suite_size;
+extern const size_t sanity_suite_size;
diff --git a/test/suite/cases/pan.c b/test/suite/cases/pan.c
new file mode 100644
index 0000000..b903b90
--- /dev/null
+++ b/test/suite/cases/pan.c
@@ -0,0 +1,84 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "support/callbacks.h"
+#include "support/pan.h"
+
+static const int local_role = BTPAN_ROLE_PANU;
+static const int remote_role = BTPAN_ROLE_PANNAP;
+
+bool pan_enable() {
+ int error;
+
+ // PAN is enabled by default, wait for the first control state change
+ // with default parameters set. We don't want to verify the result since
+ // the implementation could have set any parameters.
+ WAIT(pan_control_state_changed);
+
+ // Call enable explicitly and verify that the parameters match what we just set.
+ CALL_AND_WAIT(error = pan_interface->enable(local_role), pan_control_state_changed);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error enabling PAN: %d", error);
+ TASSERT(pan_get_control_state() == BTPAN_STATE_ENABLED, "Control state is disabled.");
+ TASSERT(pan_get_local_role() == local_role, "Unexpected local role: %d", pan_get_local_role());
+ TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error in control callback: %d", pan_get_error());
+
+ return true;
+}
+
+bool pan_connect() {
+ int error;
+
+ if (!pan_enable()) {
+ return false;
+ }
+
+ CALL_AND_WAIT(error = pan_interface->connect(&bt_remote_bdaddr, local_role, remote_role), pan_connection_state_changed);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error connecting to remote host: %d", error);
+ TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error connecting to BT device: %d", pan_get_error());
+ TASSERT(pan_get_connection_state() == BTPAN_STATE_CONNECTING, "Invalid PAN state after connect: %d", pan_get_connection_state());
+ TASSERT(pan_get_local_role() == local_role, "Incorrect local role: %d", pan_get_local_role());
+ TASSERT(pan_get_remote_role() == remote_role, "Incorrect remote role: %d", pan_get_remote_role());
+
+ WAIT(pan_connection_state_changed);
+ TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error connecting to BT device: %d", pan_get_error());
+ TASSERT(pan_get_connection_state() == BTPAN_STATE_CONNECTED, "Invalid PAN state after connect: %d", pan_get_connection_state());
+ TASSERT(pan_get_local_role() == local_role, "Incorrect local role: %d", pan_get_local_role());
+ TASSERT(pan_get_remote_role() == remote_role, "Incorrect remote role: %d", pan_get_remote_role());
+
+ return true;
+}
+
+bool pan_disconnect() {
+ int error;
+
+ if (!pan_connect()) {
+ return false;
+ }
+
+ CALL_AND_WAIT(error = pan_interface->disconnect(&bt_remote_bdaddr), pan_connection_state_changed);
+ TASSERT(error == BT_STATUS_SUCCESS, "Error disconnecting from remote host: %d", error);
+ TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error disconnecting from BT device: %d", pan_get_error());
+ TASSERT(pan_get_connection_state() == BTPAN_STATE_DISCONNECTING, "Invalid PAN state after disconnect: %d", pan_get_connection_state());
+
+ WAIT(pan_connection_state_changed);
+ TASSERT(pan_get_error() == BT_STATUS_SUCCESS, "Error disconnecting from BT device: %d", pan_get_error());
+ TASSERT(pan_get_connection_state() == BTPAN_STATE_DISCONNECTED, "Invalid PAN state after disconnect: %d", pan_get_connection_state());
+
+ return true;
+}
diff --git a/test/suite/main.c b/test/suite/main.c
new file mode 100644
index 0000000..7a3af5b
--- /dev/null
+++ b/test/suite/main.c
@@ -0,0 +1,114 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "cases/cases.h"
+#include "support/callbacks.h"
+#include "support/hal.h"
+#include "support/pan.h"
+
+#define GRAY "\x1b[0;37m"
+#define GREEN "\x1b[0;32m"
+#define RED "\x1b[0;31m"
+
+const bt_interface_t *bt_interface;
+bt_bdaddr_t bt_remote_bdaddr;
+
+static bool parse_bdaddr(const char *str, bt_bdaddr_t *addr) {
+ if (!addr) {
+ return false;
+ }
+
+ int v[6];
+ if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]) != 6) {
+ return false;
+ }
+
+ for (int i = 0; i < 6; ++i) {
+ addr->address[i] = (uint8_t)v[i];
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv) {
+ if (argc < 2 || !parse_bdaddr(argv[1], &bt_remote_bdaddr)) {
+ printf("Usage: %s <bdaddr>\n", argv[0]);
+ return -1;
+ }
+
+ if (!hal_open(callbacks_get_adapter_struct())) {
+ printf("Unable to open Bluetooth HAL.\n");
+ return 1;
+ }
+
+ if (!pan_init()) {
+ printf("Unable to initialize PAN.\n");
+ return 2;
+ }
+
+ int pass = 0;
+ int fail = 0;
+ int case_num = 0;
+
+ // Run through the sanity suite.
+ for (size_t i = 0; i < sanity_suite_size; ++i) {
+ callbacks_init();
+ if (sanity_suite[i].function()) {
+ printf("[%4d] %-64s [%sPASS%s]\n", ++case_num, sanity_suite[i].function_name, GREEN, GRAY);
+ ++pass;
+ } else {
+ printf("[%4d] %-64s [%sFAIL%s]\n", ++case_num, sanity_suite[i].function_name, RED, GRAY);
+ ++fail;
+ }
+ callbacks_cleanup();
+ }
+
+ // If there was a failure in the sanity suite, don't bother running the rest of the tests.
+ if (fail) {
+ printf("\n%sSanity suite failed with %d errors.%s\n", RED, fail, GRAY);
+ hal_close();
+ return 0;
+ }
+
+ // Run the full test suite.
+ for (size_t i = 0; i < test_suite_size; ++i) {
+ callbacks_init();
+ CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+ if (test_suite[i].function()) {
+ printf("[%4d] %-64s [%sPASS%s]\n", ++case_num, test_suite[i].function_name, GREEN, GRAY);
+ ++pass;
+ } else {
+ printf("[%4d] %-64s [%sFAIL%s]\n", ++case_num, test_suite[i].function_name, RED, GRAY);
+ ++fail;
+ }
+ CALL_AND_WAIT(bt_interface->disable(), adapter_state_changed);
+ callbacks_cleanup();
+ }
+
+ printf("\n");
+
+ if (fail) {
+ printf("%d/%d tests failed. See above for failed test cases.\n", fail, test_suite_size);
+ } else {
+ printf("All tests passed!\n");
+ }
+
+ hal_close();
+ return 0;
+}
diff --git a/test/suite/support/adapter.c b/test/suite/support/adapter.c
new file mode 100644
index 0000000..0a78253
--- /dev/null
+++ b/test/suite/support/adapter.c
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "support/adapter.h"
+#include "support/callbacks.h"
+#include "support/property.h"
+
+static bt_state_t state;
+static int property_count = 0;
+static bt_property_t *properties = NULL;
+static bt_discovery_state_t discovery_state;
+
+bt_state_t adapter_get_state() {
+ return state;
+}
+
+int adapter_get_property_count() {
+ return property_count;
+}
+
+bt_property_t *adapter_get_property(bt_property_type_t type) {
+ for (int i = 0; i < property_count; ++i) {
+ if (properties[i].type == type) {
+ return &properties[i];
+ }
+ }
+
+ return NULL;
+}
+
+bt_discovery_state_t adapter_get_discovery_state() {
+ return discovery_state;
+}
+
+// callback
+void adapter_state_changed(bt_state_t new_state) {
+ state = new_state;
+ CALLBACK_RET();
+}
+
+// callback
+void adapter_properties(bt_status_t status,
+ int num_properties,
+ bt_property_t *new_properties) {
+ property_free_array(properties, property_count);
+ properties = property_copy_array(new_properties, num_properties);
+ property_count = num_properties;
+
+ CALLBACK_RET();
+}
+
+// callback
+void discovery_state_changed(bt_discovery_state_t state) {
+ discovery_state = state;
+ CALLBACK_RET();
+}
diff --git a/test/suite/support/adapter.h b/test/suite/support/adapter.h
new file mode 100644
index 0000000..0f5883f
--- /dev/null
+++ b/test/suite/support/adapter.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "base.h"
+
+bt_state_t adapter_get_state();
+int adapter_get_property_count();
+bt_property_t *adapter_get_property(bt_property_type_t type);
+bt_discovery_state_t adapter_get_discovery_state();
diff --git a/test/suite/support/callbacks.c b/test/suite/support/callbacks.c
new file mode 100644
index 0000000..2ad12cf
--- /dev/null
+++ b/test/suite/support/callbacks.c
@@ -0,0 +1,114 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "support/callbacks.h"
+
+void adapter_state_changed(bt_state_t state);
+void adapter_properties(bt_status_t status,
+ int num_properties,
+ bt_property_t *properties);
+void discovery_state_changed(bt_discovery_state_t state);
+
+void pan_control_state_changed(btpan_control_state_t state, int local_role, bt_status_t error, const char *ifname);
+void pan_connection_state_changed(btpan_connection_state_t state, bt_status_t error, const bt_bdaddr_t *bd_addr, int local_role, int remote_role);
+
+static void remote_device_properties(bt_status_t status,
+ bt_bdaddr_t *bd_addr,
+ int num_properties,
+ bt_property_t *properties) {
+ CALLBACK_RET();
+}
+
+static void thread_evt(bt_cb_thread_evt evt) {
+ CALLBACK_RET();
+}
+
+static struct {
+ const char *name;
+ sem_t semaphore;
+} callback_data[] = {
+ // Adapter callbacks
+ { "adapter_state_changed" },
+ { "adapter_properties" },
+ { "remote_device_properties" },
+ {},
+ { "discovery_state_changed" },
+ {},
+ {},
+ {},
+ {},
+ { "thread_evt" },
+ {},
+ {},
+
+ // PAN callbacks
+ { "pan_control_state_changed" },
+ { "pan_connection_state_changed" },
+};
+
+static bt_callbacks_t bt_callbacks = {
+ sizeof(bt_callbacks_t),
+ adapter_state_changed, // adapter_state_changed_callback
+ adapter_properties, // adapter_properties_callback
+ remote_device_properties, // remote_device_properties_callback
+ NULL, // device_found_callback
+ discovery_state_changed, // discovery_state_changed_callback
+ NULL, // pin_request_callback
+ NULL, // ssp_request_callback
+ NULL, // bond_state_changed_callback
+ NULL, // acl_state_changed_callback
+ thread_evt, // callback_thread_event
+ NULL, // dut_mode_recv_callback
+ NULL, // le_test_mode_callback
+};
+
+static btpan_callbacks_t pan_callbacks = {
+ sizeof(btpan_callbacks_t),
+ pan_control_state_changed, // btpan_control_state_callback
+ pan_connection_state_changed, // btpan_connection_state_callback
+};
+
+void callbacks_init() {
+ for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
+ sem_init(&callback_data[i].semaphore, 0, 0);
+ }
+}
+
+void callbacks_cleanup() {
+ for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
+ sem_destroy(&callback_data[i].semaphore);
+ }
+}
+
+bt_callbacks_t *callbacks_get_adapter_struct() {
+ return &bt_callbacks;
+}
+
+btpan_callbacks_t *callbacks_get_pan_struct() {
+ return &pan_callbacks;
+}
+
+sem_t *callbacks_get_semaphore(const char *name) {
+ for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
+ if (callback_data[i].name && !strcmp(name, callback_data[i].name)) {
+ return &callback_data[i].semaphore;
+ }
+ }
+ return NULL;
+}
diff --git a/test/suite/support/callbacks.h b/test/suite/support/callbacks.h
new file mode 100644
index 0000000..102e13f
--- /dev/null
+++ b/test/suite/support/callbacks.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "base.h"
+
+#include <semaphore.h>
+
+#define WAIT(callback) \
+ do { \
+ sem_t *semaphore = callbacks_get_semaphore(#callback); \
+ sem_wait(semaphore); \
+ } while (0)
+
+#define CALL_AND_WAIT(expression, callback) \
+ do { \
+ sem_t *semaphore = callbacks_get_semaphore(#callback); \
+ while (!sem_trywait(semaphore)); \
+ expression; \
+ sem_wait(semaphore); \
+ } while(0)
+
+// To be called from every exit point of the callback. This macro
+// takes 0 or 1 arguments, the return value of the callback.
+#define CALLBACK_RET(...) do { \
+ sem_t *semaphore = callbacks_get_semaphore(__func__); \
+ sem_post(semaphore); \
+ return __VA_ARGS__; \
+ } while (0)
+
+void callbacks_init();
+void callbacks_cleanup();
+
+bt_callbacks_t *callbacks_get_adapter_struct();
+btpan_callbacks_t *callbacks_get_pan_struct();
+sem_t *callbacks_get_semaphore(const char *name);
diff --git a/test/suite/support/hal.c b/test/suite/support/hal.c
new file mode 100644
index 0000000..3525439
--- /dev/null
+++ b/test/suite/support/hal.c
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "support/hal.h"
+
+static const bluetooth_device_t *bt_device;
+
+bool hal_open(bt_callbacks_t *callbacks) {
+ hw_module_t *module;
+ if (hw_get_module(BT_STACK_MODULE_ID, (hw_module_t const **)&module)) {
+ return false;
+ }
+
+ hw_device_t *device;
+ if (module->methods->open(module, BT_STACK_MODULE_ID, &device)) {
+ return false;
+ }
+
+ bt_device = (bluetooth_device_t *)device;
+ bt_interface = bt_device->get_bluetooth_interface();
+ if (!bt_interface) {
+ bt_device->common.close((hw_device_t *)&bt_device->common);
+ bt_device = NULL;
+ return false;
+ }
+
+ return bt_interface->init(callbacks) == BT_STATUS_SUCCESS;
+}
+
+void hal_close() {
+ if (bt_interface) {
+ bt_interface->cleanup();
+ bt_interface = NULL;
+ }
+
+ if (bt_device) {
+ bt_device->common.close((hw_device_t *)&bt_device->common);
+ bt_device = NULL;
+ }
+}
diff --git a/test/suite/support/hal.h b/test/suite/support/hal.h
new file mode 100644
index 0000000..11fa9f9
--- /dev/null
+++ b/test/suite/support/hal.h
@@ -0,0 +1,24 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "base.h"
+
+bool hal_open(bt_callbacks_t *callbacks);
+void hal_close();
diff --git a/test/suite/support/pan.c b/test/suite/support/pan.c
new file mode 100644
index 0000000..df4c516
--- /dev/null
+++ b/test/suite/support/pan.c
@@ -0,0 +1,76 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "support/callbacks.h"
+#include "support/pan.h"
+
+const btpan_interface_t *pan_interface;
+
+static btpan_control_state_t pan_control_state;
+static btpan_connection_state_t pan_connection_state;
+static int pan_local_role;
+static int pan_remote_role;
+static bt_status_t pan_error;
+static char *pan_ifname;
+
+bool pan_init() {
+ pan_interface = bt_interface->get_profile_interface(BT_PROFILE_PAN_ID);
+ return pan_interface->init(callbacks_get_pan_struct()) == BT_STATUS_SUCCESS;
+}
+
+btpan_control_state_t pan_get_control_state() {
+ return pan_control_state;
+}
+
+btpan_connection_state_t pan_get_connection_state() {
+ return pan_connection_state;
+}
+
+int pan_get_local_role() {
+ return pan_local_role;
+}
+
+int pan_get_remote_role() {
+ return pan_remote_role;
+}
+
+bt_status_t pan_get_error() {
+ return pan_error;
+}
+
+// callback
+void pan_control_state_changed(btpan_control_state_t state, bt_status_t error, int local_role, const char *ifname) {
+ free(pan_ifname);
+
+ pan_control_state = state;
+ pan_local_role = local_role;
+ pan_error = error;
+ pan_ifname = strdup(ifname);
+
+ CALLBACK_RET();
+}
+
+// callback
+void pan_connection_state_changed(btpan_connection_state_t state, bt_status_t error, const bt_bdaddr_t *bd_addr, int local_role, int remote_role) {
+ pan_connection_state = state;
+ pan_error = error;
+ pan_local_role = local_role;
+ pan_remote_role = remote_role;
+ CALLBACK_RET();
+}
diff --git a/test/suite/support/pan.h b/test/suite/support/pan.h
new file mode 100644
index 0000000..f43eb24
--- /dev/null
+++ b/test/suite/support/pan.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "base.h"
+
+extern const btpan_interface_t *pan_interface;
+
+bool pan_init();
+
+btpan_control_state_t pan_get_control_state();
+btpan_connection_state_t pan_get_connection_state();
+int pan_get_local_role();
+int pan_get_remote_role();
+bt_status_t pan_get_error();
diff --git a/test/suite/support/property.c b/test/suite/support/property.c
new file mode 100644
index 0000000..ea2c5c4
--- /dev/null
+++ b/test/suite/support/property.c
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 "base.h"
+#include "support/property.h"
+
+bt_property_t *property_copy_array(const bt_property_t *properties, size_t count) {
+ bt_property_t *clone = calloc(sizeof(bt_property_t), count);
+ if (!clone) {
+ return NULL;
+ }
+
+ memcpy(&clone[0], &properties[0], sizeof(bt_property_t) * count);
+ for (size_t i = 0; i < count; ++i) {
+ clone[i].val = calloc(clone[i].len, 1);
+ memcpy(clone[i].val, properties[i].val, clone[i].len);
+ }
+
+ return clone;
+}
+
+bt_property_t *property_new_name(const char *name) {
+ bt_bdname_t *bdname = calloc(sizeof(bt_bdname_t), 1);
+ bt_property_t *property = calloc(sizeof(bt_property_t), 1);
+
+ property->type = BT_PROPERTY_BDNAME;
+ property->val = bdname;
+ property->len = sizeof(bt_bdname_t);
+
+ strlcpy((char *)bdname->name, name, sizeof(bdname->name));
+
+ return property;
+}
+
+bt_property_t *property_new_discovery_timeout(uint32_t timeout) {
+ uint32_t *val = malloc(sizeof(uint32_t));
+ bt_property_t *property = malloc(sizeof(bt_property_t));
+
+ property->type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
+ property->val = val;
+ property->len = sizeof(uint32_t);
+
+ *val = timeout;
+
+ return property;
+}
+
+// Warning: not thread safe.
+const char *property_extract_name(const bt_property_t *property) {
+ static char name[250] = { 0 };
+ if (!property || property->type != BT_PROPERTY_BDNAME || !property->val) {
+ return NULL;
+ }
+
+ strncpy(name, (const char *)((bt_bdname_t *)property->val)->name, property->len);
+ name[sizeof(name) - 1] = '\0';
+
+ return name;
+}
+
+bool property_equals(const bt_property_t *p1, const bt_property_t *p2) {
+ // Two null properties are not the same. May need to revisit that
+ // decision when we have a test case that exercises that condition.
+ if (!p1 || !p2 || p1->type != p2->type) {
+ return false;
+ }
+
+ // Although the Bluetooth name is a 249-byte array, the implementation
+ // treats it like a variable-length array with its size specified in the
+ // property's `len` field. We special-case the equivalence of BDNAME
+ // types here by truncating the larger, zero-padded name to its string
+ // length and comparing against the shorter name.
+ //
+ // Note: it may be the case that both strings are zero-padded but that
+ // hasn't come up yet so this implementation doesn't handle it.
+ if (p1->type == BT_PROPERTY_BDNAME && p1->len != p2->len) {
+ const bt_property_t *shorter = p1, *longer = p2;
+ if (p1->len > p2->len) {
+ shorter = p2;
+ longer = p1;
+ }
+ return strlen((const char *)longer->val) == (size_t)shorter->len && !memcmp(longer->val, shorter->val, shorter->len);
+ }
+
+ return p1->len == p2->len && !memcmp(p1->val, p2->val, p1->len);
+}
+
+void property_free(bt_property_t *property) {
+ property_free_array(property, 1);
+}
+
+void property_free_array(bt_property_t *properties, size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ free(properties[i].val);
+ }
+
+ free(properties);
+}
diff --git a/test/suite/support/property.h b/test/suite/support/property.h
new file mode 100644
index 0000000..a8b77c7
--- /dev/null
+++ b/test/suite/support/property.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "base.h"
+
+bt_property_t *property_copy_array(const bt_property_t *properties, size_t count);
+bt_property_t *property_new_name(const char *name);
+bt_property_t *property_new_discovery_timeout(uint32_t timeout);
+
+const char *property_extract_name(const bt_property_t *property);
+
+bool property_equals(const bt_property_t *p1, const bt_property_t *p2);
+
+void property_free(bt_property_t *property);
+void property_free_array(bt_property_t *properties, size_t count);
diff --git a/utils/Android.mk b/utils/Android.mk
index c74cd2d..d0327e9 100644
--- a/utils/Android.mk
+++ b/utils/Android.mk
@@ -6,7 +6,7 @@
$(LOCAL_PATH)/../gki/ulinux \
$(bdroid_C_INCLUDES)
-LOCAL_CFLAGS += -Werror $(bdroid_CFLAGS)
+LOCAL_CFLAGS += $(bdroid_CFLAGS) -std=c99
LOCAL_PRELINK_MODULE:=false
LOCAL_SRC_FILES:= \
diff --git a/utils/include/bt_utils.h b/utils/include/bt_utils.h
index d601f2e..512e1b5 100644
--- a/utils/include/bt_utils.h
+++ b/utils/include/bt_utils.h
@@ -39,7 +39,6 @@
void bt_utils_init();
void bt_utils_cleanup();
void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task);
-
+void adjust_priority_a2dp(int start);
#define UNUSED(x) (void)(x)
-
#endif /* BT_UTILS_H */
diff --git a/utils/src/bt_utils.c b/utils/src/bt_utils.c
index aeb9292..6decacf 100644
--- a/utils/src/bt_utils.c
+++ b/utils/src/bt_utils.c
@@ -50,6 +50,8 @@
static BOOLEAN g_DoSchedulingGroup[TASK_HIGH_MAX];
static pthread_mutex_t gIdxLock;
static int g_TaskIdx;
+static int g_TaskIDs[TASK_HIGH_MAX];
+#define INVALID_TASK_ID (-1)
/*****************************************************************************
**
@@ -67,6 +69,7 @@
for(i = 0; i < TASK_HIGH_MAX; i++) {
g_DoSchedulingGroupOnce[i] = PTHREAD_ONCE_INIT;
g_DoSchedulingGroup[i] = TRUE;
+ g_TaskIDs[i] = INVALID_TASK_ID;
}
pthread_mutexattr_init(&lock_attr);
pthread_mutex_init(&gIdxLock, &lock_attr);
@@ -126,6 +129,7 @@
// set_sched_policy does not support tid == 0
rc = set_sched_policy(tid, SP_FOREGROUND);
}
+ g_TaskIDs[high_task] = tid;
pthread_mutex_unlock(&gIdxLock);
if (rc) {
@@ -137,3 +141,31 @@
}
}
+/*****************************************************************************
+**
+** Function adjust_priority_a2dp
+**
+** Description increase the a2dp consumer task priority temporarily when start
+** audio playing, to avoid overflow the audio packet queue, restore
+** the a2dp consumer task priority when stop audio playing.
+**
+** Returns void
+**
+*******************************************************************************/
+void adjust_priority_a2dp(int start) {
+ int priority = start ? ANDROID_PRIORITY_URGENT_AUDIO : ANDROID_PRIORITY_AUDIO;
+ int tid;
+ int i;
+
+ for (i = TASK_HIGH_GKI_TIMER; i < TASK_HIGH_MAX; i++)
+ {
+ tid = g_TaskIDs[i];
+ if (tid != INVALID_TASK_ID)
+ {
+ if (setpriority(PRIO_PROCESS, tid, priority) < 0)
+ {
+ ALOGW("failed to change priority tid: %d to %d", tid, priority);
+ }
+ }
+ }
+}
diff --git a/vnd/ble/bta_vendor.c b/vnd/ble/bta_vendor.c
new file mode 100644
index 0000000..3b41aa4
--- /dev/null
+++ b/vnd/ble/bta_vendor.c
@@ -0,0 +1,305 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2014 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: bta_vendor.c
+**
+** Description: This is the implementation VENDOR custom Ble APIs
+**
+*****************************************************************************/
+
+#include "bta_api.h"
+#include "bta_vendor_api.h"
+#include "bta_sys_int.h"
+#include "bta_dm_int.h"
+#include "vendor_api.h"
+#include "vendor_ble.h"
+#include <string.h>
+
+#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE)
+
+static tBTA_DM_SCAN_PF_CBACK *bta_vendor_ble_scan_pf_cmpl_cback = NULL;
+
+/*******************************************************************************
+**
+** Function bta_vendor_ble_scan_pf_cmpl
+**
+** Description ADV payload filtering operation complete callback
+**
+**
+** Returns TRUE if handled, otherwise FALSE.
+**
+*******************************************************************************/
+static void bta_vendor_ble_scan_pf_cmpl(tBTM_BLE_PF_ACTION action, tBTM_BLE_PF_COND_TYPE cfg_cond, tBTM_STATUS status)
+{
+ tBTA_STATUS st = (status == BTM_SUCCESS) ? BTA_SUCCESS: BTA_FAILURE;
+
+ if (bta_vendor_ble_scan_pf_cmpl_cback)
+ ((tBTA_DM_SCAN_PF_CBACK *) bta_vendor_ble_scan_pf_cmpl_cback)(action, cfg_cond, st);
+
+}
+/*******************************************************************************
+**
+** Function bta_vendor_ble_scan_pf_enable
+**
+** Description This function processes events for enabling adv payload filtering
+** feature
+**
+** Returns TRUE if handled, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN bta_vendor_ble_scan_pf_enable(tBTA_SYS_VS_BLE_SCAN_PF_ENABLE *p_data)
+{
+ tBTM_STATUS st;
+ tBTA_STATUS status;
+
+ if ((st = BTM_BleEnableFilterCondition(p_data->enable,
+ p_data->p_target,
+ (tBTM_BLE_PF_CMPL_CBACK *)p_data->p_cmpl_cback))
+ == BTM_CMD_STARTED)
+ {
+ bta_vendor_ble_scan_pf_cmpl_cback = (tBTA_DM_SCAN_PF_CBACK *)p_data->p_cmpl_cback;
+ }
+ else
+ {
+ status = (st == BTM_SUCCESS) ? BTA_SUCCESS: BTA_FAILURE;
+ if (p_data->p_cmpl_cback)
+ ((tBTA_DM_SCAN_PF_CBACK *) p_data->p_cmpl_cback)(BTA_DM_BLE_PF_CONFIG_EVT, 0, status);
+ }
+
+ return TRUE;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_vendor_ble_scan_pf_condition
+**
+** Description This function processes events for configuring the ADV filtering
+** condition
+**
+**
+** Returns TRUE if handled, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN bta_vendor_ble_scan_pf_condition(tBTA_SYS_VS_BLE_SCAN_PF_COND *p_data)
+{
+ tBTM_STATUS st;
+ tBTA_STATUS status;
+
+ if ((st = BTM_BleCfgFilterCondition(p_data->action,
+ p_data->cond_type,
+ (tBTM_BLE_PF_COND_PARAM *)p_data->p_cond,
+ bta_vendor_ble_scan_pf_cmpl))
+ == BTM_CMD_STARTED)
+ {
+ bta_vendor_ble_scan_pf_cmpl_cback = (tBTA_DM_SCAN_PF_CBACK *)p_data->p_cmpl_cback;
+ }
+ else
+ {
+ status = (st == BTM_SUCCESS) ? BTA_SUCCESS: BTA_FAILURE;
+ if (p_data->p_cmpl_cback)
+ ((tBTA_DM_SCAN_PF_CBACK *) p_data->p_cmpl_cback)(BTA_DM_BLE_PF_CONFIG_EVT, p_data->cond_type, status);
+ }
+ return TRUE;
+}
+#endif
+/*******************************************************************************
+**
+** Function bta_vendor_evt_hdlr
+**
+** Description This function processes events for Broadcom specific features.
+**
+** Returns TRUE if handled, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN bta_vendor_evt_hdlr(UINT16 event, void *p)
+{
+ BOOLEAN st = TRUE;
+
+ APPL_TRACE_EVENT1("bta_vendor_evt_hdlr :0x%04x", event);
+
+ switch (event)
+ {
+#if BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+ case BTA_VS_BLE_SCAN_PF_ENABLE_EVT:
+ st = bta_vendor_ble_scan_pf_enable((tBTA_SYS_VS_BLE_SCAN_PF_ENABLE *)p);
+ break;
+
+ case BTA_VS_BLE_SCAN_PF_COND_EVT:
+ bta_vendor_ble_scan_pf_condition((tBTA_SYS_VS_BLE_SCAN_PF_COND*)p);
+ break;
+#endif
+
+ default:
+ APPL_TRACE_EVENT1("Unknown BTA VS event: %d", event);
+ st = FALSE;
+ break;
+ }
+
+ return st;
+}
+
+
+
+/*******************************************************************************
+**
+** Function BTA_DmBleCfgFilterCondition
+**
+** Description This function is called to configure the adv data payload filter
+** condition.
+**
+** Parameters action: to read/write/clear
+** cond_type: filter condition type.
+** p_cond: filter condition paramter
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action,
+ tBTA_DM_BLE_PF_COND_TYPE cond_type,
+ tBTA_DM_BLE_PF_COND_PARAM *p_cond,
+ tBTA_DM_SCAN_PF_CBACK *p_cmpl_cback)
+{
+#if BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+ tBTA_DM_API_CFG_FILTER_COND *p_msg;
+ UINT16 len = sizeof(tBTA_DM_API_CFG_FILTER_COND) + sizeof(tBTA_DM_BLE_PF_COND_PARAM) + \
+ BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + sizeof(tBTA_DM_BLE_PF_COND_MASK);
+
+ UINT8 *p;
+
+ if ((p_msg = (tBTA_DM_API_CFG_FILTER_COND *) GKI_getbuf(len)) != NULL)
+ {
+ memset (p_msg, 0, len);
+
+ p_msg->hdr.event = BTA_DM_API_CFG_FILTER_COND_EVT;
+ p_msg->action = action;
+ p_msg->cond_type = cond_type;
+ p_msg->p_cmpl_cback = (void *) p_cmpl_cback;
+
+ if (p_cond)
+ {
+ p_msg->p_cond_param = (tBTA_DM_BLE_PF_COND_PARAM *)(p_msg + 1);
+ memcpy(p_msg->p_cond_param, p_cond, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+ p = (UINT8 *)(p_msg->p_cond_param + 1);
+
+ if (cond_type == BTA_DM_BLE_PF_SRVC_DATA_PATTERN ||cond_type == BTA_DM_BLE_PF_MANU_DATA)
+ {
+ p_msg->p_cond_param->manu_data.p_pattern = p;
+ p_msg->p_cond_param->manu_data.data_len = p_cond->manu_data.data_len;
+ memcpy(p_msg->p_cond_param->manu_data.p_pattern, p_cond->manu_data.p_pattern, p_cond->manu_data.data_len);
+ p += p_cond->manu_data.data_len;
+
+ if (cond_type == BTA_DM_BLE_PF_MANU_DATA)
+ {
+ p_msg->p_cond_param->manu_data.company_id_mask = p_cond->manu_data.company_id_mask;
+ if ( p_cond->manu_data.p_pattern_mask != NULL)
+ {
+ p_msg->p_cond_param->manu_data.p_pattern_mask = p;
+ memcpy(p_msg->p_cond_param->manu_data.p_pattern_mask, p_cond->manu_data.p_pattern_mask, p_cond->manu_data.data_len);
+ }
+ }
+ }
+ else if (cond_type == BTA_DM_BLE_PF_LOCAL_NAME)
+ {
+ p_msg->p_cond_param->local_name.p_data = p;
+ memcpy(p_msg->p_cond_param->local_name.p_data, p_cond->local_name.p_data, p_cond->local_name.data_len);
+
+ }
+ else if ((cond_type == BTM_BLE_PF_SRVC_UUID || cond_type == BTM_BLE_PF_SRVC_SOL_UUID))
+ {
+ if (p_cond->srvc_uuid.p_target_addr != NULL)
+ {
+ p_msg->p_cond_param->srvc_uuid.p_target_addr = (tBLE_BD_ADDR *)(p);
+ p_msg->p_cond_param->srvc_uuid.p_target_addr->type = p_cond->srvc_uuid.p_target_addr->type;
+ memcpy(p_msg->p_cond_param->srvc_uuid.p_target_addr->bda, p_cond->srvc_uuid.p_target_addr->bda, BD_ADDR_LEN);
+ p = (UINT8*)( p_msg->p_cond_param->srvc_uuid.p_target_addr + 1);
+ }
+ if (p_cond->srvc_uuid.p_uuid_mask)
+ {
+ p_msg->p_cond_param->srvc_uuid.p_uuid_mask = (tBTA_DM_BLE_PF_COND_MASK *)p;
+ memcpy(p_msg->p_cond_param->srvc_uuid.p_uuid_mask, p_cond->srvc_uuid.p_uuid_mask, sizeof(tBTA_DM_BLE_PF_COND_MASK));
+ }
+ }
+ }
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmBleEnableFilterCondition
+**
+** Description This function is called to enable the adv data payload filter
+** condition.
+**
+** Parameters p_target: enabble the filter condition on a target device; if NULL
+** enable the generic scan condition.
+** enable: enable or disable the filter condition
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleEnableFilterCondition(BOOLEAN enable, tBLE_BD_ADDR *p_target, tBTA_DM_SCAN_PF_CBACK *p_cmpl_cback)
+{
+#if BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+ tBTA_DM_API_ENABLE_SCAN_FILTER *p_msg;
+ UINT16 len = sizeof(tBTA_DM_API_ENABLE_SCAN_FILTER) + sizeof(tBLE_BD_ADDR);
+
+ if ((p_msg = (tBTA_DM_API_ENABLE_SCAN_FILTER *) GKI_getbuf(len)) != NULL)
+ {
+ memset (p_msg, 0, len);
+
+ p_msg->hdr.event = BTA_DM_API_ENABLE_SCAN_FILTER_EVT;
+ p_msg->enable = enable;
+ p_msg->p_cmpl_cback = (void *) p_cmpl_cback;
+
+ if (p_target)
+ {
+ p_msg->p_target = (tBLE_BD_ADDR *)(p_msg + 1);
+ memcpy(p_msg->p_target, p_target, sizeof(tBLE_BD_ADDR));
+ }
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_BrcmInit
+**
+** Description This function initializes Broadcom specific
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_BrcmInit (void)
+{
+ APPL_TRACE_API0("BTA_BrcmInit");
+ bta_sys_cb.p_vs_evt_hdlr = bta_vendor_evt_hdlr;
+#if BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+ btm_ble_vendor_init();
+#endif
+}
+
+
diff --git a/vnd/ble/vendor_ble.c b/vnd/ble/vendor_ble.c
new file mode 100644
index 0000000..49a7983
--- /dev/null
+++ b/vnd/ble/vendor_ble.c
@@ -0,0 +1,1540 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2014 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: vendor_ble.c
+**
+** Description: This file contains vendor specific feature for BLE
+**
+******************************************************************************/
+#include <string.h>
+#include "bt_target.h"
+
+#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE)
+#include "bt_types.h"
+#include "hcimsgs.h"
+#include "btu.h"
+#include "vendor_ble.h"
+#include "vendor_hcidefs.h"
+#include "gatt_int.h"
+
+#define BTM_BLE_INVALID_COUNTER 0xff
+
+
+static UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
+ UINT8 cond_type,
+ tBLE_BD_ADDR *p_bd_addr,
+ UINT8 num_available);
+
+#define BTM_BLE_SET_SCAN_PF_OPCODE(x, y) (((x)<<4)|y)
+#define BTM_BLE_GET_SCAN_PF_SUBCODE(x) ((x) >> 4)
+#define BTM_BLE_GET_SCAN_PF_ACTION(x) ((x) & 0x0f)
+
+/* max number of filter available for different filter type, controller dependent number */
+static const UINT8 btm_ble_cs_filter_max[BTM_BLE_PF_TYPE_MAX] =
+{
+ BTM_BLE_MAX_ADDR_FILTER, /* address filter */
+ 1, /* no limit for service data change, always enable or disable */
+ BTM_BLE_MAX_UUID_FILTER, /* service UUID filter */
+ BTM_BLE_MAX_UUID_FILTER, /* solicitated UUID filter */
+ BTM_BLE_PF_STR_COND_MAX, /* local name filter */
+ BTM_BLE_PF_STR_COND_MAX /* manufacturer data filter */
+};
+
+/*** This needs to be moved to a VSC control block eventually per coding conventions ***/
+#if VENDOR_DYNAMIC_MEMORY == FALSE
+tBTM_BLE_VENDOR_CB btm_ble_vendor_cb;
+#endif
+
+static const UINT8 op_code_to_cond_type[] =
+{
+ BTM_BLE_PF_TYPE_ALL,
+ BTM_BLE_PF_ADDR_FILTER,
+ BTM_BLE_PF_SRVC_UUID,
+ BTM_BLE_PF_SRVC_SOL_UUID,
+ BTM_BLE_PF_LOCAL_NAME,
+ BTM_BLE_PF_MANU_DATA,
+ BTM_BLE_PF_SRVC_DATA_PATTERN
+};
+
+static const BD_ADDR na_bda= {0};
+
+/*******************************************************************************
+**
+** Function btm_ble_vendor_scan_pf_cmpl_cback
+**
+** Description the BTM BLE customer feature VSC complete callback for ADV PF
+** filtering
+**
+** Returns pointer to the counter if found; NULL otherwise.
+**
+*******************************************************************************/
+void btm_ble_vendor_scan_pf_cmpl_cback(tBTM_VSC_CMPL *p_params)
+{
+ UINT8 status;
+ UINT8 *p = p_params->p_param_buf, op_subcode, action = 0xff;
+ UINT16 evt_len = p_params->param_len;
+ UINT8 num_avail = 0, cond_type = BTM_BLE_PF_TYPE_MAX;
+ tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback = btm_ble_vendor_cb.p_scan_pf_cback;
+ UINT8 op = BTM_BLE_GET_SCAN_PF_ACTION(btm_ble_vendor_cb.op_type);
+ UINT8 subcode = BTM_BLE_GET_SCAN_PF_SUBCODE(btm_ble_vendor_cb.op_type);
+
+ STREAM_TO_UINT8(status, p);
+
+ evt_len--;
+
+ if (evt_len < 1 )
+ {
+ BTM_TRACE_ERROR1("can not interpret ADV PF filter setting callback. status = %d", status);
+ return;
+ }
+ op_subcode = *p ++;
+ switch (op_subcode)
+ {
+ case BTM_BLE_META_PF_LOCAL_NAME:
+ case BTM_BLE_META_PF_MANU_DATA:
+ case BTM_BLE_META_PF_ADDR:
+ case BTM_BLE_META_PF_UUID:
+ case BTM_BLE_META_PF_SOL_UUID:
+ case BTM_BLE_META_PF_FEAT_SEL:
+ case BTM_BLE_META_PF_SRVC_DATA:
+ cond_type = op_code_to_cond_type[op_subcode - BTM_BLE_META_PF_FEAT_SEL];
+ if (status == HCI_SUCCESS)
+ {
+ action = *p ++;
+ if (op_subcode != BTM_BLE_META_PF_FEAT_SEL)
+ {
+ STREAM_TO_UINT8(num_avail, p);
+ }
+
+ if (memcmp(&btm_ble_vendor_cb.cur_filter_target.bda, &na_bda, BD_ADDR_LEN) == 0)
+ btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail);
+ else
+ btm_ble_cs_update_pf_counter(action, cond_type, &btm_ble_vendor_cb.cur_filter_target, num_avail);
+ }
+ break;
+
+ case BTM_BLE_META_PF_ENABLE:
+ cond_type = BTM_BLE_META_PF_ENABLE;
+ BTM_TRACE_DEBUG0("CS feature Enabled");
+ break;
+
+ default:
+ BTM_TRACE_ERROR1("unknow operation: %d", op_subcode);
+ break;
+ }
+
+ /* send ADV PF opeartion complete */
+ if (p_cmpl_cback && subcode == cond_type)
+ {
+ btm_ble_vendor_cb.p_scan_pf_cback = NULL;
+ btm_ble_vendor_cb.op_type = 0;
+ (* p_cmpl_cback)(op, subcode, status);
+ }
+}
+/*******************************************************************************
+** adv payload filtering functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function btm_ble_find_addr_filter_counter
+**
+** Description find the per bd address ADV payload filter counter by BD_ADDR.
+**
+** Returns pointer to the counter if found; NULL otherwise.
+**
+*******************************************************************************/
+tBTM_BLE_PF_COUNT * btm_ble_find_addr_filter_counter(tBLE_BD_ADDR *p_le_bda)
+{
+ UINT8 i;
+ tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1];
+
+ if (p_le_bda == NULL)
+ return &btm_ble_vendor_cb.addr_filter_count[0];
+
+ for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++)
+ {
+ if (p_addr_filter->in_use &&
+ memcmp(p_le_bda->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)
+ {
+ return p_addr_filter;
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_alloc_addr_filter_counter
+**
+** Description allocate the per device adv payload filter counter.
+**
+** Returns pointer to the counter if allocation succeed; NULL otherwise.
+**
+*******************************************************************************/
+tBTM_BLE_PF_COUNT * btm_ble_alloc_addr_filter_counter(BD_ADDR bd_addr)
+{
+ UINT8 i;
+ tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1];
+
+ for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++)
+ {
+ if (memcmp(na_bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)
+ {
+ memcpy(p_addr_filter->bd_addr, bd_addr, BD_ADDR_LEN);
+ p_addr_filter->in_use = TRUE;
+ return p_addr_filter;
+ }
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function btm_ble_dealloc_addr_filter_counter
+**
+** Description de-allocate the per device adv payload filter counter.
+**
+** Returns TRUE if deallocation succeed; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filter_type)
+{
+ UINT8 i;
+ tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1];
+ BOOLEAN found = FALSE;
+
+ if (filter_type == BTM_BLE_PF_TYPE_ALL && p_bd_addr == NULL)
+ memset(&btm_ble_vendor_cb.addr_filter_count[0], 0, sizeof(tBTM_BLE_PF_COUNT));
+
+ for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++)
+ {
+ if ((p_addr_filter->in_use) &&
+ (p_bd_addr == NULL ||
+ (p_bd_addr != NULL && memcmp(p_bd_addr->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)))
+ {
+ found = TRUE;
+ memset(p_addr_filter, 0, sizeof(tBTM_BLE_PF_COUNT));
+
+ if (p_bd_addr != NULL) break;
+ }
+ }
+ return found;
+}
+/*******************************************************************************
+**
+** Function btm_ble_cs_update_pf_counter
+**
+** Description this function is to update the adv data payload filter counter
+**
+** Returns current number of the counter; BTM_BLE_INVALID_COUNTER if
+** counter update failed.
+**
+*******************************************************************************/
+UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
+ UINT8 cond_type,
+ tBLE_BD_ADDR *p_bd_addr,
+ UINT8 num_available)
+{
+ tBTM_BLE_PF_COUNT *p_addr_filter = NULL;
+ UINT8 *p_counter = NULL;
+ UINT32 *p_feat_mask = NULL;
+
+
+ if (cond_type > BTM_BLE_PF_TYPE_ALL)
+ {
+ BTM_TRACE_ERROR1("unknown PF filter condition type %d", cond_type);
+ return BTM_BLE_INVALID_COUNTER;
+ }
+ /* for these three types of filter, always generic */
+ if (cond_type == BTM_BLE_PF_ADDR_FILTER ||
+ cond_type == BTM_BLE_PF_MANU_DATA ||
+ cond_type == BTM_BLE_PF_LOCAL_NAME ||
+ cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN)
+ p_bd_addr = NULL;
+
+ if ((p_addr_filter = btm_ble_find_addr_filter_counter(p_bd_addr)) == NULL &&
+ action == BTM_BLE_SCAN_COND_ADD)
+ {
+ p_addr_filter = btm_ble_alloc_addr_filter_counter(p_bd_addr->bda);
+ }
+
+ if (p_addr_filter != NULL)
+ {
+ /* all filter just cleared */
+ if ((cond_type == BTM_BLE_PF_TYPE_ALL && action == BTM_BLE_SCAN_COND_CLEAR) ||
+ /* or bd address filter been deleted */
+ (cond_type == BTM_BLE_PF_ADDR_FILTER &&
+ (action == BTM_BLE_SCAN_COND_DELETE || action == BTM_BLE_SCAN_COND_CLEAR)))
+ {
+ btm_ble_dealloc_addr_filter_counter(p_bd_addr, cond_type);
+ }
+ /* if not feature selection, update new addition/reduction of the filter counter */
+ else if (cond_type != BTM_BLE_PF_TYPE_ALL)
+ {
+ p_counter = p_addr_filter->pf_counter;
+ p_feat_mask = &p_addr_filter->feat_mask;
+
+ p_counter[cond_type] = btm_ble_cs_filter_max[cond_type] - num_available;
+
+ BTM_TRACE_DEBUG1("current filter counter number = %d", p_counter[cond_type]);
+
+ /* update corresponding feature mask */
+ if (p_counter[cond_type] > 0)
+ *p_feat_mask |= (BTM_BLE_PF_BIT_TO_MASK(cond_type));
+ else
+ *p_feat_mask &= ~(BTM_BLE_PF_BIT_TO_MASK(cond_type));
+
+ return p_counter[cond_type];
+ }
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("no matching filter counter found");
+ }
+ /* no matching filter located and updated */
+ return BTM_BLE_INVALID_COUNTER;
+}
+/*******************************************************************************
+**
+** Function btm_ble_update_pf_manu_data
+**
+** Description this function update(add,delete or clear) the adv manufacturer
+** data filtering condition.
+**
+**
+** Returns BTM_SUCCESS if sucessful,
+** BTM_ILLEGAL_VALUE if paramter is not valid.
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_PARAM *p_data,
+ tBTM_BLE_PF_COND_TYPE cond_type)
+{
+ tBTM_BLE_PF_MANU_COND *p_manu_data = (p_data == NULL) ? NULL : &p_data->manu_data;
+ tBTM_BLE_PF_SRVC_PATTERN_COND *p_srvc_data = (p_data == NULL) ? NULL : &p_data->srvc_data;
+ UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH],
+ *p = param,
+ len = BTM_BLE_META_HDR_LENGTH;
+ tBTM_STATUS st = BTM_ILLEGAL_VALUE;
+
+ memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH);
+
+ if (cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN)
+ {
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_SRVC_DATA);
+ }
+ else
+ {
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_MANU_DATA);
+ }
+ UINT8_TO_STREAM(p, action);
+
+ /* Filter index */
+ UINT8_TO_STREAM(p, 0);
+
+ if (action == BTM_BLE_SCAN_COND_ADD ||
+ action == BTM_BLE_SCAN_COND_DELETE)
+ {
+ if (p_manu_data == NULL)
+ return st;
+ if (cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN)
+ {
+ if (p_srvc_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2))
+ p_srvc_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
+
+ UINT16_TO_STREAM(p, p_srvc_data->uuid);
+ ARRAY_TO_STREAM(p, p_srvc_data->p_pattern, p_srvc_data->data_len);
+ len += (p_srvc_data->data_len + 2);
+ }
+ else
+ {
+ if (p_manu_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2))
+ p_manu_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
+
+ UINT16_TO_STREAM(p, p_manu_data->company_id);
+ ARRAY_TO_STREAM(p, p_manu_data->p_pattern, p_manu_data->data_len);
+ len += (p_manu_data->data_len + 2);
+
+ if (p_manu_data->company_id_mask != 0)
+ {
+ UINT16_TO_STREAM (p, p_manu_data->company_id_mask);
+ }
+ else
+ {
+ memset(p, 0xff, 2);
+ p += 2;
+ }
+ if (p_manu_data->p_pattern_mask != NULL)
+ {
+ ARRAY_TO_STREAM(p, p_manu_data->p_pattern_mask, p_manu_data->data_len);
+ }
+ else
+ memset(p, 0xff, p_manu_data->data_len);
+ len += (p_manu_data->data_len + 2);
+ }
+ }
+
+ /* send manufacturer*/
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ len,
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
+ {
+ memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("manufacturer data PF filter update failed");
+ }
+
+ return st;
+}
+/*******************************************************************************
+**
+** Function btm_ble_update_pf_local_name
+**
+** Description this function update(add,delete or clear) the adv lcoal name
+** filtering condition.
+**
+**
+** Returns BTM_SUCCESS if sucessful,
+** BTM_ILLEGAL_VALUE if paramter is not valid.
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_PARAM *p_cond)
+{
+ tBTM_BLE_PF_LOCAL_NAME_COND *p_local_name = (p_cond == NULL) ? NULL : &p_cond->local_name;
+ UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH],
+ *p = param,
+ len = BTM_BLE_META_HDR_LENGTH;
+ tBTM_STATUS st = BTM_ILLEGAL_VALUE;
+
+ memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH);
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_LOCAL_NAME);
+ UINT8_TO_STREAM(p, action);
+
+ /* Filter index */
+ UINT8_TO_STREAM(p, 0);
+
+ if (action == BTM_BLE_SCAN_COND_ADD ||
+ action == BTM_BLE_SCAN_COND_DELETE)
+ {
+ if (p_local_name == NULL)
+ return st;
+
+ if (p_local_name->data_len > BTM_BLE_PF_STR_LEN_MAX)
+ p_local_name->data_len = BTM_BLE_PF_STR_LEN_MAX;
+
+ ARRAY_TO_STREAM(p, p_local_name->p_data, p_local_name->data_len);
+ len += p_local_name->data_len;
+ }
+ /* send local name filter */
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ len,
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback))
+ != BTM_NO_RESOURCES)
+ {
+ memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("Local Name PF filter update failed");
+ }
+
+ return st;
+}
+/*******************************************************************************
+**
+** Function btm_ble_update_addr_filter
+**
+** Description this function update(add,delete or clear) the address filter of adv.
+**
+**
+** Returns BTM_SUCCESS if sucessful,
+** BTM_ILLEGAL_VALUE if paramter is not valid.
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_PARAM *p_cond)
+{
+ UINT8 param[BTM_BLE_META_ADDR_LEN + BTM_BLE_META_HDR_LENGTH],
+ * p= param;
+ tBTM_STATUS st = BTM_ILLEGAL_VALUE;
+ tBLE_BD_ADDR *p_addr = (p_cond == NULL) ? NULL : &p_cond->target_addr;
+
+ memset(param, 0, BTM_BLE_META_ADDR_LEN + BTM_BLE_META_HDR_LENGTH);
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
+ UINT8_TO_STREAM(p, action);
+
+ /* Filter index */
+ UINT8_TO_STREAM(p, 0);
+
+ if (action == BTM_BLE_SCAN_COND_ADD ||
+ action == BTM_BLE_SCAN_COND_DELETE)
+ {
+ if (p_addr == NULL)
+ return st;
+
+ BDADDR_TO_STREAM(p, p_addr->bda);
+ UINT8_TO_STREAM(p, p_addr->type);
+ }
+ /* send address filter */
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
+ {
+ memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("Broadcaster Address Filter Update failed");
+ }
+ return st;
+}
+/*******************************************************************************
+**
+** Function btm_ble_update_uuid_filter
+**
+** Description this function update(add,delete or clear) service UUID filter.
+**
+**
+** Returns BTM_SUCCESS if sucessful,
+** BTM_ILLEGAL_VALUE if paramter is not valid.
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_TYPE filter_type,
+ tBTM_BLE_PF_COND_PARAM *p_cond)
+{
+ UINT8 param[BTM_BLE_META_UUID_LEN + BTM_BLE_META_HDR_LENGTH],
+ * p= param,
+ len = BTM_BLE_META_HDR_LENGTH;
+ tBTM_STATUS st = BTM_ILLEGAL_VALUE;
+ tBTM_BLE_PF_UUID_COND *p_uuid_cond;
+ UINT8 evt_type;
+
+ memset(param, 0, BTM_BLE_META_UUID_LEN + BTM_BLE_META_HDR_LENGTH);
+
+ if (filter_type == BTM_BLE_PF_SRVC_UUID)
+ {
+ evt_type = BTM_BLE_META_PF_UUID;
+ p_uuid_cond = p_cond ? &p_cond->srvc_uuid : NULL;
+ }
+ else
+ {
+ evt_type = BTM_BLE_META_PF_SOL_UUID;
+ p_uuid_cond = p_cond ? &p_cond->solicitate_uuid : NULL;
+ }
+
+ if (p_uuid_cond == NULL && action != BTM_BLE_SCAN_COND_CLEAR)
+ {
+ BTM_TRACE_ERROR0("Illegal param for add/delete UUID filter");
+ return st;
+ }
+
+ /* need to add address fitler first, if adding per bda UUID filter without address filter */
+ if (action == BTM_BLE_SCAN_COND_ADD &&
+ p_uuid_cond->p_target_addr &&
+ btm_ble_find_addr_filter_counter(p_uuid_cond->p_target_addr) == NULL)
+ {
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
+ UINT8_TO_STREAM(p, action);
+
+ /* Filter index */
+ UINT8_TO_STREAM(p, 0);
+
+ BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda);
+ UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type);
+
+ /* send address filter */
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback)) == BTM_NO_RESOURCES)
+ {
+ BTM_TRACE_ERROR0("Update Address filter into controller failed.");
+ return st;
+ }
+ }
+
+ p= param;
+ UINT8_TO_STREAM(p, evt_type);
+ UINT8_TO_STREAM(p, action);
+
+ /* Filter index */
+ UINT8_TO_STREAM(p, 0);
+
+ if (action == BTM_BLE_SCAN_COND_ADD ||
+ action == BTM_BLE_SCAN_COND_DELETE)
+ {
+ if (p_uuid_cond->uuid.len == LEN_UUID_16)
+ {
+ UINT16_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid16);
+ len += LEN_UUID_16;
+ }
+ else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */
+ {
+ UINT32_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid32);
+ len += LEN_UUID_32;
+ }
+ else if (p_uuid_cond->uuid.len == LEN_UUID_128)
+ {
+ ARRAY_TO_STREAM (p, p_uuid_cond->uuid.uu.uuid128, LEN_UUID_128);
+ len += LEN_UUID_128;
+ }
+ else
+ {
+ BTM_TRACE_ERROR1("illegal UUID length: %d", p_uuid_cond->uuid.len);
+ return BTM_ILLEGAL_VALUE;
+ }
+#if !(defined VENDOR_ADV_PCF_LEGACY && VENDOR_ADV_PCF_LEGACY == TRUE)
+ if (p_uuid_cond->p_uuid_mask != NULL)
+ {
+ if (p_uuid_cond->uuid.len == LEN_UUID_16)
+ {
+ UINT16_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid16_mask);
+ len += LEN_UUID_16;
+ }
+ else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */
+ {
+ UINT32_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid32_mask);
+ len += LEN_UUID_32;
+ }
+ else if (p_uuid_cond->uuid.len == LEN_UUID_128)
+ {
+ ARRAY_TO_STREAM (p, p_uuid_cond->p_uuid_mask->uuid128_mask, LEN_UUID_128);
+ len += LEN_UUID_128;
+ }
+ }
+ else
+ {
+ memset(p, 0xff, p_uuid_cond->uuid.len);
+ len += p_uuid_cond->uuid.len;
+ }
+#endif
+ }
+
+ /* send UUID filter update */
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ len,
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
+ {
+ if (p_uuid_cond && p_uuid_cond->p_target_addr)
+ memcpy(&btm_ble_vendor_cb.cur_filter_target, p_uuid_cond->p_target_addr, sizeof(tBLE_BD_ADDR));
+ else
+ memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("UUID filter udpating failed");
+ }
+
+ return st;
+}
+/*******************************************************************************
+**
+** Function btm_ble_update_srvc_data_change
+**
+** Description this function update(add/remove) service data change filter.
+**
+**
+** Returns BTM_SUCCESS if sucessful,
+** BTM_ILLEGAL_VALUE if paramter is not valid.
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_PARAM *p_cond)
+{
+ tBTM_STATUS st = BTM_ILLEGAL_VALUE;
+ tBLE_BD_ADDR *p_bd_addr = p_cond ? &p_cond->target_addr : NULL;
+ UINT8 num_avail = (action == BTM_BLE_SCAN_COND_ADD) ? 0 : 1;
+
+ if (btm_ble_cs_update_pf_counter (action, BTM_BLE_PF_SRVC_DATA, p_bd_addr, num_avail)
+ != BTM_BLE_INVALID_COUNTER)
+ st = BTM_SUCCESS;
+
+ return st;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_clear_scan_pf_filter
+**
+** Description clear all adv payload filter by de-select all the adv pf feature bits
+**
+**
+** Returns BTM_SUCCESS if sucessful,
+** BTM_ILLEGAL_VALUE if paramter is not valid.
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_PARAM *p_cond)
+{
+ tBLE_BD_ADDR *p_target = (p_cond == NULL)? NULL : &p_cond->target_addr;
+ tBTM_BLE_PF_COUNT *p_bda_filter;
+ tBTM_STATUS st = BTM_WRONG_MODE;
+ UINT8 param[20], *p;
+
+ if (action != BTM_BLE_SCAN_COND_CLEAR)
+ {
+ BTM_TRACE_ERROR1("unable to perform action:%d for generic adv filter type", action);
+ return BTM_ILLEGAL_VALUE;
+ }
+
+ p = param;
+ memset(param, 0, 20);
+
+ p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
+
+ if (p_bda_filter == NULL ||
+ /* not a generic filter, and feature selection is empty */
+ (p_target != NULL && p_bda_filter && p_bda_filter->feat_mask == 0))
+ {
+ BTM_TRACE_ERROR0("Error: Can not clear filter, No PF filter has been configured!");
+ return st;
+ }
+
+ /* clear the general filter entry */
+ if (p_target == NULL)
+ {
+ /* clear manufactuer data filter */
+ btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, NULL, BTM_BLE_PF_MANU_DATA);
+ /* clear local name filter */
+ btm_ble_update_pf_local_name(BTM_BLE_SCAN_COND_CLEAR, NULL);
+ /* update the counter for service data */
+ btm_ble_update_srvc_data_change(BTM_BLE_SCAN_COND_CLEAR, NULL);
+ /* clear UUID filter */
+ btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, BTM_BLE_PF_SRVC_UUID, NULL);
+ btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, BTM_BLE_META_PF_SOL_UUID, NULL);
+ /* clear service data filter */
+ btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, NULL, BTM_BLE_PF_MANU_DATA);
+ }
+
+ /* select feature based on control block settings */
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
+ UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR);
+
+ /* Filter index */
+ UINT8_TO_STREAM(p, 0);
+
+ /* set PCF selection */
+ UINT32_TO_STREAM(p, BTM_BLE_PF_SELECT_NONE);
+ /* set logic condition as OR as default */
+ UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR);
+
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN),
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback))
+ != BTM_NO_RESOURCES)
+ {
+ if (p_bda_filter)
+ p_bda_filter->feat_mask = BTM_BLE_PF_SELECT_NONE;
+
+ if (p_target)
+ memcpy(&btm_ble_vendor_cb.cur_filter_target, p_target, sizeof(tBLE_BD_ADDR));
+ else
+ memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
+ }
+
+ return st;
+}
+/*******************************************************************************
+**
+** Function BTM_BleEnableFilterCondition
+**
+** Description This function is called to enable the adv data payload filter
+** condition.
+**
+** Parameters p_target: enabble the filter condition on a target device; if NULL
+** enable the generic scan condition.
+** enable: enable or disable the filter condition
+**
+** Returns void
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleEnableFilterCondition(BOOLEAN enable, tBLE_BD_ADDR *p_target,
+ tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback)
+{
+ UINT8 param[20], *p;
+ tBTM_STATUS st = BTM_WRONG_MODE;
+ tBTM_BLE_PF_COUNT *p_bda_filter;
+
+ p = param;
+ memset(param, 0, 20);
+
+ if (btm_ble_vendor_cb.p_scan_pf_cback)
+ {
+ BTM_TRACE_ERROR0("ADV PF Filter activity busy");
+ return BTM_BUSY;
+ }
+
+ if (enable)
+ {
+ p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
+
+ if (p_bda_filter == NULL ||
+ (p_bda_filter && p_bda_filter->feat_mask == BTM_BLE_PF_SELECT_NONE))
+ {
+ BTM_TRACE_ERROR0("No PF filter has been configured!");
+ return st;
+ }
+
+ /* select feature based on control block settings */
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
+ UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_ADD);
+
+ /* Filter index */
+ UINT8_TO_STREAM(p, 0);
+
+ /* set PCF selection */
+ UINT32_TO_STREAM(p, p_bda_filter->feat_mask);
+ /* set logic condition as OR as default */
+ UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR);
+
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN),
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback))
+ == BTM_NO_RESOURCES)
+ {
+ return st;
+ }
+
+ /* enable the content filter in controller */
+ p = param;
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE);
+ /* enable adv data payload filtering */
+ UINT8_TO_STREAM(p, enable);
+ }
+ else
+ {
+ UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE);
+ /* disable adv data payload filtering */
+ UINT8_TO_STREAM(p, enable);
+ }
+
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
+ BTM_BLE_PCF_ENABLE_LEN,
+ param,
+ btm_ble_vendor_scan_pf_cmpl_cback))
+ == BTM_CMD_STARTED)
+ {
+ btm_ble_vendor_cb.op_type = BTM_BLE_SET_SCAN_PF_OPCODE(BTM_BLE_META_PF_ENABLE, BTM_BLE_PF_ENABLE);
+ btm_ble_vendor_cb.p_scan_pf_cback = p_cmpl_cback;
+ }
+
+ return st;
+}
+/*******************************************************************************
+**
+** Function BTM_BleCfgFilterCondition
+**
+** Description This function is called to configure the adv data payload filter
+** condition.
+**
+** Parameters action: to read/write/clear
+** cond_type: filter condition type.
+** p_cond: filter condition paramter
+**
+** Returns void
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_TYPE cond_type,
+ tBTM_BLE_PF_COND_PARAM *p_cond,
+ tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback)
+{
+ tBTM_STATUS st = BTM_ILLEGAL_VALUE;
+
+ if (btm_ble_vendor_cb.p_scan_pf_cback != NULL)
+ return BTM_BUSY;
+
+ switch (cond_type)
+ {
+ case BTM_BLE_PF_SRVC_DATA_PATTERN:
+ /* write manufacture data filter */
+ case BTM_BLE_PF_MANU_DATA:
+ st = btm_ble_update_pf_manu_data(action, p_cond, cond_type);
+ break;
+
+ /* write local name filter */
+ case BTM_BLE_PF_LOCAL_NAME:
+ st = btm_ble_update_pf_local_name(action, p_cond);
+ break;
+
+ /* filter on advertiser address */
+ case BTM_BLE_PF_ADDR_FILTER:
+ st = btm_ble_update_addr_filter(action, p_cond);
+ break;
+
+ /* filter on service/solicitated UUID */
+ case BTM_BLE_PF_SRVC_UUID:
+ case BTM_BLE_PF_SRVC_SOL_UUID:
+ st = btm_ble_update_uuid_filter(action, cond_type, p_cond);
+ break;
+
+ case BTM_BLE_PF_SRVC_DATA:
+ st = btm_ble_update_srvc_data_change(action, p_cond);
+ break;
+
+ case BTM_BLE_PF_TYPE_ALL: /* only used to clear filter */
+ st = btm_ble_clear_scan_pf_filter(action, p_cond);
+ break;
+
+ default:
+ BTM_TRACE_WARNING1("condition type [%d] not supported currently.", cond_type);
+ break;
+ }
+ if (st == BTM_CMD_STARTED
+ /* no vsc needed for service data change */
+ && cond_type != BTM_BLE_PF_SRVC_DATA)
+ {
+ btm_ble_vendor_cb.op_type = BTM_BLE_SET_SCAN_PF_OPCODE(cond_type, BTM_BLE_PF_CONFIG);
+ btm_ble_vendor_cb.p_scan_pf_cback = p_cmpl_cback;
+ }
+
+ return st;
+}
+
+/*******************************************************************************
+** Resolve Address Using IRK List functions
+*******************************************************************************/
+
+#if BLE_PRIVACY_SPT == TRUE
+/* Forward declaration */
+tBTM_STATUS BTM_BleEnableIRKFeature(BOOLEAN enable);
+
+/*******************************************************************************
+**
+** Function btm_ble_vendor_enq_irk_pending
+**
+** Description add target address into IRK pending operation queue
+**
+** Parameters target_bda: target device address
+** add_entry: TRUE for add entry, FALSE for remove entry
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_vendor_enq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_bda, UINT8 to_add)
+{
+ tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q;
+
+ memcpy(p_q->irk_q[p_q->q_next], target_bda, BD_ADDR_LEN);
+ memcpy(p_q->irk_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN);
+ p_q->irk_q_action[p_q->q_next] = to_add;
+
+ p_q->q_next ++;
+ p_q->q_next %= BTM_CS_IRK_LIST_MAX;
+
+ return ;
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_find_irk_pending_entry
+**
+** Description check to see if the action is in pending list
+**
+** Parameters TRUE: action pending;
+** FALSE: new action
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN btm_ble_vendor_find_irk_pending_entry(BD_ADDR psuedo_addr, UINT8 action)
+{
+ tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q;
+ UINT8 i;
+
+ for (i = p_q->q_pending; i != p_q->q_next; )
+ {
+ if (memcmp(p_q->irk_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 &&
+ action == p_q->irk_q_action[i])
+ return TRUE;
+
+ i ++;
+ i %= BTM_CS_IRK_LIST_MAX;
+ }
+ return FALSE;
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_deq_irk_pending
+**
+** Description add target address into IRK pending operation queue
+**
+** Parameters target_bda: target device address
+** add_entry: TRUE for add entry, FALSE for remove entry
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN btm_ble_vendor_deq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_addr)
+{
+ tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q;
+
+ if (p_q->q_next != p_q->q_pending)
+ {
+ memcpy(target_bda, p_q->irk_q[p_q->q_pending], BD_ADDR_LEN);
+ memcpy(psuedo_addr, p_q->irk_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
+
+ p_q->q_pending ++;
+ p_q->q_pending %= BTM_CS_IRK_LIST_MAX;
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_find_irk_entry
+**
+** Description find IRK entry in local host IRK list by static address
+**
+** Returns IRK list entry pointer
+**
+*******************************************************************************/
+tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry(BD_ADDR target_bda)
+{
+ tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
+ UINT8 i;
+
+ for (i = 0; i < BTM_CS_IRK_LIST_MAX; i ++, p_irk_entry++)
+ {
+ if (p_irk_entry->in_use && memcmp(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN) == 0)
+ {
+ return p_irk_entry ;
+ }
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_find_irk_entry_by_psuedo_addr
+**
+** Description find IRK entry in local host IRK list by psuedo address
+**
+** Returns IRK list entry pointer
+**
+*******************************************************************************/
+tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry_by_psuedo_addr (BD_ADDR psuedo_bda)
+{
+ tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
+ UINT8 i;
+
+ for (i = 0; i < BTM_CS_IRK_LIST_MAX; i ++, p_irk_entry++)
+ {
+ if (p_irk_entry->in_use && memcmp(p_irk_entry->psuedo_bda, psuedo_bda, BD_ADDR_LEN) == 0)
+ {
+ return p_irk_entry ;
+ }
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_alloc_irk_entry
+**
+** Description allocate IRK entry in local host IRK list
+**
+** Returns IRK list index
+**
+*******************************************************************************/
+UINT8 btm_ble_vendor_alloc_irk_entry(BD_ADDR target_bda, BD_ADDR pseudo_bda)
+{
+ tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
+ UINT8 i;
+
+ for (i = 0; i < BTM_CS_IRK_LIST_MAX; i ++, p_irk_entry++)
+ {
+ if (!p_irk_entry->in_use)
+ {
+ memcpy(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN);
+ memcpy(p_irk_entry->psuedo_bda, pseudo_bda, BD_ADDR_LEN);
+
+ p_irk_entry->index = i;
+ p_irk_entry->in_use = TRUE;
+
+ return i;
+ }
+ }
+ return BTM_CS_IRK_LIST_INVALID;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_vendor_update_irk_list
+**
+** Description update IRK entry in local host IRK list
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_vendor_update_irk_list(BD_ADDR target_bda, BD_ADDR pseudo_bda, BOOLEAN add)
+{
+ tBTM_BLE_IRK_ENTRY *p_irk_entry = btm_ble_vendor_find_irk_entry(target_bda);
+ UINT8 i;
+
+ if (add)
+ {
+ if (p_irk_entry == NULL)
+ {
+ if ((i = btm_ble_vendor_alloc_irk_entry(target_bda, pseudo_bda)) == BTM_CS_IRK_LIST_INVALID)
+ {
+ BTM_TRACE_ERROR0("max IRK capacity reached");
+ }
+ }
+ else
+ {
+ BTM_TRACE_WARNING0(" IRK already in queue");
+ }
+ }
+ else
+ {
+ if (p_irk_entry != NULL)
+ {
+ memset(p_irk_entry, 0, sizeof(tBTM_BLE_IRK_ENTRY));
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("No IRK exist in list, can not remove");
+ }
+ }
+ return ;
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_irk_vsc_op_cmpl
+**
+** Description IRK operation VSC complete handler
+**
+** Parameters
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_vendor_irk_vsc_op_cmpl (tBTM_VSC_CMPL *p_params)
+{
+ UINT8 status;
+ UINT8 *p = p_params->p_param_buf, op_subcode;
+ UINT16 evt_len = p_params->param_len;
+ UINT8 i;
+ tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb;
+ BD_ADDR target_bda, pseudo_bda, rra;
+
+
+ STREAM_TO_UINT8(status, p);
+
+ evt_len--;
+
+ /*if (evt_len < 2 )
+ {
+ BTM_TRACE_ERROR0("can not interpret IRK VSC cmpl callback");
+ return;
+ }*/
+ op_subcode = *p ++;
+ BTM_TRACE_DEBUG1("btm_ble_vendor_irk_vsc_op_cmpl op_subcode = %d", op_subcode);
+ if (evt_len < 2 )
+ {
+ BTM_TRACE_ERROR0("can not interpret IRK VSC cmpl callback");
+ return;
+ }
+
+
+ if (op_subcode == BTM_BLE_META_CLEAR_IRK_LIST)
+ {
+ if (status == HCI_SUCCESS)
+ {
+ STREAM_TO_UINT8(p_cb->irk_avail_size, p);
+ p_cb->irk_list_size = 0;
+
+ BTM_TRACE_DEBUG1("p_cb->irk_list_size = %d", p_cb->irk_avail_size);
+
+ for (i = 0; i < BTM_CS_IRK_LIST_MAX; i ++)
+ memset(&p_cb->irk_list[i], 0, sizeof(tBTM_BLE_IRK_ENTRY));
+ }
+ }
+ else if (op_subcode == BTM_BLE_META_ADD_IRK_ENTRY)
+ {
+ if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda))
+ {
+ BTM_TRACE_ERROR0("no pending IRK operation");
+ return;
+ }
+
+ if (status == HCI_SUCCESS)
+ {
+ STREAM_TO_UINT8(p_cb->irk_avail_size, p);
+ btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, TRUE);
+ }
+ else if (status == 0x07) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED */
+ {
+ p_cb->irk_avail_size = 0;
+ BTM_TRACE_ERROR0("IRK Full ");
+ }
+ else
+ {
+ /* give the credit back if invalid parameter failed the operation */
+ p_cb->irk_list_size ++;
+ }
+ }
+ else if (op_subcode == BTM_BLE_META_REMOVE_IRK_ENTRY)
+ {
+ if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda))
+ {
+ BTM_TRACE_ERROR0("no pending IRK operation");
+ return;
+ }
+ if (status == HCI_SUCCESS)
+ {
+ STREAM_TO_UINT8(p_cb->irk_avail_size, p);
+ btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, FALSE);
+ }
+ else
+ {
+ /* give the credit back if invalid parameter failed the operation */
+ if (p_cb->irk_avail_size > 0)
+ p_cb->irk_list_size --;
+ }
+
+ }
+ else if (op_subcode == BTM_BLE_META_READ_IRK_ENTRY)
+ {
+ if (status == HCI_SUCCESS)
+ {
+ //STREAM_TO_UINT8(index, p);
+ p += (1 + 16 + 1); /* skip index, IRK value, address type */
+ STREAM_TO_BDADDR(target_bda, p);
+ STREAM_TO_BDADDR(rra, p);
+
+#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
+ btm_ble_refresh_rra(target_bda, rra);
+#endif
+ }
+ }
+
+}
+/*******************************************************************************
+**
+** Function btm_ble_remove_irk_entry
+**
+** Description This function to remove an IRK entry from the list
+**
+** Parameters ble_addr_type: address type
+** ble_addr: LE adddress
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_remove_irk_entry(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ UINT8 param[20], *p;
+ tBTM_STATUS st;
+ tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb;
+
+ p = param;
+ memset(param, 0, 20);
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_REMOVE_IRK_ENTRY);
+ UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
+ BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
+
+ if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_REMOVE_IRK_LEN,
+ param,
+ btm_ble_vendor_irk_vsc_op_cmpl))
+ != BTM_NO_RESOURCES)
+ {
+ btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, FALSE);
+ p_cb->irk_list_size --;
+ }
+
+ return st;
+
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_clear_irk_list
+**
+** Description This function clears the IRK entry list
+**
+** Parameters None.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_vendor_clear_irk_list(void)
+{
+ UINT8 param[20], *p;
+ tBTM_STATUS st;
+
+ p = param;
+ memset(param, 0, 20);
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_CLEAR_IRK_LIST);
+
+ st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_CLEAR_IRK_LEN,
+ param,
+ btm_ble_vendor_irk_vsc_op_cmpl);
+
+ return st;
+
+}
+/*******************************************************************************
+**
+** Function btm_ble_read_irk_entry
+**
+** Description This function read an IRK entry by index
+**
+** Parameters entry index.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_read_irk_entry(BD_ADDR target_bda)
+{
+ UINT8 param[20], *p;
+ tBTM_STATUS st = BTM_UNKNOWN_ADDR;
+ tBTM_BLE_IRK_ENTRY *p_entry = btm_ble_vendor_find_irk_entry(target_bda);
+
+ if (p_entry == NULL)
+ return st;
+
+ p = param;
+ memset(param, 0, 20);
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_READ_IRK_ENTRY);
+ UINT8_TO_STREAM(p, p_entry->index);
+
+ st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_READ_IRK_LEN,
+ param,
+ btm_ble_vendor_irk_vsc_op_cmpl);
+
+ return st;
+
+}
+
+
+/*******************************************************************************
+**
+** Function btm_ble_vendor_enable_irk_list_known_dev
+**
+** Description This function add all known device with random address into
+** IRK list.
+**
+** Parameters enable: enable IRK list with known device, or disable it
+**
+** Returns status
+**
+*******************************************************************************/
+void btm_ble_vendor_irk_list_known_dev(BOOLEAN enable)
+{
+ UINT8 i;
+ UINT8 count = 0;
+ tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+
+ /* add all known device with random address into IRK list */
+ for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++)
+ {
+ if (p_dev_rec->sec_flags & BTM_SEC_IN_USE)
+ {
+ if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
+ count ++;
+ }
+ }
+
+ if ((count > 0 && enable) || !enable)
+ BTM_BleEnableIRKFeature(enable);
+
+ return ;
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_irk_list_load_dev
+**
+** Description This function add a device which is using RPA into white list
+**
+** Parameters
+**
+** Returns status
+**
+*******************************************************************************/
+BOOLEAN btm_ble_vendor_irk_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ UINT8 param[40], *p;
+ tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb;
+ BOOLEAN rt = FALSE;
+ tBTM_BLE_IRK_ENTRY *p_irk_entry = NULL;
+ BTM_TRACE_DEBUG1 ("btm_ble_vendor_irk_list_load_dev:max_irk_size=%d", p_cb->irk_avail_size);
+ memset(param, 0, 40);
+
+ if (p_dev_rec != NULL && /* RPA is being used and PID is known */
+ (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0)
+ {
+
+ if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) == NULL &&
+ btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, TRUE) == FALSE)
+ {
+
+ if (p_cb->irk_avail_size > 0)
+ {
+ p = param;
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
+ ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
+ UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
+ BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr);
+
+ if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_ADD_IRK_LEN,
+ param,
+ btm_ble_vendor_irk_vsc_op_cmpl)
+ != BTM_NO_RESOURCES)
+ {
+ btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, TRUE);
+ p_cb->irk_list_size ++;
+ rt = TRUE;
+ }
+ }
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("Device already in IRK list");
+ rt = TRUE;
+ }
+ }
+ else
+ {
+ BTM_TRACE_DEBUG0("Device not a RPA enabled device");
+ }
+ return rt;
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_irk_list_remove_dev
+**
+** Description This function remove the device from IRK list
+**
+** Parameters
+**
+** Returns status
+**
+*******************************************************************************/
+void btm_ble_vendor_irk_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ tBTM_BLE_VENDOR_CB *p_cs_cb = &btm_ble_vendor_cb;
+ tBTM_BLE_IRK_ENTRY *p_irk_entry;
+
+ if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) != NULL &&
+ btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, FALSE) == FALSE)
+ {
+ btm_ble_remove_irk_entry(p_dev_rec);
+ }
+ else
+ {
+ BTM_TRACE_ERROR0("Device not in IRK list");
+ }
+
+ if (p_cs_cb->irk_list_size == 0)
+ BTM_BleEnableIRKFeature(FALSE);
+}
+/*******************************************************************************
+**
+** Function btm_ble_vendor_disable_irk_list
+**
+** Description disable LE resolve address feature
+**
+** Parameters
+**
+** Returns status
+**
+*******************************************************************************/
+void btm_ble_vendor_disable_irk_list(void)
+{
+ BTM_BleEnableIRKFeature(FALSE);
+
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleEnableIRKFeature
+**
+** Description This function is called to enable or disable the RRA
+** offloading feature.
+**
+** Parameters enable: enable or disable the RRA offloading feature
+**
+** Returns BTM_SUCCESS if successful
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleEnableIRKFeature(BOOLEAN enable)
+{
+ UINT8 param[20], *p;
+ tBTM_STATUS st = BTM_WRONG_MODE;
+ tBTM_BLE_PF_COUNT *p_bda_filter;
+
+ p = param;
+ memset(param, 0, 20);
+
+ /* select feature based on control block settings */
+ UINT8_TO_STREAM(p, BTM_BLE_META_IRK_ENABLE);
+ UINT8_TO_STREAM(p, enable ? 0x01 : 0x00);
+
+ st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_IRK_ENABLE_LEN,
+ param, btm_ble_vendor_irk_vsc_op_cmpl);
+
+ return st;
+}
+
+#endif
+
+
+/*******************************************************************************
+**
+** Function btm_ble_vendor_init
+**
+** Description Initialize customer specific feature information in host stack
+**
+** Parameters
+**
+** Returns status
+**
+*******************************************************************************/
+void btm_ble_vendor_init(void)
+{
+ //memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB));
+
+ if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+ return;
+}
+
+#endif
+
+
diff --git a/vnd/ble/vendor_hcidefs.h b/vnd/ble/vendor_hcidefs.h
new file mode 100644
index 0000000..f85e7fd
--- /dev/null
+++ b/vnd/ble/vendor_hcidefs.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2014 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 vendor_hcidefs.h
+**
+** Function This file contains Broadcom Specific Host Controller Interface
+** definitions.
+**
+******************************************************************************/
+
+#ifndef VENDOR_HCIDEFS_H
+#define VENDOR_HCIDEFS_H
+
+/*****************************************************************************
+** Private address resolution VSC
+******************************************************************************/
+
+/* VSC */
+#define HCI_VENDOR_BLE_RPA_VSC (0x0155 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* Sub codes */
+#define HCI_VENDOR_BLE_RPA_ENABLE 0x01
+#define HCI_VENDOR_BLE_RPA_ADD_IRK 0x02
+#define HCI_VENDOR_BLE_RPA_REMOVE_IRK 0x03
+#define HCI_VENDOR_BLE_RPA_CLEAR_IRK 0x04
+#define HCI_VENDOR_BLE_RPA_READ_IRK 0x05
+
+
+/*****************************************************************************
+** Advertising data payload filter VSC
+******************************************************************************/
+
+/* VSC */
+#define HCI_VENDOR_BLE_PCF_VSC (0x0157 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* Sub codes */
+#define BTM_BLE_META_PF_ENABLE 0x00
+#define BTM_BLE_META_PF_FEAT_SEL 0x01
+#define BTM_BLE_META_PF_ADDR 0x02
+#define BTM_BLE_META_PF_UUID 0x03
+#define BTM_BLE_META_PF_SOL_UUID 0x04
+#define BTM_BLE_META_PF_LOCAL_NAME 0x05
+#define BTM_BLE_META_PF_MANU_DATA 0x06
+#define BTM_BLE_META_PF_SRVC_DATA 0x07
+
+#endif
+
diff --git a/vnd/include/bta_vendor_api.h b/vnd/include/bta_vendor_api.h
new file mode 100644
index 0000000..0935b14
--- /dev/null
+++ b/vnd/include/bta_vendor_api.h
@@ -0,0 +1,101 @@
+
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2014 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: bta_vendor_api.h
+**
+** Description: VENDOR custom Ble API Bluetooth application definitions
+**
+*****************************************************************************/
+#ifndef BTA_VENDOR_API_H
+#define BTA_VENDOR_API_H
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "vendor_api.h"
+
+
+#define BTA_DM_BLE_PF_ENABLE_EVT BTM_BLE_PF_ENABLE
+#define BTA_DM_BLE_PF_CONFIG_EVT BTM_BLE_PF_CONFIG
+typedef UINT8 tBTA_DM_BLE_PF_EVT;
+
+/* Search callback */
+typedef void (tBTA_DM_SCAN_PF_CBACK)(tBTA_DM_BLE_PF_EVT event, tBTA_DM_BLE_PF_COND_TYPE cfg_cond, tBTA_STATUS status);;
+
+
+#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE)
+/*******************************************************************************
+**
+** Function BTA_DmBleEnableFilterCondition
+**
+** Description This function is called to enable the adv data payload filter
+** condition.
+**
+** Parameters p_target: enabble the filter condition on a target device; if NULL
+** enable the generic scan condition.
+** enable: enable or disable the filter condition
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleEnableFilterCondition(BOOLEAN enable,
+ tBLE_BD_ADDR *p_target,
+ tBTA_DM_SCAN_PF_CBACK *p_cmpl_cback);
+
+/*******************************************************************************
+**
+** Function BTA_BrcmInit
+**
+** Description This function initializes Broadcom specific VS handler in BTA
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_BrcmInit (void);
+
+
+/*******************************************************************************
+**
+** Function BTA_DmBleCfgFilterCondition
+**
+** Description This function is called to configure the adv data payload filter
+** condition.
+**
+** Parameters action: to read/write/clear
+** cond_type: filter condition type.
+** p_cond: filter condition paramter
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action,
+ tBTA_DM_BLE_PF_COND_TYPE cond_type,
+ tBTA_DM_BLE_PF_COND_PARAM *p_cond,
+ tBTA_DM_SCAN_PF_CBACK *p_cmpl_cback);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/vnd/include/vendor_api.h b/vnd/include/vendor_api.h
new file mode 100644
index 0000000..c69c420
--- /dev/null
+++ b/vnd/include/vendor_api.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Name: vendor_api.h
+**
+** Description: Vendor specific BTE API function external definitions.
+**
+** Copyright (c) 2009-2011, BROADCOM Inc., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+******************************************************************************/
+#ifndef VENDOR_API_H
+#define VENDOR_API_H
+
+#include "bt_types.h"
+#include "btm_api.h"
+
+/****************************************************************************
+** Resolvable private address offload VSC specific definitions
+******************************************************************************/
+
+enum
+{
+ BTM_BLE_PRIVACY_ENABLE,
+ BTM_BLE_PRIVACY_DISABLE
+};
+
+
+/****************************************************************************
+** Advertising packet filter VSC specific definitions
+******************************************************************************/
+
+enum
+{
+ BTM_BLE_SCAN_COND_ADD,
+ BTM_BLE_SCAN_COND_DELETE,
+ BTM_BLE_SCAN_COND_CLEAR = 2
+};
+typedef UINT8 tBTM_BLE_SCAN_COND_OP;
+
+/* filter selection bit index */
+#define BTM_BLE_PF_ADDR_FILTER 0
+#define BTM_BLE_PF_SRVC_DATA 1
+#define BTM_BLE_PF_SRVC_UUID 2
+#define BTM_BLE_PF_SRVC_SOL_UUID 3
+#define BTM_BLE_PF_LOCAL_NAME 4
+#define BTM_BLE_PF_MANU_DATA 5
+#define BTM_BLE_PF_SRVC_DATA_PATTERN 6
+#define BTM_BLE_PF_TYPE_ALL 7 /* when passed in payload filter type all, only clear action is applicable */
+#define BTM_BLE_PF_TYPE_MAX 8
+
+typedef UINT8 tBTM_BLE_PF_COND_TYPE;
+
+#define BTM_BLE_PF_LOGIC_OR 0
+#define BTM_BLE_PF_LOGIC_AND 1
+typedef UINT8 tBTM_BLE_PF_LOGIC_TYPE;
+
+/* max number of filter spot for different filter type */
+#ifndef BTM_BLE_MAX_UUID_FILTER
+#define BTM_BLE_MAX_UUID_FILTER 8
+#endif
+#ifndef BTM_BLE_MAX_ADDR_FILTER
+#define BTM_BLE_MAX_ADDR_FILTER 8
+#endif
+#ifndef BTM_BLE_PF_STR_COND_MAX
+#define BTM_BLE_PF_STR_COND_MAX 4 /* apply to manu data , or local name */
+#endif
+#ifndef BTM_BLE_PF_STR_LEN_MAX
+#define BTM_BLE_PF_STR_LEN_MAX 20 /* match for first 20 bytes */
+#endif
+
+#define BTM_BLE_PF_ENABLE 1
+#define BTM_BLE_PF_CONFIG 2
+typedef UINT8 tBTM_BLE_PF_ACTION;
+
+/* BLE adv payload filtering operation complete callback */
+typedef void (tBTM_BLE_PF_CMPL_CBACK)(tBTM_BLE_PF_ACTION action, tBTM_BLE_PF_COND_TYPE cfg_cond, tBTM_STATUS status);
+
+typedef union
+{
+ UINT16 uuid16_mask;
+ UINT32 uuid32_mask;
+ UINT8 uuid128_mask[LEN_UUID_128];
+}tBTM_BLE_PF_COND_MASK;
+
+typedef struct
+{
+ tBLE_BD_ADDR *p_target_addr; /* target address, if NULL, generic UUID filter */
+ tBT_UUID uuid; /* UUID condition */
+ tBTM_BLE_PF_LOGIC_TYPE cond_logic; /* AND/OR */
+ tBTM_BLE_PF_COND_MASK *p_uuid_mask; /* UUID mask */
+}tBTM_BLE_PF_UUID_COND;
+
+typedef struct
+{
+ UINT8 data_len; /* <= 20 bytes */
+ UINT8 *p_data;
+}tBTM_BLE_PF_LOCAL_NAME_COND;
+
+typedef struct
+{
+ UINT16 company_id; /* company ID */
+ UINT8 data_len; /* <= 20 bytes */
+ UINT8 *p_pattern;
+ UINT16 company_id_mask; /* UUID value mask */
+ UINT8 *p_pattern_mask; /* Manufactuer data matching mask, same length as data pattern,
+ set to all 0xff, match exact data */
+}tBTM_BLE_PF_MANU_COND;
+
+typedef struct
+{
+ UINT16 uuid; /* service ID */
+ UINT8 data_len; /* <= 20 bytes */
+ UINT8 *p_pattern;
+}tBTM_BLE_PF_SRVC_PATTERN_COND;
+
+
+typedef union
+{
+ tBLE_BD_ADDR target_addr;
+ tBTM_BLE_PF_LOCAL_NAME_COND local_name; /* lcoal name filtering */
+ tBTM_BLE_PF_MANU_COND manu_data; /* manufactuer data filtering */
+ tBTM_BLE_PF_UUID_COND srvc_uuid; /* service UUID filtering */
+ tBTM_BLE_PF_UUID_COND solicitate_uuid; /* solicitated service UUID filtering */
+ tBTM_BLE_PF_SRVC_PATTERN_COND srvc_data; /* service data pattern */
+}tBTM_BLE_PF_COND_PARAM;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************
+** VENDOR SPECIFIC BLE FEATURE FUNCTIONS
+******************************************************************************/
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+
+/*******************************************************************************
+**
+** Function BTM_BleEnableFilterCondition
+**
+** Description This function is called to enable the adv data payload filter
+** condition.
+**
+** Parameters p_target: enabble the filter condition on a target device; if NULL
+** enable the generic scan condition.
+** enable: enable or disable the filter condition
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleEnableFilterCondition(BOOLEAN enable,
+ tBLE_BD_ADDR *p_target,
+ tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback);
+
+/*******************************************************************************
+**
+** Function BTM_BleCfgFilterCondition
+**
+** Description This function is called to configure the adv data payload filter
+** condition.
+**
+** Parameters action: to read/write/clear
+** cond_type: filter condition type.
+** p_cond: filter condition paramter
+**
+** Returns tBTM_STATUS
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action,
+ tBTM_BLE_PF_COND_TYPE cond_type,
+ tBTM_BLE_PF_COND_PARAM *p_cond,
+ tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback);
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vnd/include/vendor_ble.h b/vnd/include/vendor_ble.h
new file mode 100644
index 0000000..39c529e
--- /dev/null
+++ b/vnd/include/vendor_ble.h
@@ -0,0 +1,144 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2014 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: vendor_ble.h
+**
+** Description: This file contains vendor specific feature header
+** for BLE
+******************************************************************************/
+#ifndef VENDOR_BLE_H
+#define VENDOR_BLE_H
+
+#include "btm_int.h"
+#include "btm_ble_api.h"
+#include "vendor_api.h"
+
+/* RPA offload VSC specifics */
+#define BTM_BLE_META_IRK_ENABLE 0x01
+#define BTM_BLE_META_ADD_IRK_ENTRY 0x02
+#define BTM_BLE_META_REMOVE_IRK_ENTRY 0x03
+#define BTM_BLE_META_CLEAR_IRK_LIST 0x04
+#define BTM_BLE_META_READ_IRK_ENTRY 0x05
+#define BTM_BLE_META_CS_RESOLVE_ADDR 0x00000001
+#define BTM_BLE_IRK_ENABLE_LEN 2
+
+/* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */
+#define BTM_BLE_META_HDR_LENGTH 3
+#define BTM_BLE_PF_FEAT_SEL_LEN 18
+#define BTM_BLE_PCF_ENABLE_LEN 2
+#define BTM_BLE_META_ADDR_LEN 7
+#define BTM_BLE_META_UUID_LEN 40
+#define BTM_BLE_META_ADD_IRK_LEN 24
+#define BTM_BLE_META_REMOVE_IRK_LEN 8
+#define BTM_BLE_META_CLEAR_IRK_LEN 1
+#define BTM_BLE_META_READ_IRK_LEN 2
+#define BTM_BLE_META_ADD_WL_ATTR_LEN 9
+
+#define BTM_BLE_PF_BIT_TO_MASK(x) (UINT32)(1 << (x))
+#define BTM_BLE_PF_SELECT_NONE 0
+#define BTM_BLE_PF_ADDR_FILTER_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_ADDR_FILTER)
+#define BTM_BLE_PF_SRVC_DATA_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_DATA)
+#define BTM_BLE_PF_SRVC_UUID_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_UUID)
+#define BTM_BLE_PF_SRVC_SOL_UUID_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_SOL_UUID)
+#define BTM_BLE_PF_LOCAL_NAME_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_LOCAL_NAME)
+#define BTM_BLE_PF_MANU_DATA_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_MANU_DATA)
+#define BTM_BLE_PF_SRVC_DATA_PATTERN_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_DATA_PATTERN)
+typedef UINT8 tBTM_BLE_PF_SEL_MASK;
+
+
+#define BTM_BLE_MAX_FILTER_COUNTER (BTM_BLE_MAX_ADDR_FILTER + 1) /* per device filter + one generic filter indexed by 0 */
+
+typedef struct
+{
+ BOOLEAN in_use;
+ BD_ADDR bd_addr;
+ UINT32 feat_mask; /* per BD_ADDR feature mask */
+ UINT8 pf_counter[BTM_BLE_PF_TYPE_MAX]; /* number of filter indexed by tBTM_BLE_PF_COND_TYPE */
+}tBTM_BLE_PF_COUNT;
+
+#ifndef BTM_CS_IRK_LIST_MAX
+#define BTM_CS_IRK_LIST_MAX 0x20
+#endif
+
+#define BTM_CS_IRK_LIST_INVALID 0xff
+
+typedef struct
+{
+ BOOLEAN in_use;
+ BD_ADDR bd_addr; /* must be the address used in controller */
+ BD_ADDR psuedo_bda; /* the random pseudo address */
+ UINT8 index;
+}tBTM_BLE_IRK_ENTRY;
+
+
+typedef struct
+{
+ BD_ADDR irk_q[BTM_CS_IRK_LIST_MAX];
+ BD_ADDR irk_q_random_pseudo[BTM_CS_IRK_LIST_MAX];
+ UINT8 irk_q_action[BTM_CS_IRK_LIST_MAX];
+ UINT8 q_next;
+ UINT8 q_pending;
+} tBTM_BLE_IRK_Q;
+
+/* control block for BLE customer specific feature */
+typedef struct
+{
+ BOOLEAN enable;
+
+ UINT8 op_type;
+ tBTM_BLE_PF_COUNT addr_filter_count[BTM_BLE_MAX_FILTER_COUNTER]; /* per BDA filter indexed by tBTM_BLE_PF_COND_TYPE */
+ tBLE_BD_ADDR cur_filter_target;
+
+ UINT8 irk_list_size;
+ UINT8 irk_avail_size;
+ tBTM_BLE_IRK_ENTRY irk_list[BTM_CS_IRK_LIST_MAX];
+ tBTM_BLE_IRK_Q irk_pend_q;
+
+ tBTM_BLE_PF_CMPL_CBACK *p_scan_pf_cback;
+}tBTM_BLE_VENDOR_CB;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if VENDOR_DYNAMIC_MEMORY == FALSE
+BTM_API extern tBTM_BLE_VENDOR_CB btm_ble_vendor_cb;
+#else
+BTM_API extern tBTM_BLE_VENDOR_CB *btm_ble_vendor_ptr;
+#define btm_ble_vendor_cb (*btm_ble_vendor_ptr)
+#endif
+
+extern void btm_ble_vendor_irk_list_known_dev(BOOLEAN enable);
+extern tBTM_STATUS btm_ble_read_irk_entry(BD_ADDR target_bda);
+extern void btm_ble_vendor_disable_irk_list(void);
+extern BOOLEAN btm_ble_vendor_irk_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
+extern void btm_ble_vendor_irk_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
+extern tBTM_STATUS btm_ble_enable_vendor_feature (BOOLEAN enable, UINT32 feature_bit);
+
+extern void btm_ble_vendor_init(void);
+extern BOOLEAN btm_ble_vendor_write_device_wl_attribute (tBLE_ADDR_TYPE addr_type, BD_ADDR bd_addr, UINT8 attribute);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+