LE: Add controller based advertising filter API (2/2)
Change-Id: I444654bf19a048d5fcef33f79edbf1cdda3d3b62
diff --git a/bta/Android.mk b/bta/Android.mk
index ce7b6f3..89eca5f 100644
--- a/bta/Android.mk
+++ b/bta/Android.mk
@@ -75,7 +75,8 @@
./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
@@ -95,7 +96,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/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 6a72e97..92bdded 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -5424,6 +5424,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_int.h b/bta/dm/bta_dm_int.h
index dd3e16c..784d49e 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -103,6 +103,11 @@
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
#endif
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -565,6 +570,25 @@
BOOLEAN remove_dev;
}tBTA_DM_API_REMOVE_ACL;
+#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 +664,10 @@
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
#endif
tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT set_afh_channel_assessment;
@@ -1001,6 +1029,11 @@
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
+
#endif
extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
extern void bta_dm_confirm(tBTA_DM_MSG *p_data);
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index 0f6b91a..74f4d82 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -100,6 +100,10 @@
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
#endif
#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 4345fbf..86d9182 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -432,20 +432,29 @@
/* 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_TYPE_ALL BTM_BLE_PF_TYPE_ALL
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 +468,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 +487,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;
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/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/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_gatt_client.c b/btif/src/btif_gatt_client.c
index c788bd8..59840af 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -51,6 +51,9 @@
#include "btif_dm.h"
#include "btif_storage.h"
+#include "bta_vendor_api.h"
+#include "vendor_api.h"
+
/*******************************************************************************
** Constants & Macros
********************************************************************************/
@@ -92,12 +95,16 @@
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_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
@@ -119,8 +126,10 @@
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;
uint8_t client_if;
uint8_t action;
uint8_t is_direct;
@@ -130,6 +139,7 @@
uint8_t status;
uint8_t addr_type;
uint8_t start;
+ uint8_t has_mask;
int8_t rssi;
tBT_DEVICE_TYPE device_type;
} __attribute__((packed)) btif_gattc_cb_t;
@@ -524,6 +534,13 @@
, 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;
+ }
default:
ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
@@ -592,6 +609,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)
{
@@ -854,6 +880,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);
@@ -1334,6 +1453,52 @@
(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 int btif_gattc_get_device_type( const bt_bdaddr_t *bd_addr )
{
int device_type = 0;
@@ -1373,6 +1538,9 @@
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,
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
index 715dcd6..91cf004 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
*******************************************************************************/
diff --git a/include/bt_target.h b/include/bt_target.h
index 0fc90f0..5ac668c 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -1403,6 +1403,11 @@
#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
diff --git a/main/Android.mk b/main/Android.mk
index 9cc5bbf..d76e4d2 100644
--- a/main/Android.mk
+++ b/main/Android.mk
@@ -92,7 +92,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 \
diff --git a/stack/Android.mk b/stack/Android.mk
index a801771..65dc79f 100644
--- 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,7 +28,6 @@
$(LOCAL_PATH)/../ctrlr/include \
$(LOCAL_PATH)/../bta/include \
$(LOCAL_PATH)/../bta/sys \
- $(LOCAL_PATH)/../brcm/include \
$(LOCAL_PATH)/../utils/include \
$(bdroid_C_INCLUDES) \
@@ -143,7 +144,8 @@
./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
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 7ce4f16..7a05507 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -299,7 +299,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 */
diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c
index a4e55da..aa2e747 100644
--- a/stack/hcic/hciblecmds.c
+++ b/stack/hcic/hciblecmds.c
@@ -163,7 +163,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 +186,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);
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index cb85cb1..318e748 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -1267,7 +1267,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);
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..b686908
--- /dev/null
+++ b/vnd/ble/vendor_ble.c
@@ -0,0 +1,961 @@
+/******************************************************************************
+ *
+ * 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 */
+const static 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);
+
+ 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);
+
+ 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);
+
+ 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 + 7;
+ 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);
+
+ 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);
+
+ /* per BD ADDR UUID filter */
+ if (p_uuid_cond && p_uuid_cond->p_target_addr)
+ {
+ BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda);
+ UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type);
+ }
+ else /* generic UUID filter */
+ {
+ BDADDR_TO_STREAM(p, na_bda);
+ UINT8_TO_STREAM(p, 0x02);
+ }
+
+ if (action == BTM_BLE_SCAN_COND_ADD ||
+ action == BTM_BLE_SCAN_COND_DELETE)
+ {
+ UINT8_TO_STREAM(p, p_uuid_cond->cond_logic);
+ len ++;
+
+ 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);
+
+ if (p_target != NULL)
+ {
+ BDADDR_TO_STREAM(p, p_target->bda);
+ UINT8_TO_STREAM(p, p_target->type);
+ }
+ else
+ {
+ BDADDR_TO_STREAM(p, na_bda);
+ UINT8_TO_STREAM(p, 0x02);
+ }
+
+ /* 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);
+
+ if (p_target != NULL)
+ {
+ BDADDR_TO_STREAM(p, p_target->bda);
+ UINT8_TO_STREAM(p, p_target->type);
+ }
+ else
+ {
+ BDADDR_TO_STREAM(p, na_bda);
+ UINT8_TO_STREAM(p, 0x02);
+ }
+
+ /* 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;
+}
+
+
+/*******************************************************************************
+**
+** 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..dd2a1ca
--- /dev/null
+++ b/vnd/ble/vendor_hcidefs.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * 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
+
+/* advertising data payload filter VSC */
+#define HCI_VENDOR_BLE_PCF_VSC (0x0138 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* BLE PCF VSC sub code */
+#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..3c65a35
--- /dev/null
+++ b/vnd/include/vendor_api.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** 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"
+
+
+/*************************************
+** VENDOR BLE 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..432b55e
--- /dev/null
+++ b/vnd/include/vendor_ble.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: 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"
+
+/* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */
+#define BTM_BLE_META_HDR_LENGTH 2
+#define BTM_BLE_PF_FEAT_SEL_LEN 12
+#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;
+
+
+/* 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;
+
+ 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_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
+
+