#include "eir.h"
#ifdef __TIZEN_PATCH__
+#define TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+#endif
+
+#ifdef __TIZEN_PATCH__
#include "adapter_le_vsc_features.h"
#endif
#define LE_BEARER_POSTFIX " LE"
#define LE_BEARER_POSTFIX_LEN 3
+
+/* Slot value shall be changed when required */
+#define SCAN_FILTER_SLOTS_MAX 20
#endif /* __TIZEN_PATCH__ */
#ifdef __TIZEN_PATCH__
guint private_addr_timeout;
uint8_t central_rpa_res_support;
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ bool scan_filter_support; /* platform's scan filtering support */
+ uint8_t scan_type; /* scan type */
+ GSList *scan_params; /* scan filter parameters */
+ GSList *addr_filters; /* adress scan filters list */
+ GSList *service_data_changed_filters; /* service data changed scan filters list */
+ GSList *service_uuid_filters; /* service uuid scan filters list */
+ GSList *solicit_data_filters; /* solicitation data scan filters list */
+ GSList *local_name_filters; /* local name scan filters list */
+ GSList *manufaturer_data_filters; /* manufacturer data scan filters list */
+ GSList *service_data_filters; /* service data scan filters list */
+#endif
#endif
bool is_default; /* true if adapter is default one */
};
stop_discovery_complete, adapter, NULL);
}
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+static void addr_filter_params_free(gpointer data, gpointer user_data)
+{
+ adapter_le_address_filter_params_t *params = data;
+
+ g_free(params);
+}
+
+static void uuid_filter_params_free(gpointer data, gpointer user_data)
+{
+ adapter_le_uuid_params_t *params = data;
+
+ g_free((char *)params->uuid);
+ g_free((char *)params->uuid_mask);
+ g_free(params);
+}
+
+static void manufacturer_filter_params_free(gpointer data, gpointer user_data)
+{
+ adapter_le_manf_data_params_t *params = data;
+
+ g_free((char *)params->man_data);
+ g_free((char *)params->man_data_mask);
+ g_free(params);
+}
+
+static void local_name_filter_params_free(gpointer data, gpointer user_data)
+{
+ adapter_le_local_name_params_t *params = data;
+
+ g_free((char *)params->local_name);
+ g_free(params);
+}
+
+static void service_data_filter_params_free(gpointer data, gpointer user_data)
+{
+ adapter_le_service_data_params_t *params = data;
+
+ g_free((char *)params->service_data);
+ g_free((char *)params->service_data_mask);
+ g_free(params);
+}
+
+static void scan_filter_params_free(gpointer data, gpointer user_data)
+{
+ adapter_le_scan_filter_param_t *params = data;
+ g_free(params);
+}
+
+int adapter_le_address_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_address_filter_params_t *params = a;
+ const char *address = b;
+ char addr[18];
+
+ ba2str(¶ms->broadcaster_addr, addr);
+ return strcasecmp(addr, address);
+}
+
+int adapter_le_uuid_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_uuid_params_t *params = a;
+ const char *uuid = b;
+
+ return strcasecmp((const char *)params->uuid, uuid);
+}
+
+int adapter_le_manufacturer_data_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_manf_data_params_t *params = a;
+ const struct eir_msd *msd = b;
+
+ if (msd->company == params->company_id)
+ return strncasecmp((const char *)params->man_data, msd->data, params->man_data_len);
+ else
+ return -1;
+}
+
+int adapter_le_local_name_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_local_name_params_t *params = a;
+ const char *name = b;
+
+ return strcasecmp(params->local_name, name);
+}
+
+int adapter_le_service_data_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_service_data_params_t *params = a;
+ const struct eir_sd *sd = b;
+ /* Todo, the service data format for 16 bit, 32bit and
+ * 128 bit uuids needs to addressed */
+ return strncasecmp((const char *)(params->service_data), sd->data, sd->data_len);
+}
+
+int adapter_le_address_filter_index_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_address_filter_params_t *params = a;
+ uint16_t filter_inex = GPOINTER_TO_UINT(b);
+
+ return params->filter_index - filter_inex;
+}
+
+int adapter_le_uuid_filter_index_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_uuid_params_t *params = a;
+ uint16_t filter_inex = GPOINTER_TO_UINT(b);
+
+ return params->filter_index - filter_inex;
+}
+
+int adapter_le_manufacturer_data_filter_index_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_manf_data_params_t *params = a;
+ uint16_t filter_inex = GPOINTER_TO_UINT(b);
+
+ return params->filter_index - filter_inex;
+}
+
+int adapter_le_local_name_filter_index_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_local_name_params_t *params = a;
+ uint16_t filter_inex = GPOINTER_TO_UINT(b);
+
+ return params->filter_index - filter_inex;
+}
+
+int adapter_le_service_data_filter_index_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_service_data_params_t *params = a;
+ uint16_t filter_inex = GPOINTER_TO_UINT(b);
+
+ return params->filter_index - filter_inex;
+}
+
+int adapter_le_scan_params_filter_index_cmp(gconstpointer a, gconstpointer b)
+{
+ const adapter_le_scan_filter_param_t *params = a;
+ uint16_t filter_inex = GPOINTER_TO_UINT(b);
+
+ return params->index - filter_inex;
+}
+
+static gboolean adapter_le_clear_platform_scan_filter_data (
+ struct btd_adapter *adapter, int filter_index)
+{
+ DBG("");
+ GSList *list;
+ if (!adapter)
+ return FALSE;
+
+ list = g_slist_find_custom(adapter->addr_filters,
+ GINT_TO_POINTER(filter_index), adapter_le_address_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->addr_filters = g_slist_delete_link(adapter->addr_filters, list);
+ }
+ list = g_slist_find_custom(adapter->service_data_changed_filters,
+ GINT_TO_POINTER(filter_index), adapter_le_service_data_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->service_data_changed_filters = g_slist_delete_link(adapter->service_data_changed_filters, list);
+ }
+
+ list = g_slist_find_custom(adapter->service_uuid_filters,
+ GINT_TO_POINTER(filter_index), adapter_le_uuid_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->service_uuid_filters = g_slist_delete_link(adapter->service_uuid_filters, list);
+ }
+
+ list = g_slist_find_custom(adapter->solicit_data_filters,
+ GINT_TO_POINTER(filter_index), adapter_le_uuid_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->solicit_data_filters = g_slist_delete_link(adapter->solicit_data_filters, list);
+ }
+
+ list = g_slist_find_custom(adapter->local_name_filters,
+ GINT_TO_POINTER(filter_index), adapter_le_local_name_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->local_name_filters = g_slist_delete_link(adapter->local_name_filters, list);
+ }
+
+ list = g_slist_find_custom(adapter->manufaturer_data_filters,
+ GINT_TO_POINTER(filter_index), adapter_le_manufacturer_data_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->manufaturer_data_filters = g_slist_delete_link(adapter->manufaturer_data_filters, list);
+ }
+
+ list = g_slist_find_custom(adapter->service_data_filters,
+ GINT_TO_POINTER(filter_index), adapter_le_service_data_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->service_data_filters = g_slist_delete_link(adapter->service_data_filters, list);
+ }
+
+ list = g_slist_find_custom(adapter->scan_params,
+ GINT_TO_POINTER(filter_index), adapter_le_scan_params_filter_index_cmp);
+ if (list && list->data) {
+ /* Delete info from the struct to list */
+ adapter->scan_params = g_slist_delete_link(adapter->scan_params, list);
+ }
+
+ return TRUE;
+}
+
+static gboolean adapter_le_enable_platform_scan_filtering (
+ struct btd_adapter *adapter, gboolean enable)
+{
+ if (!adapter)
+ return FALSE;
+
+ DBG("Platform scan filtering enable[%d]", enable);
+
+ adapter->scan_filter_support = enable;
+
+ return TRUE;
+}
+
+
+static gboolean adapter_le_service_add_addr_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, gchar *string, int addr_type)
+{
+ /* TYPE_DEVICE_ADDRESS */
+ adapter_le_address_filter_params_t *params;
+
+ DBG("");
+
+ params = g_new0(adapter_le_address_filter_params_t, 1);
+ if (!params)
+ return FALSE;
+
+ params->filter_index = filter_index;
+ str2ba(string, ¶ms->broadcaster_addr);
+ params->bdaddr_type = addr_type;
+
+ /* Store the struct to list */
+ adapter->addr_filters = g_slist_append(adapter->addr_filters, params);
+ return TRUE;
+}
+
+static const char *adapter_le_service_find_addr_scan_filter_data(
+ struct btd_adapter *adapter, gchar *string)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->addr_filters, string, adapter_le_address_cmp);
+ if (!list)
+ return NULL;
+ else
+ return list->data;
+
+ return NULL;
+}
+
+static gboolean adapter_le_service_delete_addr_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, gchar *string, int addr_type)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->addr_filters, string, adapter_le_address_cmp);
+ if (!list)
+ return FALSE;
+ else
+ /* Delete info from the struct to list */
+ adapter->addr_filters = g_slist_delete_link(adapter->addr_filters, list);
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_clear_addr_scan_filter_data(struct btd_adapter *adapter)
+{
+ DBG("");
+
+ g_slist_free_full(adapter->addr_filters, addr_filter_params_free);
+ adapter->addr_filters = NULL;
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_add_uuid_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, gboolean is_solicited, uint8_t *p_uuid,
+ uint8_t *p_uuid_mask, int uuid_mask_len)
+{
+
+ adapter_le_uuid_params_t *params;
+ bt_uuid_t uuid;
+
+ DBG("");
+
+ params = g_new0(adapter_le_uuid_params_t, 1);
+ if (!params)
+ return FALSE;
+
+ if (uuid_mask_len == UUID_16_LEN) {
+ uint16_t *uuid16 = (void *)p_uuid;
+ sdp_uuid16_create(&uuid, get_be16(uuid16));
+ } else if (uuid_mask_len == UUID_32_LEN) {
+ uint32_t *uuid32 = (void *)p_uuid;
+ sdp_uuid32_create(&uuid, get_be32(uuid32));
+ } else {
+ sdp_uuid128_create(&uuid, p_uuid);
+ }
+ params->filter_index = filter_index;
+ params->uuid = bt_uuid2string(&uuid);
+ params->uuid_mask = g_new0(uint8_t, uuid_mask_len);
+ memcpy(params->uuid_mask, p_uuid_mask, uuid_mask_len);
+ params->uuid_len = uuid_mask_len;
+
+ /* Store the struct to list */
+ adapter->solicit_data_filters = g_slist_append(adapter->solicit_data_filters, params);
+
+ return TRUE;
+}
+
+static adapter_le_uuid_params_t *adapter_le_service_find_uuid_scan_filter_data(struct btd_adapter *adapter,
+ uint8_t *p_uuid)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->solicit_data_filters, p_uuid, adapter_le_uuid_cmp);
+ if (!list)
+ return NULL;
+ else
+ /* Delete info from the struct to list */
+ return list->data;
+
+ return NULL;
+}
+
+static gboolean adapter_le_service_delete_uuid_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, gboolean is_solicited, uint8_t *p_uuid,
+ uint8_t *p_uuid_mask, int uuid_mask_len)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->solicit_data_filters, GINT_TO_POINTER(filter_index), adapter_le_uuid_filter_index_cmp);
+ if (!list)
+ return FALSE;
+ else {
+ adapter_le_uuid_params_t *params = list->data;
+ /* Delete info from the struct to list */
+ if (params && strcasecmp((const char *)params->uuid, (const char *)p_uuid)) {
+ adapter->solicit_data_filters = g_slist_delete_link(adapter->solicit_data_filters, list);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_clear_uuid_scan_filter_data(struct btd_adapter *adapter)
+{
+ DBG("");
+
+ g_slist_free_full(adapter->solicit_data_filters, uuid_filter_params_free);
+ adapter->solicit_data_filters = NULL;
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_add_manufacturer_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, int company_id, int company_id_mask,
+ uint8_t *p_data, uint8_t *p_mask, int data_len)
+{
+
+ adapter_le_manf_data_params_t *params;
+
+ DBG("");
+
+ params = g_new0(adapter_le_manf_data_params_t, 1);
+ if (!params)
+ return FALSE;
+
+ params->filter_index = filter_index;
+ params->company_id = company_id;
+ params->company_id_mask = company_id_mask;
+ params->man_data = g_new0(uint8_t, data_len);
+ memcpy(params->man_data, p_data, data_len);
+ params->man_data_mask = g_new0(uint8_t, data_len);
+ memcpy(params->man_data_mask, p_mask, data_len);
+ params->man_data_len = data_len;
+
+ /* Store the struct to list */
+ adapter->manufaturer_data_filters = g_slist_append(adapter->manufaturer_data_filters, params);
+
+ return TRUE;
+}
+
+static adapter_le_manf_data_params_t *adapter_le_service_find_manufacturer_scan_filter_data(struct btd_adapter *adapter,
+ struct eir_msd *msd)
+{
+ GSList *list;
+ DBG("");
+ list = g_slist_find_custom(adapter->manufaturer_data_filters, msd, adapter_le_manufacturer_data_cmp);
+ if (!list)
+ return NULL;
+ else
+ return list->data;
+
+ return NULL;
+}
+
+static gboolean adapter_le_service_delete_manufacturer_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, int company_id, int company_id_mask,
+ uint8_t *p_data, uint8_t *p_mask, int data_len)
+{
+ GSList *list;
+ DBG("");
+ list = g_slist_find_custom(adapter->manufaturer_data_filters, GINT_TO_POINTER(filter_index), adapter_le_manufacturer_data_filter_index_cmp);
+ if (!list)
+ return FALSE;
+ else {
+ adapter_le_manf_data_params_t *params = list->data;
+ /* Delete info from the struct to list */
+ if (params && strcasecmp((const char *)params->man_data, (const char *)p_data)) {
+ adapter->manufaturer_data_filters = g_slist_delete_link(adapter->manufaturer_data_filters, list);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_clear_manufacturer_scan_filter_data(struct btd_adapter *adapter)
+{
+ DBG("");
+
+ g_slist_free_full(adapter->manufaturer_data_filters, manufacturer_filter_params_free);
+ adapter->manufaturer_data_filters = NULL;
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_add_local_name_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, gchar *name)
+{
+
+ adapter_le_local_name_params_t *params;
+
+ DBG("");
+
+ params = g_new0(adapter_le_local_name_params_t, 1);
+ if (!params)
+ return FALSE;
+
+ params->filter_index = filter_index;
+ params->local_name = g_strdup(name);
+ params->name_len = strlen(name);
+
+ /* Store the struct to list */
+ adapter->local_name_filters = g_slist_append(adapter->local_name_filters, params);
+
+ return TRUE;
+}
+
+static adapter_le_local_name_params_t *adapter_le_service_find_local_name_scan_filter_data(
+ struct btd_adapter *adapter,
+ gchar *name)
+{
+ GSList *list;
+ DBG("");
+ list = g_slist_find_custom(adapter->local_name_filters, name, adapter_le_local_name_cmp);
+ if (!list)
+ return NULL;
+ else
+ return list->data;
+
+ return NULL;
+}
+
+static gboolean adapter_le_service_delete_local_name_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, gchar *name)
+{
+ GSList *list;
+ DBG("");
+ list = g_slist_find_custom(adapter->local_name_filters, GINT_TO_POINTER(filter_index), adapter_le_local_name_filter_index_cmp);
+ if (!list)
+ return FALSE;
+ else {
+ adapter_le_local_name_params_t *params = list->data;
+ /* Delete info from the struct to list */
+ if (params && strcasecmp((const char *)params->local_name, (const char *)name)) {
+ adapter->local_name_filters = g_slist_delete_link(adapter->local_name_filters, list);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_clear_local_name_scan_filter_data(struct btd_adapter *adapter)
+{
+ DBG("");
+
+ g_slist_free_full(adapter->local_name_filters, local_name_filter_params_free);
+ adapter->local_name_filters = NULL;
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_add_service_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, uint8_t *p_data, uint8_t *p_mask, int data_len)
+{
+ adapter_le_service_data_params_t *params;
+
+ DBG("");
+
+ params = g_new0(adapter_le_service_data_params_t, 1);
+ if (!params)
+ return FALSE;
+
+ params->filter_index = filter_index;
+ params->service_data = g_new0(uint8_t, data_len);
+ memcpy(params->service_data, p_data, data_len);
+ params->service_data_mask = g_new0(uint8_t, data_len);
+ memcpy(params->service_data_mask, p_mask, data_len);
+ params->service_data_len = data_len;
+
+ /* Store the struct to list */
+ adapter->service_data_filters = g_slist_append(adapter->service_data_filters, params);
+
+ return TRUE;
+}
+
+static adapter_le_service_data_params_t *adapter_le_service_find_service_scan_filter_data(
+ struct btd_adapter *adapter, struct eir_sd *sd)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->service_data_filters, sd, adapter_le_service_data_cmp);
+ if (!list)
+ return NULL;
+ else
+ return list->data;
+
+ return NULL;
+}
+
+static gboolean adapter_le_service_delete_service_scan_filter_data(struct btd_adapter *adapter,
+ int filter_index, uint8_t *p_data, uint8_t *p_mask, int data_len)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->service_data_filters, GINT_TO_POINTER(filter_index), adapter_le_service_data_filter_index_cmp);
+ if (!list)
+ return FALSE;
+ else {
+ adapter_le_service_data_params_t *params = list->data;
+ /* Delete info from the struct to list */
+ if (params && strcasecmp((const char *)params->service_data, (const char *)p_data)) {
+ adapter->service_data_filters = g_slist_delete_link(adapter->service_data_filters, list);
+ }
+ }
+ return TRUE;
+}
+
+static gboolean adapter_le_service_clear_service_scan_filter_data(struct btd_adapter *adapter)
+{
+ DBG("");
+
+ g_slist_free_full(adapter->service_data_filters, service_data_filter_params_free);
+ adapter->service_data_filters = NULL;
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_add_scan_filter_params(struct btd_adapter *adapter,
+ adapter_le_scan_filter_param_t *params)
+{
+ adapter_le_scan_filter_param_t *l_params;
+
+ DBG("");
+
+ l_params = g_new0(adapter_le_scan_filter_param_t, 1);
+ if (!l_params)
+ return FALSE;
+
+ l_params->action = params->action;
+ l_params->delivery_mode = params->delivery_mode;
+ l_params->feature = params->feature;
+ l_params->filter_logic_type = params->filter_logic_type;
+ l_params->index = params->index;
+ l_params->list_logic_type = params->list_logic_type;
+ l_params->onfound_timeout = params->onfound_timeout;
+ l_params->onfound_timeout_cnt = params->onfound_timeout_cnt;
+ l_params->rssi_high_threshold = params->rssi_high_threshold;
+ l_params->rssi_low_threshold = params->rssi_low_threshold;
+
+ /* Store the struct to list */
+ adapter->scan_params = g_slist_append(adapter->scan_params, l_params);
+
+ return TRUE;
+}
+
+static adapter_le_service_data_params_t *adapter_le_service_find_scan_filter_params(
+ struct btd_adapter *adapter, int filter_index)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->scan_params, GINT_TO_POINTER(filter_index), adapter_le_scan_params_filter_index_cmp);
+ if (!list)
+ return NULL;
+ else
+ return list->data;
+
+ return NULL;
+}
+
+static gboolean adapter_le_service_delete_scan_filter_params(struct btd_adapter *adapter,
+ adapter_le_scan_filter_param_t *params)
+{
+ GSList *list;
+ DBG("");
+
+ list = g_slist_find_custom(adapter->scan_params, GINT_TO_POINTER(params->index), adapter_le_scan_params_filter_index_cmp);
+ if (!list)
+ return FALSE;
+ else
+ adapter->scan_params = g_slist_remove(adapter->scan_params, list);
+
+ return TRUE;
+}
+
+static gboolean adapter_le_service_clear_scan_filter_params(struct btd_adapter *adapter)
+{
+ DBG("");
+
+ g_slist_free_full(adapter->scan_params, scan_filter_params_free);
+ adapter->scan_params = NULL;
+
+ return TRUE;
+}
+
+int adapter_byte_arr_cmp_with_mask(const char *data1, const char *data2,
+ const char *mask, int data_len)
+{
+ int i;
+ char a, b;
+ if (data1 == NULL || data2 == NULL || mask == NULL)
+ return -1;
+ for (i = 0; i < data_len; i++) {
+ a = data1[i] & mask[i];
+ b = data2[i] & mask[i];
+ if (a != b)
+ return (int)(a - b);
+ }
+ return 0;
+}
+
+static gboolean validate_for_filter_policy(struct btd_adapter *adapter, const struct eir_data *eir, gchar *addr)
+{
+ gboolean is_allowed = FALSE;
+ DBG("");
+
+ if (adapter->scan_filter_support == FALSE)
+ is_allowed = TRUE;
+ else {
+ if (adapter_le_service_find_addr_scan_filter_data(adapter, addr))
+ is_allowed = TRUE;
+ if (eir->name) {
+ if(adapter_le_service_find_local_name_scan_filter_data(adapter, eir->name))
+ is_allowed = TRUE;
+ }
+ if (eir->sd_list) {
+ GSList *list = NULL;
+ for (list = eir->sd_list; list != NULL; list = g_slist_next(list)) {
+ struct eir_sd *sd = list->data;
+ if (sd != NULL) {
+ static adapter_le_uuid_params_t *uuid_data = NULL;
+ static adapter_le_service_data_params_t *service_data = NULL;
+ static adapter_le_scan_filter_param_t *scan_param_data = NULL;
+ uuid_data = adapter_le_service_find_uuid_scan_filter_data(adapter, (uint8_t *)sd->uuid);
+ service_data = adapter_le_service_find_service_scan_filter_data(adapter, sd);
+ if (service_data != NULL) {
+ if (!adapter_byte_arr_cmp_with_mask((const char *)service_data->service_data,
+ (const char *)sd->data, (const char *)service_data->service_data_mask,
+ service_data->service_data_len)) {
+ scan_param_data = adapter_le_service_find_scan_filter_params(adapter,
+ service_data->filter_index);
+ if (scan_param_data && scan_param_data->rssi_high_threshold > eir->tx_power &&
+ scan_param_data->rssi_low_threshold < eir->tx_power)
+ is_allowed = TRUE;
+ }
+ }
+ if (uuid_data != NULL) {
+ if (!adapter_byte_arr_cmp_with_mask((const char *)uuid_data->uuid,
+ (const char *)sd->uuid, (const char *)uuid_data->uuid_mask,
+ uuid_data->uuid_len)) {
+ scan_param_data = adapter_le_service_find_scan_filter_params(adapter,
+ uuid_data->filter_index);
+ if (scan_param_data && scan_param_data->rssi_high_threshold > eir->tx_power &&
+ scan_param_data->rssi_low_threshold < eir->tx_power)
+ is_allowed = TRUE;
+ }
+ }
+ if (is_allowed)
+ break;
+ }
+ }
+ }
+ if (eir->msd_list) {
+ GSList *list = NULL;
+ for (list = eir->msd_list; list != NULL; list = g_slist_next(list)) {
+ struct eir_msd *msd = list->data;
+ if (msd != NULL) {
+ static adapter_le_manf_data_params_t *manuf_data;
+ static adapter_le_scan_filter_param_t *scan_param_data = NULL;
+ manuf_data = adapter_le_service_find_manufacturer_scan_filter_data(adapter,
+ msd);
+ if (manuf_data != NULL) {
+ if (!adapter_byte_arr_cmp_with_mask((const char *)msd->data,
+ (const char *)manuf_data->man_data, (const char *)manuf_data->man_data_mask,
+ manuf_data->man_data_len)) {
+ scan_param_data = adapter_le_service_find_scan_filter_params(adapter,
+ manuf_data->filter_index);
+ if (scan_param_data && scan_param_data->rssi_high_threshold > eir->tx_power &&
+ scan_param_data->rssi_low_threshold < eir->tx_power)
+ is_allowed = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ return is_allowed;
+}
+
+gboolean adapter_le_set_platform_scan_filter_params(struct btd_adapter *adapter,
+ adapter_le_scan_filter_param_t *params)
+{
+ gboolean ret = TRUE;
+ DBG("adapter_le_scan_filter_param_t [%d]", params->index);
+ adapter_le_scan_filter_action_type action_type = params->action;
+
+ if (action_type == ADD) {
+ ret = adapter_le_service_add_scan_filter_params(adapter, params);
+ } else if (action_type == DELETE) {
+ ret = adapter_le_service_delete_scan_filter_params(adapter, params);
+ } else if (action_type == CLEAR) {
+ ret = adapter_le_service_clear_scan_filter_params(adapter);
+ } else {
+ DBG("filter_action error");
+ ret = FALSE;
+ }
+
+ DBG("Scan Filter VSC :: Action [%x]",
+ params->action);
+ return ret;
+}
+
+gboolean adapter_le_set_platform_scan_filter_data(struct btd_adapter *adapter,
+ int client_if, int action,
+ int filt_type, int filter_index,
+ int company_id,
+ int company_id_mask,
+ int uuid_len, uint8_t *p_uuid,
+ int uuid_mask_len, uint8_t *p_uuid_mask,
+ gchar *string, int addr_type,
+ int data_len, uint8_t *p_data,
+ int mask_len, uint8_t *p_mask)
+{
+ gboolean ret = TRUE;
+
+ DBG("");
+
+ switch (filt_type) {
+ case TYPE_DEVICE_ADDRESS: {
+ /* TYPE_DEVICE_ADDRESS */
+ adapter_le_scan_filter_action_type action_type = action;
+
+ if (action_type == ADD) {
+ ret = adapter_le_service_add_addr_scan_filter_data(adapter,
+ filter_index, string, addr_type);
+ } else if (action_type == DELETE) {
+ ret = adapter_le_service_delete_addr_scan_filter_data(adapter,
+ filter_index, string, addr_type);
+ } else if (action_type == CLEAR) {
+ ret = adapter_le_service_clear_addr_scan_filter_data(adapter);
+ } else {
+ DBG("filter_action error");
+ ret = FALSE;
+ }
+
+ break;
+ }
+
+ case TYPE_SERVICE_UUID:
+ case TYPE_SOLICIT_UUID: {
+ adapter_le_scan_filter_action_type action_type = action;
+
+ gboolean is_solicited = (filt_type == TYPE_SOLICIT_UUID) ? TRUE : FALSE;
+
+ if (uuid_len != UUID_16_LEN && uuid_len != UUID_32_LEN
+ && uuid_len != UUID_128_LEN) {
+ DBG("UUID length error");
+ return FALSE;
+ }
+
+ if (uuid_len != uuid_mask_len) {
+ DBG("Both UUID and UUID_MASK length shoule be samed");
+ return FALSE;
+ }
+
+ if (action_type == ADD) {
+ ret = adapter_le_service_add_uuid_scan_filter_data(adapter,
+ filter_index, is_solicited, p_uuid,
+ p_uuid_mask, uuid_len);
+ } else if (action_type == DELETE) {
+ ret = adapter_le_service_delete_uuid_scan_filter_data(adapter,
+ filter_index, is_solicited, p_uuid,
+ p_uuid_mask, uuid_len);
+ } else if (action_type == CLEAR) {
+ ret = adapter_le_service_clear_uuid_scan_filter_data(adapter);
+ } else {
+ DBG("filter_action error");
+ ret = FALSE;
+ }
+
+ break;
+ }
+
+ case TYPE_LOCAL_NAME: {
+ adapter_le_scan_filter_action_type action_type = action;
+
+ if (action_type == ADD) {
+ ret = adapter_le_service_add_local_name_scan_filter_data(adapter,
+ filter_index, (gchar*)string);
+ } else if (action_type == DELETE) {
+ ret = adapter_le_service_delete_local_name_scan_filter_data(adapter,
+ filter_index, (gchar*)string);
+ } else if (action_type == CLEAR) {
+ ret = adapter_le_service_clear_local_name_scan_filter_data(adapter);
+ } else {
+ DBG("filter_action error");
+ ret = FALSE;
+ }
+
+ break;
+ }
+
+ case TYPE_MANUFACTURER_DATA: {
+ adapter_le_scan_filter_action_type action_type = action;
+
+ if (data_len == 0 || (data_len != mask_len)) {
+ DBG("parameter length error");
+ return FALSE;
+ }
+
+ if (action_type == ADD) {
+ ret = adapter_le_service_add_manufacturer_scan_filter_data(adapter,
+ filter_index,company_id, company_id_mask, p_data, p_mask, data_len);
+ } else if (action_type == DELETE) {
+ ret = adapter_le_service_delete_manufacturer_scan_filter_data(adapter,
+ filter_index, company_id, company_id_mask, p_data, p_mask, data_len);
+ } else if (action_type == CLEAR) {
+ ret = adapter_le_service_clear_manufacturer_scan_filter_data(adapter);
+ } else {
+ DBG("filter_action error");
+ ret = FALSE;
+ }
+
+ break;
+ }
+
+ case TYPE_SERVICE_DATA: {
+ adapter_le_scan_filter_action_type action_type = action;
+
+ if (data_len == 0 || (data_len != mask_len)) {
+ DBG("parameter length error");
+ return FALSE;
+ }
+
+ if (action_type == ADD) {
+ ret = adapter_le_service_add_service_scan_filter_data(adapter,
+ filter_index, p_data, p_mask, data_len);
+ } else if (action_type == DELETE) {
+ ret = adapter_le_service_delete_service_scan_filter_data(adapter,
+ filter_index, p_data, p_mask, data_len);
+ } else if (action_type == CLEAR) {
+ ret = adapter_le_service_clear_service_scan_filter_data(adapter);
+ } else {
+ DBG("filter_action error");
+ ret = FALSE;
+ }
+
+ break;
+ }
+
+ default:
+ DBG("filter_type error");
+ ret = FALSE;
+ }
+
+ return ret;
+}
+#endif
static int set_adv_data_flag(uint8_t *adv_data, uint8_t *data, int data_len)
{
DBusMessage *msg, void *data)
{
struct btd_adapter *adapter = data;
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ dbus_bool_t ctlr_filter_support = TRUE;
+#endif
dbus_int32_t client_if, action, filt_index;
dbus_int32_t feat_seln, list_logic_type, filt_logic_type;
dbus_int32_t rssi_high_thres, rssi_low_thres, dely_mode;
return btd_error_not_ready(msg);
if (adapter_le_get_scan_filter_size() == 0)
+#ifndef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
return btd_error_not_supported(msg);
+#else
+ ctlr_filter_support = FALSE;
+#endif
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &client_if,
DBUS_TYPE_INT32, &action,
params.onlost_timeout = lost_timeout;
}
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ if (ctlr_filter_support)
+#endif
err = adapter_le_set_scan_filter_params(¶ms);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ else
+ err = adapter_le_set_platform_scan_filter_params(adapter, ¶ms);
+#endif
if (!err)
return btd_error_failed(msg, "Failed to scan filter param setup");
uint8_t *p_uuid, *p_uuid_mask, *p_data, *p_mask;
int32_t uuid_len = 0, uuid_mask_len = 0, data_len = 0, mask_len = 0;
gboolean err;
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ dbus_bool_t ctlr_filter_support = TRUE;
+#endif
DBG("adapter_le_scan_filter_add_remove");
if (!(adapter->current_settings & MGMT_SETTING_POWERED))
return btd_error_not_ready(msg);
- if (adapter_le_get_scan_filter_size() == 0)
+ /* if controller does not support vendor specific scan filtering feature
+ * then add the filter into platform supported scan filters.
+ */
+ if (adapter_le_get_scan_filter_size() == 0) {
+#ifndef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
return btd_error_not_supported(msg);
+#else
+ ctlr_filter_support = FALSE;
+#endif
+ }
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &client_if,
DBUS_TYPE_INT32, &action,
DBG("addr %s, type %d", ida_string, addr_type);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ if (ctlr_filter_support)
+#endif
err = adapter_le_set_scan_filter_data(client_if, action, filt_type,
filt_index, company_id, company_id_mask,
uuid_len, p_uuid, uuid_mask_len, p_uuid_mask,
ida_string, addr_type, data_len, p_data, mask_len, p_mask);
-
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ else
+ err = adapter_le_set_platform_scan_filter_data(adapter, client_if, action, filt_type,
+ filt_index, company_id, company_id_mask,
+ uuid_len, p_uuid, uuid_mask_len, p_uuid_mask,
+ ida_string, addr_type, data_len, p_data, mask_len, p_mask);
+#endif
if (!err)
return btd_error_failed(msg, "Failed to add/remove filter");
dbus_int32_t client_if = 0;
dbus_int32_t filt_index = 0;
gboolean err;
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ dbus_bool_t ctlr_filter_support = TRUE;
+#endif
DBG("adapter_le_scan_filter_clear");
return btd_error_not_ready(msg);
if (adapter_le_get_scan_filter_size() == 0)
+#ifndef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
return btd_error_not_supported(msg);
+#else
+ ctlr_filter_support = FALSE;
+#endif
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &client_if,
DBUS_TYPE_INT32, &filt_index,
DBUS_TYPE_INVALID))
return btd_error_invalid_args(msg);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ if (ctlr_filter_support)
+#endif
err = adapter_le_clear_scan_filter_data(client_if, filt_index);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ else
+ err = adapter_le_clear_platform_scan_filter_data(adapter, filt_index);
+#endif
if (!err)
return btd_error_failed(msg, "Failed to clear filter");
dbus_bool_t enable = FALSE;
dbus_int32_t client_if = 0;
gboolean err;
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ dbus_bool_t ctlr_filter_support = TRUE;
+#endif
DBG("adapter_le_scan_filter_enable");
if (!(adapter->current_settings & MGMT_SETTING_POWERED))
return btd_error_not_ready(msg);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ /* if controller does not support vendor specific scan filtering feature
+ * then enable platform supported scan filtering functionalites.
+ */
+#endif
if (adapter_le_get_scan_filter_size() == 0)
+#ifndef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
return btd_error_not_supported(msg);
+#else
+ ctlr_filter_support = FALSE;
+#endif
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &client_if,
DBUS_TYPE_BOOLEAN, &enable,
DBUS_TYPE_INVALID))
return btd_error_invalid_args(msg);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ if (ctlr_filter_support)
+#endif
err = adapter_le_enable_scan_filtering(enable);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ else
+ err = adapter_le_enable_platform_scan_filtering(adapter, enable);
+#endif
if (!err)
return btd_error_failed(msg, "Failed to enable scan filtering");
cp.type = type;
cp.interval = interval;
cp.window = window;
+ adapter->scan_type = type;
if (mgmt_send(adapter->mgmt, MGMT_OP_LE_SET_SCAN_PARAMS,
adapter->dev_id, sizeof(cp), &cp,
}
value = adapter_le_get_scan_filter_size();
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ if (value <= 0)
+ value = SCAN_FILTER_SLOTS_MAX;
+#endif
if (value > 0) {
str = g_strdup("max_filter");
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &str);
if (adapter_le_read_ble_feature_info())
g_dbus_emit_property_changed(dbus_conn, adapter->path,
ADAPTER_INTERFACE, "SupportedLEFeatures");
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ else
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
+ ADAPTER_INTERFACE, "SupportedLEFeatures");
+#endif
adapter_get_adv_tx_power(adapter);
struct btd_device *dev;
struct eir_data eir_data;
bool name_known, discoverable;
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ bool is_allowed;
+#endif
char addr[18];
memset(&eir_data, 0, sizeof(eir_data));
ba2str(bdaddr, addr);
+#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
+ /* Check if the any filter policy */
+ is_allowed = validate_for_filter_policy(adapter, &eir_data, addr);
+ if (!is_allowed && ((adapter->scan_type == 1 && adv_type == 04) ||
+ adapter->scan_type == 0)) {
+ eir_data_free(&eir_data);
+ return;
+ }
+#endif
dev = btd_adapter_find_device(adapter, bdaddr, bdaddr_type);
if (!dev) {
/*