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 *)&param);
+}
+
+/*******************************************************************************
+**
+** 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 *)&param);
+}
+#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
+
+