*/
#include <stdio.h>
+#include <dbus/dbus.h>
#include <gio/gio.h>
#include <glib.h>
#include <dlog.h>
#include <string.h>
#include <vconf.h>
#include <syspopup_caller.h>
+#include <aul.h>
#include "bt-internal-types.h"
#include "bt-service-common.h"
char *sender;
GSList *filter_list;
gboolean is_scanning;
+ gboolean stop_pending;
} bt_adapter_le_scanner_t;
static bluetooth_advertising_params_t adv_params = {
static gboolean scan_filter_enabled = FALSE;
static bt_le_scan_type_t le_scan_type = BT_LE_PASSIVE_SCAN;
-static void __bt_free_le_adv_slot(void)
+static GSList *gatt_client_senders = NULL;
+
+
+gboolean _bt_is_set_scan_parameter(void)
+{
+ return is_le_set_scan_parameter;
+}
+
+void _bt_init_gatt_client_senders(void)
+{
+ _bt_clear_request_list();
+}
+
+int _bt_insert_gatt_client_sender(char *sender)
+{
+ char *info;
+
+ retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+ info = g_strdup(sender);
+ retv_if(info == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
+
+ gatt_client_senders = g_slist_append(gatt_client_senders, info);
+
+ BT_DBG("insert sender: %s", sender);
+
+ return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_delete_gatt_client_sender(char *sender)
+{
+ GSList *l;
+ char *info;
+
+ BT_DBG("remove sender: %s", sender);
+
+ for (l = gatt_client_senders; l != NULL; l = g_slist_next(l)) {
+ info = l->data;
+ if (info == NULL)
+ continue;
+
+ if (g_strcmp0(info, sender) == 0) {
+ BT_DBG("remove info");
+ gatt_client_senders = g_slist_remove(gatt_client_senders, info);
+ g_free(info);
+ return BLUETOOTH_ERROR_NONE;
+ }
+ }
+
+ return BLUETOOTH_ERROR_NOT_FOUND;
+}
+
+void _bt_clear_gatt_client_senders(void)
+{
+ if (gatt_client_senders) {
+ g_slist_foreach(gatt_client_senders, (GFunc)g_free, NULL);
+ g_slist_free(gatt_client_senders);
+ 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,
+ 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)
{
int i;
le_adv_slot = NULL;
}
+int _bt_le_set_max_packet_len(void)
+{
+ 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)
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;
static void __bt_register_adv_slot_owner(const char *sender, int adv_handle, int slot_id)
{
- if (le_adv_slot == NULL)
- return;
-
if (le_adv_slot[slot_id].sender == NULL) {
le_adv_slot[slot_id].sender = strdup(sender);
le_adv_slot[slot_id].adv_handle = adv_handle;
void _bt_unregister_adv_slot_owner(int slot_id)
{
- if (le_adv_slot == NULL)
- return;
-
if (le_adv_slot[slot_id].hold_timer_id > 0) {
BT_INFO("Hold state adv is not unregistered");
return;
void _bt_set_advertising_status(int slot_id, gboolean mode)
{
- if (le_adv_slot == NULL)
- return;
-
le_adv_slot[slot_id].is_advertising = mode;
}
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;
return status;
}
-gboolean _bt_is_multi_adv_supported(void)
-{
- return (le_feature_info.adv_inst_max > 1) ? TRUE : FALSE;
-}
-
void _bt_stop_advertising_by_terminated_process(const char* terminated_name)
{
int i;
&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;
__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);
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);
adv_params.interval_max = params->interval_max;
adv_params.filter_policy = params->filter_policy;
adv_params.type = params->type;
+ adv_params.tx_power_level = params->tx_power_level;
if (ret)
g_variant_unref(ret);
__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);
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) {
return BLUETOOTH_ERROR_NONE;
}
+static gboolean __start_le_scan_timeout(gpointer user_data)
+{
+ char *sender = (char *)user_data;
+ _bt_start_le_scan(sender);
+
+ return FALSE;
+}
+
+
int _bt_start_le_scan(const char *sender)
{
GDBusProxy *proxy;
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;
+ }
+
if (scanner->is_scanning == TRUE) {
BT_ERR("BT is already in LE scanning");
return BLUETOOTH_ERROR_IN_PROGRESS;
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);
}
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);
}
GDBusProxy *proxy;
GError *error = NULL;
GVariant *ret;
- bt_adapter_le_scanner_t *scanner = __bt_find_scanner_from_list(sender);
+ bt_adapter_le_scanner_t *scan_sender = __bt_find_scanner_from_list(sender);
+ bt_adapter_le_scanner_t *scanner;
GSList *l;
gboolean next_scanning = FALSE;
gboolean need_scan_filter = TRUE;
- if (scanner == NULL || scanner->is_scanning == FALSE)
+ if (scan_sender == NULL || scan_sender->is_scanning == FALSE)
return BLUETOOTH_ERROR_NOT_IN_OPERATION;
- scanner->is_scanning = FALSE;
+ scan_sender->is_scanning = FALSE;
+ scan_sender->stop_pending = TRUE;
for (l = scanner_list; l != NULL; l = g_slist_next(l)) {
scanner = l->data;
-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);
}
BT_INFO("Enable LE Scan Filter");
scan_filter_enabled = TRUE;
}
+ BT_INFO("next_scanning exists. Keep the LE scanning");
+ scan_sender->stop_pending = FALSE;
return BLUETOOTH_ERROR_NONE;
} else {
if (scan_filter_enabled == TRUE) {
-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);
}
ret = g_dbus_proxy_call_sync(proxy, "StopLEDiscovery",
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;
for (l = scanner_list; l != NULL; l = g_slist_next(l)) {
scanner = l->data;
scanner->is_scanning = FALSE;
+ scanner->stop_pending = FALSE;
}
}
void _bt_set_le_scan_status(gboolean mode)
{
+ BT_DBG("set is_le_scanning : %d -> %d", is_le_scanning, mode);
is_le_scanning = mode;
}
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);
}
}