X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service%2Fbt-service-adapter-le.c;h=b7d9c4983ce8fc68a681672f308f10090a16edb1;hb=a0e93a330aa0362824aa37ab8aebd20a3127a434;hp=276f8aa5af1c84d80ecc9402b47e40faf61c3008;hpb=a9de94d8c3927a79b78a732f83dfcc65719a0d83;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service/bt-service-adapter-le.c b/bt-service/bt-service-adapter-le.c old mode 100755 new mode 100644 index 276f8aa..b7d9c49 --- a/bt-service/bt-service-adapter-le.c +++ b/bt-service/bt-service-adapter-le.c @@ -22,9 +22,7 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif #include #include "bt-internal-types.h" @@ -43,6 +41,8 @@ #define BT_ADV_FILTER_POLICY_DEFAULT 0x00 #define BT_ADV_TYPE_DEFAULT 0x00 #define BT_ADV_FILTER_POLICY_ALLOW_SCAN_CONN_WL_ONLY 0x03 +#define BT_SCAN_INTERVAL_SPLIT 0.625 + typedef struct { int adv_inst_max; @@ -54,6 +54,7 @@ typedef struct { char *sender; int adv_handle; gboolean is_advertising; + guint hold_timer_id; } bt_adapter_le_adv_slot_t; typedef struct { @@ -79,7 +80,8 @@ 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 bt_le_scan_type_t le_scan_type = BT_LE_PASSIVE_SCAN; +static bt_le_scan_type_t le_scan_type = BT_LE_ACTIVE_SCAN; +static bluetooth_le_scan_params_t le_scan_params = { BT_LE_ACTIVE_SCAN, 0, 0 }; static GSList *gatt_client_senders = NULL; @@ -141,20 +143,24 @@ void _bt_clear_gatt_client_senders(void) gatt_client_senders = NULL; } } - +#if 0 static void __bt_send_foreach_event(gpointer data, gpointer user_data) { char *sender = data; GVariant *param = user_data; - _bt_send_event_to_dest(sender, BT_DEVICE_EVENT,BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED, + _bt_send_event_to_dest(sender, BT_DEVICE_EVENT, BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED, param); } - +#endif void _bt_send_char_value_changed_event(void *param) { +#if 0 g_slist_foreach(gatt_client_senders, __bt_send_foreach_event, (gpointer)param); +#else + _bt_send_event(BT_DEVICE_EVENT, BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED, param); +#endif } void __bt_free_le_adv_slot(void) @@ -167,38 +173,82 @@ void __bt_free_le_adv_slot(void) for (i = 0; i < le_feature_info.adv_inst_max; i++) { if (le_adv_slot[i].sender) g_free(le_adv_slot[i].sender); + if (le_adv_slot[i].hold_timer_id > 0) + g_source_remove(le_adv_slot[i].hold_timer_id); } g_free(le_adv_slot); le_adv_slot = NULL; } -int _bt_service_adapter_le_init(void) +static void __bt_free_le_scanner(bt_adapter_le_scanner_t *scanner) { - le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max); + g_free(scanner->sender); + g_slist_free_full(scanner->filter_list, g_free); + g_free(scanner); +} - return BLUETOOTH_ERROR_NONE; +static void __bt_free_le_scanner_all(void) +{ + g_slist_free_full(scanner_list, (GDestroyNotify)__bt_free_le_scanner); + scanner_list = NULL; + + scan_filter_enabled = FALSE; + 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_service_adapter_le_deinit(void) +int _bt_le_set_max_packet_len(void) { - __bt_free_le_adv_slot(); + int result = BLUETOOTH_ERROR_NONE; + int tx_octets, tx_time; + bluetooth_le_read_maximum_data_length_t max_len = {0}; + + if (BLUETOOTH_ERROR_NONE != _bt_le_read_maximum_data_length(&max_len)) + return BLUETOOTH_ERROR_INTERNAL; + + if (max_len.max_tx_octets > BT_LE_TX_LEN_DEFAULT) { + tx_octets = max_len.max_tx_octets > BT_LE_TX_LEN_MAX ? + BT_LE_TX_LEN_MAX : max_len.max_tx_octets; + tx_time = BT_LE_TX_TIME_MAX; + + result = _bt_le_write_host_suggested_default_data_length(tx_octets, tx_time); + + BT_DBG("Wrote max packet size : result[%d], MAX[%d], set[%d]", + result, max_len.max_tx_octets, tx_octets); + } + + return result; } gboolean _bt_update_le_feature_support(const char *item, const char *value) { - if (item== NULL || value == NULL) + if (item == NULL || value == NULL) return FALSE; + if (!le_adv_slot) + _bt_service_adapter_le_init(); + if (g_strcmp0(item, "adv_inst_max") == 0) { - if (atoi(value) != le_feature_info.adv_inst_max) { + int slot_num; + + slot_num = atoi(value); + retv_if(slot_num < 0, FALSE); + + if (slot_num != le_feature_info.adv_inst_max) { __bt_free_le_adv_slot(); - le_feature_info.adv_inst_max = atoi(value); + le_feature_info.adv_inst_max = slot_num; + BT_INFO("Advertising instance max : %d", le_feature_info.adv_inst_max); le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max); } } else if (g_strcmp0(item, "rpa_offloading") == 0) { le_feature_info.rpa_offloading = atoi(value); + BT_INFO("RPA offloading : %d", le_feature_info.rpa_offloading); } else if (g_strcmp0(item, "max_filter") == 0) { le_feature_info.max_filter = atoi(value); + BT_INFO("BLE Scan max filter : %d", le_feature_info.max_filter); } else { BT_DBG("No registered item"); return FALSE; @@ -210,12 +260,12 @@ gboolean _bt_update_le_feature_support(const char *item, const char *value) static gboolean __bt_is_factory_test_mode(void) { int mode = 0; -#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) { BT_ERR("Get the DUT Mode fail"); return TRUE; } -#endif + if (mode != FALSE) { BT_INFO("DUT Test Mode !!"); return TRUE; @@ -228,8 +278,12 @@ int __bt_get_available_adv_slot_id(const char *sender, int adv_handle, gboolean { int i; - if (le_adv_slot == NULL) + if (le_adv_slot == NULL) { + BT_ERR("le_adv_slot is NULL"); return -1; + } + + BT_DBG("adv_inst_max : %d", le_feature_info.adv_inst_max); for (i = 0; i < le_feature_info.adv_inst_max; i++) { if (le_adv_slot[i].sender == NULL) @@ -238,10 +292,10 @@ int __bt_get_available_adv_slot_id(const char *sender, int adv_handle, gboolean return i; } - if (le_feature_info.adv_inst_max <= 2) - i = 0; - else if (le_feature_info.adv_inst_max > 2 && use_reserved_slot == TRUE) + if (le_feature_info.adv_inst_max <= 1) i = 0; + else if (use_reserved_slot == TRUE) + i = 1; else i = 2; @@ -253,7 +307,7 @@ int __bt_get_available_adv_slot_id(const char *sender, int adv_handle, gboolean return -1; } -void _bt_register_adv_slot_owner(const char *sender, int adv_handle, int slot_id) +static void __bt_register_adv_slot_owner(const char *sender, int adv_handle, int slot_id) { if (le_adv_slot[slot_id].sender == NULL) { le_adv_slot[slot_id].sender = strdup(sender); @@ -263,6 +317,11 @@ void _bt_register_adv_slot_owner(const char *sender, int adv_handle, int slot_id void _bt_unregister_adv_slot_owner(int slot_id) { + if (le_adv_slot[slot_id].hold_timer_id > 0) { + BT_INFO("Hold state adv is not unregistered"); + return; + } + g_free(le_adv_slot[slot_id].sender); le_adv_slot[slot_id].sender = NULL; le_adv_slot[slot_id].adv_handle = 0; @@ -294,6 +353,9 @@ gboolean _bt_is_advertising(void) gboolean status = FALSE; int i; + if (le_adv_slot == NULL) + return FALSE; + for (i = 0; i < le_feature_info.adv_inst_max; i++) { if (le_adv_slot[i].is_advertising == TRUE) status = TRUE; @@ -355,7 +417,13 @@ int _bt_set_advertising(const char *sender, int adv_handle, gboolean enable, gbo if (le_adv_slot[slot_id].is_advertising == TRUE && enable == TRUE) return BLUETOOTH_ERROR_IN_PROGRESS; - if (le_adv_slot[slot_id].sender != NULL && le_adv_slot[slot_id].is_advertising == FALSE && enable == FALSE) + if (le_adv_slot[slot_id].hold_timer_id > 0) { + g_source_remove(le_adv_slot[slot_id].hold_timer_id); + le_adv_slot[slot_id].hold_timer_id = 0; + _bt_unregister_adv_slot_owner(slot_id); + } + + if (le_adv_slot[slot_id].is_advertising == FALSE && enable == FALSE) return BLUETOOTH_ERROR_NOT_IN_OPERATION; proxy = _bt_get_adapter_proxy(); @@ -369,16 +437,17 @@ int _bt_set_advertising(const char *sender, int adv_handle, gboolean enable, gbo &error); if (error) { + BT_INFO("SetAdvertising %d, slot_id %d", enable, slot_id); BT_ERR("SetAdvertising Fail: %s", error->message); g_clear_error(&error); return BLUETOOTH_ERROR_INTERNAL; } if (enable == TRUE) - _bt_register_adv_slot_owner(sender, adv_handle, slot_id); + __bt_register_adv_slot_owner(sender, adv_handle, slot_id); le_adv_slot[slot_id].is_advertising = enable; - BT_INFO("Set advertising [%d]", enable); + BT_INFO_C("### Set advertising [%d], Slot id [%d]", enable, slot_id); if (ret) g_variant_unref(ret); @@ -417,7 +486,13 @@ int _bt_set_custom_advertising(const char *sender, int adv_handle, if (le_adv_slot[slot_id].is_advertising == TRUE && enable == TRUE) return BLUETOOTH_ERROR_IN_PROGRESS; - if (le_adv_slot[slot_id].sender != NULL && le_adv_slot[slot_id].is_advertising == FALSE && enable == FALSE) + if (le_adv_slot[slot_id].hold_timer_id > 0) { + g_source_remove(le_adv_slot[slot_id].hold_timer_id); + le_adv_slot[slot_id].hold_timer_id = 0; + _bt_unregister_adv_slot_owner(slot_id); + } + + if (le_adv_slot[slot_id].is_advertising == FALSE && enable == FALSE) return BLUETOOTH_ERROR_NOT_IN_OPERATION; proxy = _bt_get_adapter_proxy(); @@ -436,14 +511,18 @@ int _bt_set_custom_advertising(const char *sender, int adv_handle, params->type == BLUETOOTH_ADV_NON_CONNECTABLE) return BLUETOOTH_ERROR_NOT_SUPPORT; + if (params->tx_power_level > 1 || + params->tx_power_level < -127) + return BLUETOOTH_ERROR_INVALID_PARAM; + min = params->interval_min / BT_ADV_INTERVAL_SPLIT; max = params->interval_max / BT_ADV_INTERVAL_SPLIT; ret = g_dbus_proxy_call_sync(proxy, "SetAdvertisingParameters", - g_variant_new("(uuuui)", min, max, + g_variant_new("(uuuuii)", min, max, params->filter_policy, params->type, - slot_id), G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); + params->tx_power_level, slot_id), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) { BT_ERR("SetAdvertisingParameters Fail: %s", error->message); @@ -454,7 +533,8 @@ int _bt_set_custom_advertising(const char *sender, int adv_handle, adv_params.interval_min = params->interval_min; adv_params.interval_max = params->interval_max; adv_params.filter_policy = params->filter_policy; - adv_params.type= params->type; + adv_params.type = params->type; + adv_params.tx_power_level = params->tx_power_level; if (ret) g_variant_unref(ret); @@ -473,18 +553,86 @@ int _bt_set_custom_advertising(const char *sender, int adv_handle, } if (enable == TRUE) - _bt_register_adv_slot_owner(sender, adv_handle, slot_id); - else - _bt_unregister_adv_slot_owner(slot_id); + __bt_register_adv_slot_owner(sender, adv_handle, slot_id); le_adv_slot[slot_id].is_advertising = enable; - BT_INFO_C("Set advertising [%d]", enable); + BT_INFO_C("### Set advertising [%d], Slot id [%d]", enable, slot_id); if (ret) g_variant_unref(ret); return BLUETOOTH_ERROR_NONE; } +static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data) +{ + GDBusProxy *proxy; + GError *error = NULL; + GVariant *ret; + + BT_INFO("Restart advertising stopped by bt-service"); + + le_adv_slot[0].hold_timer_id = 0; + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, FALSE); + + ret = g_dbus_proxy_call_sync(proxy, "SetAdvertising", + g_variant_new("(bi)", TRUE, 0), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (error) { + BT_ERR("SetAdvertising Fail: %s", error->message); + g_clear_error(&error); + return FALSE; + } + + if (ret) + g_variant_unref(ret); + + return FALSE; +} + +int _bt_hold_current_advertising(void) +{ + GDBusProxy *proxy; + GError *error = NULL; + GVariant *ret; + + if (le_adv_slot[0].sender && le_adv_slot[0].is_advertising == TRUE) { + BT_INFO("Stop current advertising by bt-service"); + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + ret = g_dbus_proxy_call_sync(proxy, "SetAdvertising", + g_variant_new("(bi)", FALSE, 0), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (error) { + BT_ERR("SetAdvertising Fail: %s", error->message); + g_clear_error(&error); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (ret) + g_variant_unref(ret); + + le_adv_slot[0].hold_timer_id = g_timeout_add(2000, + __bt_hold_current_advertising_timeout_cb, NULL); + } else { + BT_INFO("It's NOT advertising"); + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + } + + return BLUETOOTH_ERROR_NONE; +} + static int __bt_get_ad_data_by_type(char *in_data, int in_len, char in_type, char **data, int *data_len) { @@ -582,9 +730,8 @@ int _bt_set_advertising_data(const char *sender, int adv_handle, } builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) g_variant_builder_add(builder, "y", adv->data[i]); - } temp = g_variant_new("ay", builder); g_variant_builder_unref(builder); @@ -599,7 +746,7 @@ int _bt_set_advertising_data(const char *sender, int adv_handle, return BLUETOOTH_ERROR_INTERNAL; } - _bt_register_adv_slot_owner(sender, adv_handle, slot_id); + __bt_register_adv_slot_owner(sender, adv_handle, slot_id); __bt_get_ad_data_by_type((char *)adv_data.data, adv_data_len, 0xff, &old_mdata, &old_len); @@ -608,8 +755,8 @@ int _bt_set_advertising_data(const char *sender, int adv_handle, if (old_len != new_len || (old_mdata && new_mdata && memcmp(old_mdata, new_mdata, new_len))) { - ad_data = g_variant_new_from_data((const GVariantType *)"ay", - new_mdata, new_len, TRUE, NULL, NULL); + ad_data = g_variant_new_from_data((const GVariantType *)"ay", + new_mdata, new_len, TRUE, NULL, NULL); param = g_variant_new("(@ay)", ad_data); _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ADVERTISING_MANUFACTURER_DATA_CHANGED, @@ -676,9 +823,8 @@ int _bt_set_scan_response_data(const char *sender, int adv_handle, return BLUETOOTH_ERROR_NO_RESOURCES; } builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) g_variant_builder_add(builder, "y", response->data[i]); - } temp = g_variant_new("ay", builder); g_variant_builder_unref(builder); @@ -693,7 +839,7 @@ int _bt_set_scan_response_data(const char *sender, int adv_handle, return BLUETOOTH_ERROR_INTERNAL; } - _bt_register_adv_slot_owner(sender, adv_handle, slot_id); + __bt_register_adv_slot_owner(sender, adv_handle, slot_id); /* Compare with previous scan resp data */ __bt_get_ad_data_by_type((char *)resp_data.data, resp_data_len, 0xff, @@ -704,7 +850,7 @@ int _bt_set_scan_response_data(const char *sender, int adv_handle, (old_mdata && new_mdata && memcmp(old_mdata, new_mdata, new_len))) { scan_data = g_variant_new_from_data((const GVariantType *)"ay", - new_mdata, new_len, TRUE, NULL, NULL); + new_mdata, new_len, TRUE, NULL, NULL); param = g_variant_new("(@ay)", scan_data); _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_SCAN_RESPONSE_MANUFACTURER_DATA_CHANGED, @@ -741,6 +887,8 @@ int _bt_set_scan_parameters(bluetooth_le_scan_params_t *params) proxy = _bt_get_adapter_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + BT_DBG("inteval %f, win %f, type %d", params->interval, params->window, params->type); + if (params->interval < BT_LE_SCAN_INTERVAL_MIN || params->interval > BT_LE_SCAN_INTERVAL_MAX) return BLUETOOTH_ERROR_INVALID_PARAM; @@ -750,8 +898,8 @@ int _bt_set_scan_parameters(bluetooth_le_scan_params_t *params) if (params->window > params->interval) return BLUETOOTH_ERROR_INVALID_PARAM; - itv = params->interval / BT_ADV_INTERVAL_SPLIT; - win = params->window / BT_ADV_INTERVAL_SPLIT; + itv = params->interval / BT_SCAN_INTERVAL_SPLIT; + win = params->window / BT_SCAN_INTERVAL_SPLIT; ret = g_dbus_proxy_call_sync(proxy, "SetScanParameters", g_variant_new("(uuu)", params->type, itv, win), @@ -770,7 +918,46 @@ int _bt_set_scan_parameters(bluetooth_le_scan_params_t *params) if (ret) g_variant_unref(ret); - BT_INFO("Set scan parameters"); + BT_INFO("Set scan parameters inteval %f, win %f, type %d", + itv * BT_SCAN_INTERVAL_SPLIT, win * BT_SCAN_INTERVAL_SPLIT, params->type); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_prepare_scan_parameters(bluetooth_le_scan_params_t *params, int scan_type) +{ + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + if (params) + BT_DBG("inteval %f, win %f", params->interval, params->window); + else + BT_DBG("type %d", scan_type); + + if (params) { + if (params->interval < BT_LE_SCAN_INTERVAL_MIN || params->interval > BT_LE_SCAN_INTERVAL_MAX) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (params->window < BT_LE_SCAN_WINDOW_MIN || params->window > BT_LE_SCAN_WINDOW_MAX) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (params->window > params->interval) + return BLUETOOTH_ERROR_INVALID_PARAM; + + le_scan_params.interval = params->interval; + le_scan_params.window = params->window; + } else { + le_scan_params.type = scan_type; + if (le_scan_params.interval == 0) { + /* Set default scan interval same with BT_ADAPTER_LE_SCAN_MODE_LOW_ENERGY */ + le_scan_params.interval = 5120; + le_scan_params.window = 512; + } + } + + is_le_set_scan_parameter = TRUE; + return BLUETOOTH_ERROR_NONE; } @@ -788,7 +975,7 @@ bt_adapter_le_scanner_t* __bt_find_scanner_from_list(const char *sender) return NULL; } -int __bt_get_available_scan_filter_slot_id(void) +static int __bt_get_available_scan_filter_slot_id(void) { GSList *l; bt_adapter_le_scanner_t *scanner; @@ -802,18 +989,13 @@ int __bt_get_available_scan_filter_slot_id(void) return -1; } slot_check_list = g_malloc0(sizeof(gboolean) * le_feature_info.max_filter); - if (slot_check_list == NULL) { - BT_ERR("Fail to allocate memory"); - return -1; - } 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) { + if (filter_data->slot_id < le_feature_info.max_filter) slot_check_list[filter_data->slot_id] = TRUE; - } } } @@ -829,7 +1011,15 @@ int __bt_get_available_scan_filter_slot_id(void) return -1; } -int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *filter, int *slot_id) +gboolean _bt_is_scan_filter_supported(void) +{ + if (le_feature_info.max_filter > 0) + return TRUE; + + return FALSE; +} + +int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *filter) { GDBusProxy *proxy; GError *error = NULL; @@ -843,9 +1033,10 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil bt_adapter_le_scanner_t *scanner = NULL; bluetooth_le_scan_filter_t *filter_data = NULL; int feature_selection = 0; + int slot_id; - *slot_id = __bt_get_available_scan_filter_slot_id(); - if (*slot_id == -1) + slot_id = __bt_get_available_scan_filter_slot_id(); + if (slot_id == -1) return BLUETOOTH_ERROR_NO_RESOURCES; proxy = _bt_get_adapter_proxy(); @@ -870,7 +1061,7 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil 0, // client_if 0, // action (Add - 0x00, Delete - 0x01, Clear - 0x02) BLUETOOTH_LE_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type - *slot_id, // filter_index + slot_id, // filter_index 0, // company_id 0, // company_id_mask arr_uuid_param, // p_uuid @@ -908,7 +1099,7 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil 0, // client_if 0, // action (Add - 0x00, Delete - 0x01, Clear - 0x02) BLUETOOTH_LE_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type - *slot_id, // filter_index + slot_id, // filter_index 0, // company_id 0, // company_id_mask arr_uuid_param, // p_uuid @@ -940,9 +1131,9 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil g_array_append_vals(arr_uuid_mask, filter->service_uuid_mask.data.data, filter->service_uuid_mask.data_len * sizeof(guint8)); arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL); + arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL); arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL); + arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL); arr_data_param = g_variant_new_from_data((const GVariantType *)"ay", NULL, 0, TRUE, NULL, NULL); arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay", @@ -952,12 +1143,12 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil 0, // client_if 0, // action (Add - 0x00, Delete - 0x01, Clear - 0x02) BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type - *slot_id, // filter_index + slot_id, // filter_index 0, // company_id 0, // company_id_mask arr_uuid_param, // p_uuid arr_uuid_mask_param, // p_uuid_mask - NULL, // string + "", // string 0, // address_type arr_data_param, // p_data arr_data_mask_param); @@ -975,8 +1166,6 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil g_array_free(arr_uuid, TRUE); g_array_free(arr_uuid_mask, TRUE); - g_array_free(arr_data, TRUE); - g_array_free(arr_data_mask, TRUE); } if (filter->added_features & BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) { @@ -989,9 +1178,9 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil g_array_append_vals(arr_uuid_mask, filter->service_solicitation_uuid_mask.data.data, filter->service_solicitation_uuid_mask.data_len * sizeof(guint8)); arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL); + arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL); arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL); + arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL); arr_data_param = g_variant_new_from_data((const GVariantType *)"ay", NULL, 0, TRUE, NULL, NULL); arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay", @@ -1001,12 +1190,12 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil 0, // client_if 0, // action (Add - 0x00, Delete - 0x01, Clear - 0x02) BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type - *slot_id, // filter_index + slot_id, // filter_index 0, // company_id 0, // company_id_mask arr_uuid_param, // p_uuid arr_uuid_mask_param, // p_uuid_mask - NULL, // string + "", // string 0, // address_type arr_data_param, // p_data arr_data_mask_param); @@ -1040,20 +1229,20 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay", NULL, 0, TRUE, NULL, NULL); arr_data_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_data->data, arr_data->len, TRUE, NULL, NULL); + arr_data->data, arr_data->len, TRUE, NULL, NULL); arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL); + arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL); param = g_variant_new("(iiiiii@ay@aysu@ay@ay)", 0, // client_if 0, // action (Add - 0x00, Delete - 0x01, Clear - 0x02) BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type - *slot_id, // filter_index + slot_id, // filter_index 0, // company_id 0, // company_id_mask arr_uuid_param, // p_uuid arr_uuid_mask_param, // p_uuid_mask - NULL, // string + "", // string 0, // address_type arr_data_param, // p_data arr_data_mask_param); @@ -1087,20 +1276,20 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay", NULL, 0, TRUE, NULL, NULL); arr_data_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_data->data, arr_data->len, TRUE, NULL, NULL); + arr_data->data, arr_data->len, TRUE, NULL, NULL); arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay", - arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL); + arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL); param = g_variant_new("(iiiiii@ay@aysu@ay@ay)", 0, // client_if 0, // action (Add - 0x00, Delete - 0x01, Clear - 0x02) BLUETOOTH_LE_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type - *slot_id, // filter_index + slot_id, // filter_index filter->manufacturer_id, // company_id 0xFFFF, // company_id_mask arr_uuid_param, // p_uuid arr_uuid_mask_param, // p_uuid_mask - NULL, // string + "", // string 0, // address_type arr_data_param, // p_data arr_data_mask_param); @@ -1125,7 +1314,7 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil param = g_variant_new("(iiiiiiiiiiii)", 0, // client_if 0, // action (Add - 0x00, Delete - 0x01, Clear - 0x02) - *slot_id, // filter_index + slot_id, // filter_index feature_selection, // feat_seln 0, // list_logic_type (OR - 0x00, AND - 0x01) 1, // filt_logic_type (OR - 0x00, AND - 0x01) @@ -1147,70 +1336,19 @@ int _bt_register_scan_filter(const char *sender, bluetooth_le_scan_filter_t *fil scanner = __bt_find_scanner_from_list(sender); if (scanner == NULL) { scanner = g_malloc0(sizeof(bt_adapter_le_scanner_t)); - if (scanner) { - scanner->sender = strdup(sender); - scanner_list = g_slist_append(scanner_list, scanner); - } - } - - filter_data = g_malloc0(sizeof(bluetooth_le_scan_filter_t)); - if (filter_data) { - memcpy(filter_data, filter, sizeof(bluetooth_le_scan_filter_t)); - filter_data->slot_id = *slot_id; - - if (scanner) - scanner->filter_list = g_slist_append(scanner->filter_list, filter_data); - } - - if (ret) - g_variant_unref(ret); - return BLUETOOTH_ERROR_NONE; -} - -int _bt_unregister_scan_filter(const char *sender, int slot_id) -{ - GDBusProxy *proxy; - GError *error = NULL; - GVariant *ret; - bt_adapter_le_scanner_t *scanner = NULL; - bluetooth_le_scan_filter_t *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)) { - filter_data = l->data; - if (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; + scanner->sender = g_strdup(sender); + scanner_list = g_slist_append(scanner_list, scanner); } - proxy = _bt_get_adapter_proxy(); - retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear", - g_variant_new("(ii)", 0, slot_id), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); + if (scanner) { + filter_data = g_malloc0(sizeof(bluetooth_le_scan_filter_t)); + memcpy(filter_data, filter, sizeof(bluetooth_le_scan_filter_t)); + filter_data->slot_id = slot_id; - if (error) { - BT_ERR("scan_filter_clear Fail: %s", error->message); - g_clear_error(&error); + scanner->filter_list = g_slist_append(scanner->filter_list, filter_data); } - scanner->filter_list = g_slist_remove(scanner->filter_list, filter_data); - g_free(filter_data); - if (ret) g_variant_unref(ret); return BLUETOOTH_ERROR_NONE; @@ -1264,9 +1402,7 @@ int _bt_start_le_scan(const char *sender) if (scanner == NULL) { scanner = g_malloc0(sizeof(bt_adapter_le_scanner_t)); - retv_if(scanner == NULL, BLUETOOTH_ERROR_INTERNAL); - - scanner->sender = strdup(sender); + scanner->sender = g_strdup(sender); scanner_list = g_slist_append(scanner_list, scanner); } @@ -1287,7 +1423,7 @@ int _bt_start_le_scan(const char *sender) G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) { - BT_ERR("scan_filter_clear Fail: %s", error->message); + BT_ERR("scan_filter_enable Fail: %s", error->message); g_clear_error(&error); } @@ -1307,10 +1443,11 @@ int _bt_start_le_scan(const char *sender) /* 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 = 5000; - scan_params.window = 500; + scan_params.interval = 5120; + scan_params.window = 512; _bt_set_scan_parameters(&scan_params); - } + } else + _bt_set_scan_parameters(&le_scan_params); if (scanner->filter_list == NULL) { BT_INFO("Start LE Full Scan"); @@ -1321,7 +1458,7 @@ int _bt_start_le_scan(const char *sender) G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) { - BT_ERR("scan_filter_clear Fail: %s", error->message); + BT_ERR("scan_filter_enable Fail: %s", error->message); g_clear_error(&error); } @@ -1333,7 +1470,7 @@ int _bt_start_le_scan(const char *sender) } ret = g_dbus_proxy_call_sync(proxy, "StartLEDiscovery", - NULL,G_DBUS_CALL_FLAGS_NONE, + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) { @@ -1360,7 +1497,10 @@ int _bt_stop_le_scan(const char *sender) if (scanner == NULL || scanner->is_scanning == FALSE) return BLUETOOTH_ERROR_NOT_IN_OPERATION; - scanner->is_scanning = FALSE; + _bt_unregister_all_scan_filters(sender); + + scanner_list = g_slist_remove(scanner_list, scanner); + __bt_free_le_scanner(scanner); for (l = scanner_list; l != NULL; l = g_slist_next(l)) { scanner = l->data; @@ -1382,7 +1522,7 @@ int _bt_stop_le_scan(const char *sender) -1, NULL, &error); if (error) { - BT_ERR("scan_filter_clear Fail: %s", error->message); + BT_ERR("scan_filter_enable Fail: %s", error->message); g_clear_error(&error); } @@ -1391,6 +1531,7 @@ int _bt_stop_le_scan(const char *sender) BT_INFO("Enable LE Scan Filter"); scan_filter_enabled = TRUE; } + BT_INFO("next_scanning exists. Keep the LE scanning"); return BLUETOOTH_ERROR_NONE; } else { if (scan_filter_enabled == TRUE) { @@ -1400,7 +1541,7 @@ int _bt_stop_le_scan(const char *sender) -1, NULL, &error); if (error) { - BT_ERR("scan_filter_clear Fail: %s", error->message); + BT_ERR("scan_filter_enable Fail: %s", error->message); g_clear_error(&error); } @@ -1413,8 +1554,13 @@ int _bt_stop_le_scan(const char *sender) } ret = g_dbus_proxy_call_sync(proxy, "StopLEDiscovery", - NULL,G_DBUS_CALL_FLAGS_NONE, + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + BT_ERR("StopLEDiscovery Fail: %s", error->message); + g_clear_error(&error); + } + if (ret == NULL) { BT_ERR("LE Scan stop failed"); return BLUETOOTH_ERROR_INTERNAL; @@ -1422,6 +1568,9 @@ int _bt_stop_le_scan(const char *sender) scan_filter_enabled = 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; if (ret) g_variant_unref(ret); return BLUETOOTH_ERROR_NONE; @@ -1440,6 +1589,7 @@ void _bt_disable_all_scanner_status(void) void _bt_set_le_scan_status(gboolean mode) { + BT_DBG("set is_le_scanning : %d -> %d", is_le_scanning, mode); is_le_scanning = mode; } @@ -1469,7 +1619,6 @@ static gboolean __bt_check_scan_result_uuid(const char *adv_data, __bt_get_ad_data_by_type((char*)adv_data, adv_data_len, ad_type, &data, &data_len); if (data != NULL) { - _bt_swap_byte_ordering(data, data_len); for (i = 0; i < data_len; i += uuid_len) { if (uuid_len > (data_len - i)) break; @@ -1678,14 +1827,24 @@ static gboolean __bt_check_scan_result_with_filter(const char *device_address, adv_data_len, BT_LE_AD_TYPE_MANUFACTURER_SPECIFIC_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, - (char*)filter_data->manufacturer_data.data.data, - (char*)filter_data->manufacturer_data_mask.data.data, - data_len) == 0) { - is_matched = TRUE; + 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, + (char*)filter_data->manufacturer_data.data.data, + (char*)filter_data->manufacturer_data_mask.data.data, + data_len - 2) == 0) { + is_matched = TRUE; + } + } } g_free(data); data = NULL; @@ -1694,14 +1853,24 @@ static gboolean __bt_check_scan_result_with_filter(const char *device_address, scan_data_len, BT_LE_AD_TYPE_MANUFACTURER_SPECIFIC_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, - (char*)filter_data->manufacturer_data.data.data, - (char*)filter_data->manufacturer_data_mask.data.data, - data_len) == 0) { - is_matched = TRUE; + 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, + (char*)filter_data->manufacturer_data.data.data, + (char*)filter_data->manufacturer_data_mask.data.data, + data_len - 2) == 0) { + is_matched = TRUE; + } + } } g_free(data); data = NULL; @@ -1775,10 +1944,8 @@ void _bt_send_scan_result_event(const bt_remote_le_dev_info_t *le_dev_info, int scan_data_len = 0; ret_if(le_dev_info == NULL); - if (_bt_get_le_scan_type() == BT_LE_ACTIVE_SCAN) - ret_if(adv_info == NULL); - if (_bt_get_le_scan_type() == BT_LE_PASSIVE_SCAN) { + if (adv_info == NULL) { /* Not received scan response data within 1 sec */ adv_data = le_dev_info->adv_data; adv_data_len = le_dev_info->adv_data_len; scan_data = le_dev_info->adv_data; @@ -1815,8 +1982,42 @@ void _bt_send_scan_result_event(const bt_remote_le_dev_info_t *le_dev_info, scan_data_len, scan_data_param); +#if 0 _bt_send_event_to_dest(scanner->sender, BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, param); +#else + _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, param); +#endif + } +} + +void _bt_send_ibeacon_scan_result_event(const bt_remote_ibeacon_dev_info_t *ibeacon_dev_info) +{ + int result = BLUETOOTH_ERROR_NONE; + GSList *l; + GVariant *param; + bt_adapter_le_scanner_t *scanner = NULL; + + ret_if(ibeacon_dev_info == NULL); + BT_DBG("_bt_send_ibeacon_scan_result_event"); + + for (l = scanner_list; l != NULL; l = g_slist_next(l)) { + scanner = l->data; + if (scanner->is_scanning == FALSE) + continue; + + param = g_variant_new("(isnnnsnnn)", + result, + ibeacon_dev_info->address, + ibeacon_dev_info->addr_type, + ibeacon_dev_info->company_id, + ibeacon_dev_info->ibeacon_type, + ibeacon_dev_info->uuid, + ibeacon_dev_info->major_id, + ibeacon_dev_info->minor_id, + ibeacon_dev_info->measured_power); + + _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_REMOTE_IBEACON_DEVICE_FOUND, param); } } @@ -1917,7 +2118,7 @@ int _bt_clear_white_list(void) retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); ret = g_dbus_proxy_call_sync(proxy, "ClearDeviceWhiteList", - NULL,G_DBUS_CALL_FLAGS_NONE, + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) { @@ -1949,7 +2150,7 @@ int _bt_initialize_ipsp(void) retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); ret = g_dbus_proxy_call_sync(proxy, "InitializeIpsp", - NULL,G_DBUS_CALL_FLAGS_NONE, + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) { BT_ERR("Initialize IPSP Failed :[%s]", error->message); @@ -1980,7 +2181,7 @@ int _bt_deinitialize_ipsp(void) retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); ret = g_dbus_proxy_call_sync(proxy, "DeinitializeIpsp", - NULL,G_DBUS_CALL_FLAGS_NONE, + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) { BT_ERR("De-Initialize IPSP Failed :[%s]", error->message); @@ -2010,8 +2211,6 @@ int _bt_le_read_maximum_data_length( reply = g_dbus_proxy_call_sync(proxy, "LEReadMaximumDataLength", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - g_object_unref(proxy); - if (reply == NULL) { BT_ERR("LEReadMaximumDataLength dBUS-RPC failed"); if (error != NULL) { @@ -2022,7 +2221,7 @@ int _bt_le_read_maximum_data_length( return BLUETOOTH_ERROR_INTERNAL; } - g_variant_get(reply ,"(qqqq)", &max_tx_octets, &max_tx_time, + g_variant_get(reply, "(qqqq)", &max_tx_octets, &max_tx_time, &max_rx_octets, &max_rx_time); max_le_datalength->max_tx_octets = max_tx_octets; @@ -2052,8 +2251,6 @@ int _bt_le_write_host_suggested_default_data_length( NULL, &error); - g_object_unref(proxy); - if (reply == NULL) { BT_ERR("_bt_le_write_host_suggested_default_data_length dBUS-RPC failed"); if (error != NULL) { @@ -2093,7 +2290,7 @@ int _bt_le_read_host_suggested_default_data_length( return BLUETOOTH_ERROR_INTERNAL; } - g_variant_get(reply ,"(qq)", &def_tx_octets, &def_tx_time); + g_variant_get(reply, "(qq)", &def_tx_octets, &def_tx_time); def_data_length->def_tx_octets = def_tx_octets; def_data_length->def_tx_time = def_tx_time; @@ -2123,11 +2320,11 @@ int _bt_le_set_data_length(bluetooth_device_address_t *device_address, return BLUETOOTH_ERROR_INTERNAL; } - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); if (conn == NULL) { BT_ERR("conn == NULL"); g_free(device_path); - return NULL; + return BLUETOOTH_ERROR_INTERNAL; } device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, @@ -2155,3 +2352,16 @@ int _bt_le_set_data_length(bluetooth_device_address_t *device_address, return BLUETOOTH_ERROR_NONE; } + +int _bt_service_adapter_le_init(void) +{ + le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max); + + return BLUETOOTH_ERROR_NONE; +} + +void _bt_service_adapter_le_deinit(void) +{ + __bt_free_le_adv_slot(); + __bt_free_le_scanner_all(); +}