X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service-adaptation%2Fservices%2Fadapter%2Fbt-service-core-adapter-le.c;h=5f146f3a33d0110c9df86d9a22b24255e17ddeca;hb=d3f64e9c21a3743c3b8fb36e4524a030945e3333;hp=cd62f3f03486777ec978de1d0927bccd3755b0ee;hpb=6a5859823abb699c6ad1c3c87d4ace655648fc98;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c b/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c index cd62f3f..5f146f3 100644 --- a/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c +++ b/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c @@ -33,6 +33,7 @@ #include "bt-service-gatt.h" #include "bt-service-util.h" #include "bt-service-core-device.h" +#include "bt-service-battery-monitor.h" #include #include @@ -90,14 +91,16 @@ static bt_le_discovery_state_t adapter_le_discovery_state = LE_DISCOVERY_STOPPED typedef struct { char *sender; + uid_t uid; + pid_t pid; GSList *filter_list; gboolean is_scanning; - gboolean stop_pending; } bt_adapter_le_scanner_t; GSList *scanner_list = NULL; static gboolean is_le_set_scan_parameter = FALSE; static gboolean is_le_scanning = FALSE; +static gboolean scan_filter_enabled = FALSE; static bluetooth_le_scan_params_t le_scan_params = { BT_LE_ACTIVE_SCAN, 0, 0 }; @@ -106,6 +109,25 @@ static void _bt_disable_all_scanner_status(void); /******************************************* LE Scan *********************************************/ +static void __bt_free_le_scanner(bt_adapter_le_scanner_t *scanner) +{ + g_free(scanner->sender); + g_slist_free_full(scanner->filter_list, g_free); + g_free(scanner); +} + +static void __bt_free_le_scanner_all(void) +{ + g_slist_free_full(scanner_list, (GDestroyNotify)__bt_free_le_scanner); + scanner_list = NULL; + + is_le_scanning = FALSE; + is_le_set_scan_parameter = FALSE; + le_scan_params.type = BT_LE_ACTIVE_SCAN; + le_scan_params.interval = 0; + le_scan_params.window = 0; +} + void _bt_adapter_set_le_status(bt_le_status_t status) { BT_INFO("adapter_le_state changed [%d] -> [%d]", adapter_le_state, status); @@ -220,9 +242,9 @@ static void __bt_le_update_bt_disabled(void) g_variant_new("(i)", result)); } - static void __bt_set_le_scan_status(gboolean mode) { + BT_DBG("Set scanning status: %s", mode == TRUE ? "TRUE" : "FALSE"); is_le_scanning = mode; } @@ -252,7 +274,6 @@ static void __bt_adapter_le_handle_pending_request_info(int result, GSList *l; GArray *out_param; invocation_info_t *req_info = NULL; - BT_DBG("+"); for (l = _bt_get_invocation_list(); l != NULL; ) { req_info = l->data; @@ -268,7 +289,6 @@ static void __bt_adapter_le_handle_pending_request_info(int result, int *saved_handle; bt_pending_adv_data_set_t *data; - BT_DBG("Service function: [%d]", service_function); ret_if(param == NULL); saved_handle = (int*)req_info->user_data; @@ -313,10 +333,10 @@ static void __bt_adapter_le_handle_pending_request_info(int result, break; } default: + BT_DBG("Unknown function(%d)", service_function); break; } } - BT_DBG("-"); } static void __bt_le_handle_server_instance_registered(event_gatts_register_t *data) @@ -430,6 +450,8 @@ static void __bt_le_multi_advertising_enabled(event_ble_multiadv_status *event) /* Free data */ g_free(info->sender); g_free(info); + + BT_PERMANENT_LOG("Adv started %d", event->server_inst); } } @@ -466,6 +488,8 @@ static void __bt_le_multi_advertising_disabled(event_ble_multiadv_status *event) /* Free data */ g_free(info->sender); g_free(info); + + BT_PERMANENT_LOG("Adv stopped %d", event->server_inst); } } @@ -480,14 +504,13 @@ static void __bt_le_multi_advertising_set_data(event_ble_multiadv_status *event) if (sender == NULL) { BT_ERR("Abnormal!!"); } else { - BT_DBG("Sender [%s], adv handle [%d]", sender, adv_handle); + BT_INFO("Sender [%s], adv handle [%d]", sender, adv_handle); if (event->status != OAL_STATUS_SUCCESS) result = BLUETOOTH_ERROR_INTERNAL; info = g_malloc0(sizeof(bt_pending_adv_data_set_t)); info->sender = sender; info->adv_handle = adv_handle; - BT_DBG("Sender [%s], adv handle [%d]", info->sender, info->adv_handle); __bt_adapter_le_handle_pending_request_info(result, BT_SET_SCAN_RESPONSE_DATA, (void*)info, sizeof(bt_pending_adv_data_set_t)); @@ -499,25 +522,362 @@ static void __bt_le_multi_advertising_set_data(event_ble_multiadv_status *event) } } -static int __get_advertisement_data(unsigned char *dest, unsigned char *src) +static int __bt_get_ad_data_by_type(const char *in_data, int in_len, + char in_type, char **data, int *data_len) { - int length = 0; - int i = 0; + if (in_data == NULL || data == NULL || data_len == NULL) + return BLUETOOTH_ERROR_INTERNAL; - while (i <= 31) { - int len = src[i]; + if (in_len <= 0) + return BLUETOOTH_ERROR_INTERNAL; + + int i; + unsigned char len = 0; + int type = 0; + + for (i = 0; i < in_len && i < BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1; i++) { + len = in_data[i]; + if (len <= 0 || i + 1 >= in_len) { + BT_ERR("Invalid advertising data"); + return BLUETOOTH_ERROR_INTERNAL; + } - if ((len == 0) || (31 < (i + len))) { - BT_INFO("length: %d", length); - memcpy(dest, src, length); + type = in_data[i + 1]; + if (type == in_type) { + i = i + 2; + len--; break; } - length += (len + 1); - i += (len + 1); + i += len; + len = 0; + } + + if (i > BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1 + || i + len > in_len + || i + len > BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX) { + BT_ERR("Invalid advertising data"); + return BLUETOOTH_ERROR_INTERNAL; + } else if (len == 0) { + BT_DBG("AD Type 0x%02x data is not set", in_type); + *data = NULL; + *data_len = 0; + return BLUETOOTH_ERROR_NONE; + } + + *data = g_memdup(&in_data[i], len); + if (*data == NULL) + return BLUETOOTH_ERROR_OUT_OF_MEMORY; + *data_len = len; + + return BLUETOOTH_ERROR_NONE; +} + +static gboolean __bt_check_scan_result_uuid(const char *adv_data, + int adv_data_len, const char *svc_uuid, int uuid_len, + const char *uuid_mask, char ad_type) +{ + char *data = NULL; + int data_len = 0; + int i; + + __bt_get_ad_data_by_type(adv_data, adv_data_len, + ad_type, &data, &data_len); + if (data != NULL) { + for (i = 0; i < data_len; i += uuid_len) { + if (uuid_len > (data_len - i)) + break; + + if (_bt_byte_arr_cmp_with_mask(data + i, + svc_uuid, uuid_mask, uuid_len) == 0) { + g_free(data); + return TRUE; + } + } + g_free(data); + } + + return FALSE; +} + +static gboolean __bt_check_scan_result_with_filter(const char *device_address, + const char *adv_data, int adv_data_len, + const char *scan_data, int scan_data_len, + const bt_adapter_le_scanner_t *scanner) +{ + GSList *l; + bluetooth_le_scan_filter_t *filter_data = NULL; + char *data = NULL; + int data_len = 0; + gboolean is_matched = FALSE; + int idx; + + if (scanner->filter_list == NULL) { + BT_DBG("This scanner is on Full Scan."); + return TRUE; + } + + for (l = scanner->filter_list; l != NULL; l = g_slist_next(l)) { + filter_data = l->data; + + if (filter_data->added_features & + BLUETOOTH_LE_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) { + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + _bt_convert_addr_type_to_string(address, + filter_data->device_address.addr); + if (strncmp(address, device_address, + BT_ADDRESS_STRING_SIZE) != 0) + continue; + } + + /* Check service uuid filter */ + if (filter_data->added_features & + BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_UUID) { + is_matched = FALSE; + const int ad_type_uuids[] = { + BT_LE_AD_TYPE_INCOMP_LIST_16_BIT_SERVICE_CLASS_UUIDS, + BT_LE_AD_TYPE_COMP_LIST_16_BIT_SERVICE_CLASS_UUIDS, + BT_LE_AD_TYPE_INCOMP_LIST_128_BIT_SERVICE_CLASS_UUIDS, + BT_LE_AD_TYPE_COMP_LIST_128_BIT_SERVICE_CLASS_UUIDS + }; + + for (idx = 0; idx < sizeof(ad_type_uuids) / sizeof(bt_le_ad_type_t); idx++) { + /* Check service uuid in advertising data */ + if (__bt_check_scan_result_uuid(adv_data, adv_data_len, + (const char *)filter_data->service_uuid.data.data, + filter_data->service_uuid.data_len, + (const char *)filter_data->service_uuid_mask.data.data, + ad_type_uuids[idx]) == TRUE) { + BT_INFO("Service UUID is matched in adv data."); + is_matched = TRUE; + break; + } + + /* Check service uuid in scan response data */ + if (__bt_check_scan_result_uuid(scan_data, scan_data_len, + (const char *)filter_data->service_uuid.data.data, + filter_data->service_uuid.data_len, + (const char *)filter_data->service_uuid_mask.data.data, + ad_type_uuids[idx]) == TRUE) { + BT_INFO("Service UUID is matched in scan data."); + is_matched = TRUE; + break; + } + } + + /* Service UUID is NOT matched. Continue to next filter */ + if (is_matched == FALSE) + continue; + } + + /* Check solicitation uuid filter */ + if (filter_data->added_features & + BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) { + is_matched = FALSE; + const int ad_type_solicit_uuids[] = { + BT_LE_AD_TYPE_LIST_16_BIT_SERVICE_SOLICITATION_UUIDS, + BT_LE_AD_TYPE_LIST_128_BIT_SERVICE_SOLICITATION_UUIDS + }; + + for (idx = 0; idx < sizeof(ad_type_solicit_uuids) / sizeof(bt_le_ad_type_t); idx++) { + /* Check solicit uuid in advertising data */ + if (__bt_check_scan_result_uuid(adv_data, adv_data_len, + (const char *)filter_data->service_solicitation_uuid.data.data, + filter_data->service_solicitation_uuid.data_len, + (const char *)filter_data->service_solicitation_uuid_mask.data.data, + ad_type_solicit_uuids[idx]) == TRUE) { + BT_INFO("Service Solicitation UUID is matched in adv data."); + is_matched = TRUE; + break; + } + + /* Check solicit uuid in scan response data */ + if (__bt_check_scan_result_uuid(scan_data, scan_data_len, + (const char *)filter_data->service_solicitation_uuid.data.data, + filter_data->service_solicitation_uuid.data_len, + (const char *)filter_data->service_solicitation_uuid_mask.data.data, + ad_type_solicit_uuids[idx]) == TRUE) { + BT_INFO("Service Solicitation UUID is matched in scan data."); + is_matched = TRUE; + break; + } + } + + /* Service Solicitation UUID is NOT matched. Continue to next filter */ + if (is_matched == FALSE) + continue; + } + + /* Check device name filter */ + if (filter_data->added_features & + BLUETOOTH_LE_SCAN_FILTER_FEATURE_DEVICE_NAME) { + char name[BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX] = {0, }; + data = NULL; + data_len = 0; + is_matched = FALSE; + + /* Check device name in advertising data */ + __bt_get_ad_data_by_type(adv_data, adv_data_len, + BT_LE_AD_TYPE_COMPLETE_LOCAL_NAME, + &data, &data_len); + if (data != NULL) { + if (data_len >= BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX) + data_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1; + memcpy(name, data, data_len); + name[data_len] = '\0'; + g_free(data); + data = NULL; + if (g_strrstr(name, filter_data->device_name) != NULL) { + BT_INFO("Device Name is matched in adv data."); + is_matched = TRUE; + } + } + + /* Check device name in scan response data */ + __bt_get_ad_data_by_type(scan_data, scan_data_len, + BT_LE_AD_TYPE_COMPLETE_LOCAL_NAME, + &data, &data_len); + if (data != NULL) { + if (data_len >= BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX) + data_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1; + memcpy(name, data, data_len); + name[data_len] = '\0'; + g_free(data); + data = NULL; + if (g_strrstr(name, filter_data->device_name) != NULL) { + BT_INFO("Device Name is matched in scan data."); + is_matched = TRUE; + } + } + + /* Device Name is NOT matched. Continue to next filter */ + if (is_matched == FALSE) + continue; + } + + /* Check manufacturer data filter */ + if (filter_data->added_features & + BLUETOOTH_LE_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) { + data = NULL; + data_len = 0; + is_matched = FALSE; + + /* Check manufacturer data in advertising data */ + __bt_get_ad_data_by_type(adv_data, adv_data_len, + BT_LE_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, + &data, &data_len); + if (data != NULL) { + int manufacturer_id; + manufacturer_id = (data[1] << 8) + data[0]; + + if (filter_data->manufacturer_id == manufacturer_id) { + if (filter_data->manufacturer_data.data_len == 0) { + is_matched = TRUE; + } else { + if (data_len >= BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX) + data_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1; + if (_bt_byte_arr_cmp_with_mask(data + 2, + (const char *)filter_data->manufacturer_data.data.data, + (const char *)filter_data->manufacturer_data_mask.data.data, + data_len - 2) == 0) { + BT_INFO("Manufacturer Data is matched in adv data."); + is_matched = TRUE; + } + } + } + g_free(data); + data = NULL; + } + + /* Check manufacturer data in scan response data */ + __bt_get_ad_data_by_type(scan_data, scan_data_len, + BT_LE_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, + &data, &data_len); + if (data != NULL) { + int manufacturer_id; + manufacturer_id = (data[1] << 8) + data[0]; + + if (filter_data->manufacturer_id == manufacturer_id) { + if (filter_data->manufacturer_data.data_len == 0) { + is_matched = TRUE; + } else { + if (data_len >= BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX) + data_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1; + if (_bt_byte_arr_cmp_with_mask(data + 2, + (const char *)filter_data->manufacturer_data.data.data, + (const char *)filter_data->manufacturer_data_mask.data.data, + data_len - 2) == 0) { + BT_INFO("Manufacturer Data is matched in scan data."); + is_matched = TRUE; + } + } + } + g_free(data); + data = NULL; + } + + /* Manufacturer Data is NOT matched. Continue to next filter */ + if (is_matched == FALSE) + continue; + } + + /* Check service data filter */ + if (filter_data->added_features & + BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_DATA) { + data = NULL; + data_len = 0; + is_matched = FALSE; + + /* Check service data in advertising data */ + __bt_get_ad_data_by_type(adv_data, + adv_data_len, + BT_LE_AD_TYPE_SERVICE_DATA, + &data, &data_len); + if (data != NULL) { + if (data_len >= BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX) + data_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1; + if (_bt_byte_arr_cmp_with_mask(data, + (const char *)filter_data->service_data.data.data, + (const char *)filter_data->service_data_mask.data.data, + data_len) == 0) { + BT_INFO("Service Data is matched in adv data."); + is_matched = TRUE; + } + g_free(data); + data = NULL; + } + + /* Check service data in scan response data */ + __bt_get_ad_data_by_type(scan_data, + scan_data_len, + BT_LE_AD_TYPE_SERVICE_DATA, + &data, &data_len); + if (data != NULL) { + if (data_len >= BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX) + data_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 1; + if (_bt_byte_arr_cmp_with_mask(data, + (const char *)filter_data->service_data.data.data, + (const char *)filter_data->service_data_mask.data.data, + data_len) == 0) { + BT_INFO("Service Data is matched in scan data."); + is_matched = TRUE; + } + g_free(data); + data = NULL; + } + + /* Service Data is NOT matched. Continue to next filter */ + if (is_matched == FALSE) + continue; + } + + BT_INFO("The scan result is conformable."); + return TRUE; } - return length; + BT_INFO("The scan result is NOT conformable."); + return FALSE; } static void __bt_le_handle_device_found(event_ble_scan_result_info *scan_result) @@ -525,53 +885,39 @@ static void __bt_le_handle_device_found(event_ble_scan_result_info *scan_result) int result = BLUETOOTH_ERROR_NONE; bt_adapter_le_scanner_t *scanner = NULL; char address[BT_ADDRESS_STRING_SIZE]; - int addr_type = 0x01; /* TODO: Need to get correct address type */ - unsigned char adv_ind_data[31]; - unsigned char scan_resp_data[31]; + unsigned char adv_ind_data[BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX]; + unsigned char scan_resp_data[BLUETOOTH_SCAN_RESP_DATA_LENGTH_MAX]; int adv_ind_len = 0; int scan_resp_len = 0; - char *tmp_str = NULL; GVariant *scan_data_param; GVariant *adv_data_param; GVariant *param; GSList *l; - BT_DBG("+"); ret_if(NULL == scan_result); _bt_convert_addr_type_to_string(address, scan_result->address.addr); memset(adv_ind_data, 0x00, sizeof(adv_ind_data)); - adv_ind_len = __get_advertisement_data( - adv_ind_data, &(scan_result->adv_data[0])); + adv_ind_len = scan_result->adv_data_len; + memcpy(adv_ind_data, scan_result->adv_data, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX); memset(scan_resp_data, 0x00, sizeof(scan_resp_data)); - scan_resp_len = __get_advertisement_data( - scan_resp_data, &(scan_result->adv_data[adv_ind_len])); + scan_resp_len = scan_result->scan_rsp_data_len; + memcpy(scan_resp_data, scan_result->scan_rsp_data, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX); - BT_INFO("Address: %s, RSSI: %d, adv_ind_len: %d, scan_resp_len: %d", + BT_DBG("Address: %s, RSSI: %d, adv_ind_len: %d, scan_resp_len: %d", address, scan_result->rssi, adv_ind_len, scan_resp_len); - tmp_str = _bt_service_convert_hex_to_string(scan_result->adv_data, 62); - BT_INFO("Complete Data: [%s]", tmp_str); - g_free(tmp_str); - tmp_str = NULL; - - tmp_str = _bt_service_convert_hex_to_string(adv_ind_data, adv_ind_len); - BT_INFO("Adv Ind Data: [%s]", tmp_str); - g_free(tmp_str); - tmp_str = NULL; - - tmp_str = _bt_service_convert_hex_to_string(scan_resp_data, scan_resp_len); - BT_INFO("Scan resp Data: [%s]", tmp_str); - g_free(tmp_str); - tmp_str = NULL; - for (l = scanner_list; l != NULL; l = g_slist_next(l)) { scanner = l->data; if (scanner->is_scanning == FALSE) continue; + if (__bt_check_scan_result_with_filter(address, (const char *)adv_ind_data, + adv_ind_len, (const char *)scan_resp_data, scan_resp_len, scanner) == FALSE) + continue; + adv_data_param = g_variant_new_from_data((const GVariantType *)"ay", adv_ind_data, adv_ind_len, TRUE, NULL, NULL); scan_data_param = g_variant_new_from_data((const GVariantType *)"ay", @@ -579,15 +925,13 @@ static void __bt_le_handle_device_found(event_ble_scan_result_info *scan_result) param = g_variant_new("(isnnn@ayn@ay)", result, address, - addr_type, scan_result->rssi, + scan_result->addr_type, scan_result->rssi, adv_ind_len, adv_data_param, scan_resp_len, scan_data_param); _bt_send_event_to_dest(scanner->sender, BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, param); } - - BT_DBG("-"); } static void __bt_le_state_change_callback(int bt_status) @@ -621,7 +965,7 @@ static void __bt_le_state_change_callback(int bt_status) static void __bt_le_event_handler(int event_type, gpointer event_data) { - BT_INFO("OAL event = 0x%x, \n", event_type); + BT_INFO("OAL event = %d", event_type); switch (event_type) { case OAL_EVENT_BLE_ENABLED: { @@ -666,7 +1010,6 @@ static void __bt_le_event_handler(int event_type, gpointer event_data) } case OAL_EVENT_BLE_DISCOVERY_STARTED: { __bt_set_le_scan_status(TRUE); - __bt_adapter_le_handle_pending_request_info( BLUETOOTH_ERROR_NONE, BT_START_LE_DISCOVERY, NULL, 0); @@ -682,6 +1025,7 @@ static void __bt_le_event_handler(int event_type, gpointer event_data) } __bt_set_le_scan_status(FALSE); + _bt_disable_all_scanner_status(); __bt_adapter_le_handle_pending_request_info( BLUETOOTH_ERROR_NONE, BT_STOP_LE_DISCOVERY, NULL, 0); @@ -689,7 +1033,6 @@ static void __bt_le_event_handler(int event_type, gpointer event_data) } case OAL_EVENT_BLE_REMOTE_DEVICE_FOUND: { event_ble_scan_result_info *scan_result = event_data; - BT_INFO("OAL Event: OAL_EVENT_BLE_REMOTE_DEVICE_FOUND"); __bt_le_handle_device_found(scan_result); break; } @@ -720,71 +1063,29 @@ static void __bt_le_event_handler(int event_type, gpointer event_data) le_feature_info.le_2m_phy = le_features->le_2m_phy_support; le_feature_info.le_coded_phy = le_features->le_coded_phy_support; + le_feature_info.max_filter = le_features->max_adv_filter; BT_INFO("Adapter LE 2M PHY Support [%s]", le_feature_info.le_2m_phy ? "TRUE" : "FALSE"); BT_INFO("Adapter LE CODED PHY Support [%s]", le_feature_info.le_coded_phy ? "TRUE" : "FALSE"); break; } - case OAL_EVENT_BLE_DISCOVERY_FINISHED: { - _bt_disable_all_scanner_status(); - break; - } default: break; } } -int _bt_unregister_scan_filter(const char *sender, int slot_id) -{ - int ret; - bt_adapter_le_scanner_t *scanner = NULL; - bluetooth_le_scan_filter_t *scan_filter_data = NULL; - GSList *l; - gboolean is_slot_id_found = FALSE; - - scanner = __bt_find_scanner_from_list(sender); - if (scanner == NULL) { - BT_ERR("There is NO available scanner."); - return BLUETOOTH_ERROR_NOT_FOUND; - } - - for (l = scanner->filter_list; l != NULL; l = g_slist_next(l)) { - scan_filter_data = l->data; - if (scan_filter_data->slot_id == slot_id) { - is_slot_id_found = TRUE; - break; - } - } - if (is_slot_id_found == FALSE) { - BT_ERR("There is NO registered slot."); - return BLUETOOTH_ERROR_NOT_FOUND; - } - ret = gattc_unregister_scan_filter(slot_id); - if (OAL_STATUS_SUCCESS != ret) { - BT_ERR("gattc_unregister_scan_filter failed"); - return BLUETOOTH_ERROR_INTERNAL; - } - scanner->filter_list = g_slist_remove(scanner->filter_list, scan_filter_data); - g_free(scan_filter_data); - return BLUETOOTH_ERROR_NONE; -} - int _bt_le_init(void) { - BT_DBG("+"); /* Register LE event handler */ _bt_service_register_event_handler_callback(BT_ADAPTER_LE_MODULE, __bt_le_event_handler); - BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } void _bt_le_deinit(void) { - BT_DBG("+"); /* Un-register LE event handler */ _bt_service_unregister_event_handler_callback(BT_ADAPTER_LE_MODULE); - BT_DBG("-"); } static void __bt_le_update_discovery_status(bt_adapter_discovery_state_t status) @@ -796,7 +1097,6 @@ static void __bt_le_update_discovery_status(bt_adapter_discovery_state_t status) static int __bt_le_state_handle_request(gboolean enable) { int result = BLUETOOTH_ERROR_NONE; - BT_DBG(""); switch (_bt_adapter_get_le_status()) { case BT_LE_ACTIVATING: { @@ -993,7 +1293,6 @@ int _bt_set_custom_advertising(const char *sender, int adv_handle, int server_instance; bt_pending_adv_data_set_t *info = NULL; int result = OAL_STATUS_SUCCESS; - BT_DBG("+"); if (__bt_is_factory_test_mode()) { BT_ERR("Unable to start advertising in factory binary !!"); @@ -1031,6 +1330,13 @@ int _bt_set_custom_advertising(const char *sender, int adv_handle, } if (enable) { + /* Set the Advertising filter policy Parameter in HAL */ + result = adapter_ble_set_filter_policy(params->filter_policy); + + if (result != OAL_STATUS_SUCCESS){ + BT_ERR("OAL API adapter_ble_set_filter_policy Fail %d", result); + return BLUETOOTH_ERROR_INTERNAL; + } /* Set Advertising parameters to Stack */ result = adapter_ble_multi_adv_update(server_instance, params->interval_min, params->interval_max, params->type, BT_ADV_DEFAULT_CHANNEL_MAP, params->tx_power_level, BT_ADV_DEFAULT_TIMEOUT); @@ -1106,7 +1412,6 @@ static int __bt_set_multi_adv_param(oal_ble_multi_adv_param_setup_t *adv_setup, unsigned char *ptr; int num_uuids; - BT_INFO("+"); retv_if(NULL == adv_data, BLUETOOTH_ERROR_INVALID_PARAM); retv_if(NULL == adv_setup, BLUETOOTH_ERROR_INVALID_PARAM); @@ -1114,7 +1419,7 @@ static int __bt_set_multi_adv_param(oal_ble_multi_adv_param_setup_t *adv_setup, int len = ptr[0]; int type = ptr[1]; - BT_INFO("len: %d, type: %x", len, type); + BT_DBG("len: %d, type: 0x%x", len, type); switch (type) { case 0xFF: /* Manufacturer Data */ @@ -1134,7 +1439,6 @@ static int __bt_set_multi_adv_param(oal_ble_multi_adv_param_setup_t *adv_setup, break; case 0x14: { /* 16 bit Solicit UUID */ int c; - int k; num_uuids = (len -1)/2; adv_setup->solicit_uuid = g_malloc0(sizeof(char) * 16 * num_uuids); char *tmp = adv_setup->solicit_uuid; @@ -1148,14 +1452,10 @@ static int __bt_set_multi_adv_param(oal_ble_multi_adv_param_setup_t *adv_setup, if (c < num_uuids) tmp += 16; } - /* DEBUG: Test*/ - for (k = 0; k < 16 * num_uuids; k++) - BT_DBG("%x", adv_setup->solicit_uuid[k]); break; } case 0x02: { /* 16 bit Service UUID */ int c; - int k; num_uuids = (len -1)/2; adv_setup->service_uuid = g_malloc0(sizeof(char) * 16 * num_uuids); char *tmp = adv_setup->service_uuid; @@ -1169,9 +1469,6 @@ static int __bt_set_multi_adv_param(oal_ble_multi_adv_param_setup_t *adv_setup, if (c < num_uuids) tmp += 16; } - /* DEBUG: Test*/ - for (k = 0; k < 16 * num_uuids; k++) - BT_DBG("%x", adv_setup->service_uuid[k]); break; } case 0x16: { /* Service Data */ @@ -1206,7 +1503,6 @@ static int __bt_set_multi_adv_param(oal_ble_multi_adv_param_setup_t *adv_setup, ptr += len + 1; } - BT_INFO("-"); return BLUETOOTH_ERROR_NONE; } @@ -1287,7 +1583,7 @@ int _bt_set_advertising_data(const char *sender, int adv_handle, /* Set Server instance[Product Requirement] */ adv_setup.tx_power = 4; - BT_DBG("####Service UUID len [%d], service data len [%d] Solicit UUID len [%d]", + BT_DBG("Service UUID len [%d], service data len [%d] Solicit UUID len [%d]", adv_setup.solicit_uuid_len, adv_setup.service_uuid_len, adv_setup.service_data_len); result = adapter_ble_multi_adv_set_inst_data(server_instance, &adv_setup); if (result != OAL_STATUS_SUCCESS) { @@ -1570,15 +1866,124 @@ gboolean __send_le_scan_reply(gpointer data) return FALSE; } -static gboolean __start_le_scan_timeout(gpointer user_data) +static int __bt_get_available_scan_filter_slot_id(void) { - char *sender = (char *)user_data; - _bt_start_le_scan(sender); + GSList *l; + bt_adapter_le_scanner_t *scanner; + GSList *fl; + bluetooth_le_scan_filter_t *filter_data; + gboolean *slot_check_list = NULL; + int i; - return FALSE; + if (le_feature_info.max_filter == 0) { + BT_ERR("Scan filter is NOT Supported"); + return -1; + } + slot_check_list = g_malloc0(sizeof(gboolean) * le_feature_info.max_filter); + + for (l = scanner_list; l != NULL; l = g_slist_next(l)) { + scanner = l->data; + for (fl = scanner->filter_list; fl != NULL; fl = g_slist_next(fl)) { + filter_data = fl->data; + if (filter_data->slot_id < le_feature_info.max_filter) + slot_check_list[filter_data->slot_id] = TRUE; + } + } + + for (i = 0; i < le_feature_info.max_filter; i++) { + if (slot_check_list[i] == FALSE) { + g_free(slot_check_list); + return i; + } + } + + BT_ERR("There is NO available slot for scan filter."); + g_free(slot_check_list); + return -1; +} + +int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *filter) +{ + int ret = BLUETOOTH_ERROR_NONE; + bt_adapter_le_scanner_t *scanner = NULL; + bluetooth_le_scan_filter_t *scan_filter_data = NULL; + int slot_id; + + slot_id = __bt_get_available_scan_filter_slot_id(); + if (slot_id == -1) + return BLUETOOTH_ERROR_NO_RESOURCES; + + oal_ble_scan_filter_t filter_data = {.slot_id = slot_id, .device_address = (bt_address_t*)&filter->device_address, .device_name = filter->device_name, + .service_uuid = (oal_uuid_t*)&filter->service_uuid.data, .service_uuid_len = filter->service_uuid.data_len, + .service_uuid_mask = (oal_uuid_t*)&filter->service_uuid_mask.data, .service_uuid_mask_len = filter->service_uuid_mask.data_len, + .service_solicitation_uuid = (oal_uuid_t*)&filter->service_solicitation_uuid.data, + .service_solicitation_uuid_len = filter->service_solicitation_uuid.data_len, + .service_solicitation_uuid_mask = (oal_uuid_t*)&filter->service_solicitation_uuid_mask.data, + .service_solicitation_uuid_mask_len = filter->service_solicitation_uuid_mask.data_len, + .service_data = filter->service_data.data.data, .service_data_len = filter->service_data.data_len, + .service_data_mask = filter->service_data_mask.data.data, .service_data_mask_len = filter->service_data_mask.data_len, + .manufacturer_id = filter->manufacturer_id, .manufacturer_data = filter->manufacturer_data.data.data, + .manufacturer_data_len = filter->manufacturer_data.data_len, .manufacturer_data_mask = filter->manufacturer_data_mask.data.data, + .manufacturer_data_mask_len = filter->manufacturer_data_mask.data_len , .added_features = filter->added_features + }; + ret = gattc_register_scan_filter(&filter_data); + + if (OAL_STATUS_SUCCESS != ret) { + BT_ERR("gattc_register_scan_filter failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + scanner = __bt_find_scanner_from_list(sender); + + if (scanner == NULL) { + scanner = g_malloc0(sizeof(bt_adapter_le_scanner_t)); + + if (scanner == NULL) + return BLUETOOTH_ERROR_MEMORY_ALLOCATION; + + scanner->sender = g_strdup(sender); + scanner_list = g_slist_append(scanner_list, scanner); + } + + scan_filter_data = g_malloc0(sizeof(bluetooth_le_scan_filter_t)); + + memcpy(scan_filter_data, filter, sizeof(bluetooth_le_scan_filter_t)); + + scan_filter_data->slot_id = slot_id; + scanner->filter_list = g_slist_append(scanner->filter_list, scan_filter_data); + + return ret; +} + +int _bt_unregister_all_scan_filters(const char* sender) +{ + int ret; + bt_adapter_le_scanner_t *scanner = NULL; + bluetooth_le_scan_filter_t *filter_data = NULL; + GSList *l; + + scanner = __bt_find_scanner_from_list(sender); + + if (scanner == NULL) { + BT_ERR("There is NO available scanner."); + return BLUETOOTH_ERROR_NOT_FOUND; + } + for (l = scanner->filter_list; l != NULL; l = g_slist_next(l)) { + filter_data = l->data; + + ret = gattc_unregister_scan_filter(filter_data->slot_id); + + if (OAL_STATUS_SUCCESS != ret) + BT_ERR("gattc_unregister_scan_filter failed for slot_id = [%d]", filter_data->slot_id); + } + + g_slist_free_full(scanner->filter_list, g_free); + scanner->filter_list = NULL; + + return BLUETOOTH_ERROR_NONE; } -int _bt_start_le_scan(const char *sender) +int _bt_start_le_scan(const char *sender, uid_t uid, pid_t pid) { bt_adapter_le_scanner_t *scanner; int ret; @@ -1589,38 +1994,61 @@ int _bt_start_le_scan(const char *sender) retv_if(scanner == NULL, BLUETOOTH_ERROR_INTERNAL); scanner->sender = g_strdup(sender); + scanner->uid = uid; + scanner->pid = pid; scanner_list = g_slist_append(scanner_list, scanner); } - if (scanner->stop_pending == TRUE) { - BT_DBG("Waiting LEDiscoveryFinished"); - g_timeout_add(500, (GSourceFunc)__start_le_scan_timeout, scanner->sender); - return BLUETOOTH_ERROR_NONE; - } - + /* Check scanning is in progress or not */ if (scanner->is_scanning) { BT_ERR("BT is already in LE scanning"); return BLUETOOTH_ERROR_IN_PROGRESS; } + scanner->is_scanning = TRUE; + + /* Check scanning is in progress or not by other users */ if (_bt_is_le_scanning()) { int value = 1; - BT_INFO("LE Full Scan is already on progress"); g_idle_add(__send_le_scan_reply, (void *)(intptr_t)value); - goto done; - } - - if (is_le_set_scan_parameter == FALSE) { - bluetooth_le_scan_params_t scan_params; - /* Set default scan parameter same with BT_ADAPTER_LE_SCAN_MODE_LOW_ENERGY */ - scan_params.type = 0x01; - scan_params.interval = 5120; - scan_params.window = 512; - _bt_set_scan_parameters(&scan_params); + /* Disable scan filter if filter is NULL */ + if (scan_filter_enabled == TRUE) { + if (scanner->filter_list == NULL) { + BT_INFO("Disable LE Scan Filter"); + ret = gattc_disable_scan_filter(0); + if (ret != OAL_STATUS_SUCCESS) + BT_ERR("gattc_disable_scan_filter failed"); + scan_filter_enabled = FALSE; + } else { + BT_INFO("LE Filter Scan is continue"); + } + } else { + BT_INFO("LE Full Scan is already on progress"); + } + return BLUETOOTH_ERROR_NONE; } else { - _bt_set_scan_parameters(&le_scan_params); + if (is_le_set_scan_parameter == FALSE) { + /* Set default scan parameter same with BT_ADAPTER_LE_SCAN_MODE_LOW_ENERGY */ + bluetooth_le_scan_params_t scan_params; + scan_params.type = BT_LE_ACTIVE_SCAN; + scan_params.interval = 5120; + scan_params.window = 512; + _bt_set_scan_parameters(&scan_params); + } else + _bt_set_scan_parameters(&le_scan_params); + + /* Enable scan filter if filter is exisiting */ + if (scanner->filter_list == NULL) { + scan_filter_enabled = FALSE; + } else { + BT_INFO("Enable LE Scan Filter"); + ret = gattc_enable_scan_filter(0); + if (ret != OAL_STATUS_SUCCESS) + BT_ERR("gattc_enable_scan_filter failed"); + scan_filter_enabled = TRUE; + } } BT_INFO("Start LE Full Scan"); @@ -1631,29 +2059,31 @@ int _bt_start_le_scan(const char *sender) return BLUETOOTH_ERROR_INTERNAL; } -done: - scanner->is_scanning = TRUE; return BLUETOOTH_ERROR_NONE; } int _bt_stop_le_scan(const char *sender) { - bt_adapter_le_scanner_t *scan_sender; + int result = BLUETOOTH_ERROR_NONE; bt_adapter_le_scanner_t *scanner; gboolean next_scanning = FALSE; GSList *l; int ret; - scan_sender = __bt_find_scanner_from_list(sender); - if (scan_sender == NULL || scan_sender->is_scanning == FALSE) + /* Check scanning is in progress or not */ + scanner = __bt_find_scanner_from_list(sender); + if (scanner == NULL) return BLUETOOTH_ERROR_NOT_IN_OPERATION; - scan_sender->is_scanning = FALSE; - scan_sender->stop_pending = TRUE; + if (scanner->is_scanning == FALSE) + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + + scanner->is_scanning = FALSE; for (l = scanner_list; l != NULL; l = g_slist_next(l)) { - scanner = l->data; - if (scanner->is_scanning == TRUE) + bt_adapter_le_scanner_t *scanner_iter = l->data; + + if (scanner_iter->is_scanning == TRUE) next_scanning = TRUE; } @@ -1661,26 +2091,30 @@ int _bt_stop_le_scan(const char *sender) int value = 0; g_idle_add(__send_le_scan_reply, (void *)(intptr_t)value); - return BLUETOOTH_ERROR_NONE; + result = BLUETOOTH_ERROR_NONE; } else { BT_INFO("Just stop LE scan"); - } + ret = gattc_stop_le_discovery(g_gatt_client_id); - ret = gattc_stop_le_discovery(g_gatt_client_id); + if (OAL_STATUS_SUCCESS != ret) { + BT_ERR("gattc_start_le_discovery failed"); + result = BLUETOOTH_ERROR_INTERNAL; + } - if (OAL_STATUS_SUCCESS != ret) { - BT_ERR("gattc_start_le_discovery failed"); - scan_sender->stop_pending = FALSE; - return BLUETOOTH_ERROR_INTERNAL; +// TODO: Disable scan filter + is_le_set_scan_parameter = FALSE; + + le_scan_params.type = BT_LE_ACTIVE_SCAN; + le_scan_params.interval = 0; + le_scan_params.window = 0; } - is_le_set_scan_parameter = FALSE; + _bt_unregister_all_scan_filters(sender); - le_scan_params.type = BT_LE_ACTIVE_SCAN; - le_scan_params.interval = 0; - le_scan_params.window = 0; + scanner_list = g_slist_remove(scanner_list, scanner); + __bt_free_le_scanner(scanner); - return BLUETOOTH_ERROR_NONE; + return result; } static void _bt_disable_all_scanner_status(void) @@ -1691,32 +2125,9 @@ static void _bt_disable_all_scanner_status(void) for (l = scanner_list; l != NULL; l = g_slist_next(l)) { scanner = l->data; scanner->is_scanning = FALSE; - scanner->stop_pending = FALSE; } } -static void __bt_free_le_scanner(void) -{ - GSList *l; - bt_adapter_le_scanner_t *scanner; - - for (l = scanner_list; l != NULL; l = g_slist_next(l)) { - scanner = l->data; - g_free(scanner->sender); - g_slist_free_full(scanner->filter_list, g_free); - g_free(scanner); - } - - g_slist_free(scanner_list); - scanner_list = NULL; - - is_le_scanning = FALSE; - is_le_set_scan_parameter = FALSE; - le_scan_params.type = BT_LE_ACTIVE_SCAN; - le_scan_params.interval = 0; - le_scan_params.window = 0; -} - void _bt_check_le_scanner_app_termination(const char *sender) { bt_adapter_le_scanner_t *scanner; @@ -1725,12 +2136,16 @@ void _bt_check_le_scanner_app_termination(const char *sender) if (!scanner) return; - if (scanner->is_scanning) - _bt_stop_le_scan(sender); + _bt_bm_remove_scan_app(SCAN_LE, scanner->uid, scanner->pid); + + if (scanner->is_scanning) { + /* Free 'scanner' into the function */ + if (_bt_stop_le_scan(sender) != BLUETOOTH_ERROR_NOT_IN_OPERATION) + return; + } scanner_list = g_slist_remove(scanner_list, scanner); - g_free(scanner->sender); - g_free(scanner); + __bt_free_le_scanner(scanner); } int _bt_service_le_init(void) @@ -1743,7 +2158,7 @@ int _bt_service_le_init(void) void _bt_service_le_deinit(void) { le_deinit(); - __bt_free_le_scanner(); + __bt_free_le_scanner_all(); } int _bt_is_advertising(void) @@ -1772,6 +2187,14 @@ gboolean _bt_is_le_coded_phy_supported(void) return FALSE; } +gboolean _bt_is_scan_filter_supported(void) +{ + if (le_feature_info.max_filter > 0) + return TRUE; + + return FALSE; +} + int _bt_set_le_privacy(gboolean set_privacy) { int result = BLUETOOTH_ERROR_NONE; @@ -1871,7 +2294,7 @@ int _bt_set_le_static_random_address(gboolean is_enable) result = adapter_set_le_static_random_address(is_enable); if (result != OAL_STATUS_SUCCESS) { - BT_ERR("adapter_set_connectable failed: %d", result); + BT_ERR("adapter_set_le_static_random_address failed: %d", result); result = BLUETOOTH_ERROR_INTERNAL; } else { BT_INFO("SetLeStaticRandomAddress as %d", is_enable);