X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service%2Fbt-service-adapter.c;h=eb358f2448455683daf7404fd1e2596c3d94774d;hb=aa9b3271329649a3289501711e53d39fe38318b6;hp=3f510adaa8ab25ce3a98bce3f79cd5bd403f5786;hpb=25986f9247de588fc3bb272c5acf6544434f46bf;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service/bt-service-adapter.c b/bt-service/bt-service-adapter.c index 3f510ad..eb358f2 100644 --- a/bt-service/bt-service-adapter.c +++ b/bt-service/bt-service-adapter.c @@ -1,13 +1,11 @@ /* - * bluetooth-frwk - * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,33 +16,38 @@ */ #include -#include -#include +#include #include #include #include #include -#include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif -#ifdef __TIZEN_MOBILE__ #include -#endif -#include "alarm.h" +#include +#include +#include +#include +#include +#include "alarm.h" #include "bluetooth-api.h" #include "bt-internal-types.h" - #include "bt-service-common.h" #include "bt-service-event.h" #include "bt-service-adapter.h" #include "bt-service-util.h" #include "bt-service-network.h" #include "bt-service-obex-server.h" +#include "bt-service-opp-client.h" #include "bt-service-agent.h" #include "bt-service-main.h" #include "bt-service-avrcp.h" +#include "bt-service-device.h" +#include "bt-service-adapter-le.h" + +#ifdef TIZEN_DPM_ENABLE +#include "bt-service-dpm.h" +#endif typedef struct { guint event_id; @@ -53,17 +56,91 @@ typedef struct { int alarm_id; } bt_adapter_timer_t; -bt_adapter_timer_t visible_timer; +bt_adapter_timer_t visible_timer = {0, }; + +typedef struct { + alarm_id_t alarm_id; + bt_set_alarm_cb callback; + void *user_data; +} bt_service_alarm_t; + +typedef struct { + gboolean is_alarm_initialized; + GList *g_alarm_list; +} bt_service_alarm_mgr_t; + +static bt_service_alarm_mgr_t alarm_mgr = {0, }; + static gboolean is_discovering; static gboolean cancel_by_user; static bt_status_t adapter_status = BT_DEACTIVATED; +static bt_le_status_t adapter_le_status = BT_LE_DEACTIVATED; +static gboolean is_le_intended = FALSE; static void *adapter_agent = NULL; -static DBusGProxy *core_proxy = NULL; +static GDBusProxy *core_proxy = NULL; +static guint timer_id = 0; +static guint le_timer_id = 0; +static gboolean is_recovery_mode; +static gboolean in_power_off; + +static guint poweroff_subscribe_id; +static uint status_reg_id; #define BT_CORE_NAME "org.projectx.bt_core" #define BT_CORE_PATH "/org/projectx/bt_core" #define BT_CORE_INTERFACE "org.projectx.btcore" +#define BT_DISABLE_TIME 500 /* 500 ms */ + +static int alarm_cb(alarm_id_t alarm_id, void* user_param); +static void alarm_data_free(void *data); + +GDBusProxy *_bt_init_core_proxy(void) +{ + GDBusProxy *proxy; + GDBusConnection *conn; + + conn = _bt_gdbus_get_system_gconn(); + if (!conn) + return NULL; + + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, + BT_CORE_NAME, + BT_CORE_PATH, + BT_CORE_INTERFACE, + NULL, NULL); + + if (!proxy) + return NULL; + + core_proxy = proxy; + + return proxy; +} + +static GDBusProxy *__bt_get_core_proxy(void) +{ + return (core_proxy) ? core_proxy : _bt_init_core_proxy(); +} + +static gboolean __bt_is_factory_test_mode(void) +{ + int mode = 0; + + if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) { + BT_ERR("Get the DUT Mode fail"); + return TRUE; + } + + if (mode != FALSE) { + BT_INFO("DUT Test Mode !!"); + return TRUE; + } + + return FALSE; +} + static gboolean __bt_timeout_handler(gpointer user_data) { int result = BLUETOOTH_ERROR_NONE; @@ -77,17 +154,17 @@ static gboolean __bt_timeout_handler(gpointer user_data) /* Send event to application */ _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &time_diff, - DBUS_TYPE_INVALID); + g_variant_new("(in)", result, time_diff)); if (visible_timer.timeout <= time_diff) { g_source_remove(visible_timer.event_id); visible_timer.event_id = 0; visible_timer.timeout = 0; +#ifndef TIZEN_PROFILE_WEARABLE if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) - BT_DBG("Set vconf failed\n"); + BT_ERR("Set vconf failed\n"); +#endif return FALSE; } @@ -96,418 +173,240 @@ static gboolean __bt_timeout_handler(gpointer user_data) static int __bt_visibility_alarm_cb(alarm_id_t alarm_id, void* user_param) { - BT_DBG("__bt_visibility_alarm_cb \n"); + int result = BLUETOOTH_ERROR_NONE; + int timeout = 0; + + if (alarm_id != visible_timer.alarm_id) + return 0; + + if (visible_timer.event_id) { + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED, + g_variant_new("(in)", result, timeout)); + g_source_remove(visible_timer.event_id); + visible_timer.event_id = 0; + visible_timer.timeout = 0; + +#ifndef TIZEN_PROFILE_WEARABLE + if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) + BT_ERR("Set vconf failed\n"); +#endif + } /* Switch Off visibility in Bluez */ _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0); visible_timer.alarm_id = 0; - alarmmgr_fini(); return 0; } -static void __bt_visibility_alarm_create() -{ - alarm_id_t alarm_id; - int result; - - result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, visible_timer.timeout, - 0, NULL, &alarm_id); - if(result < 0) { - BT_DBG("Failed to create alarm error = %d\n", result); - alarmmgr_fini(); - } else { - BT_DBG("Alarm created = %d\n", alarm_id); - visible_timer.alarm_id = alarm_id; - } -} - -int __bt_set_visible_time(int timeout) +static void __bt_visibility_alarm_remove() { - int result; - if (visible_timer.event_id > 0) { g_source_remove(visible_timer.event_id); visible_timer.event_id = 0; } if (visible_timer.alarm_id > 0) { - alarmmgr_remove_alarm(visible_timer.alarm_id); + _bt_service_remove_alarm(visible_timer.alarm_id); visible_timer.alarm_id = 0; } +} + +int __bt_set_visible_time(int timeout) +{ + int result; + alarm_id_t alarm_id; + + __bt_visibility_alarm_remove(); visible_timer.timeout = timeout; +#ifndef TIZEN_PROFILE_WEARABLE +#ifdef TIZEN_DPM_ENABLE + if (_bt_dpm_get_bluetooth_limited_discoverable_state() != DPM_RESTRICTED) { +#endif if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0) - BT_ERR("Set vconf failed\n"); + BT_ERR("Set vconf failed"); +#ifdef TIZEN_DPM_ENABLE + } +#endif +#endif + if (timeout <= 0) return BLUETOOTH_ERROR_NONE; + result = _bt_service_set_alarm(visible_timer.timeout, + __bt_visibility_alarm_cb, NULL, &alarm_id); + if (result != BLUETOOTH_ERROR_NONE) + return BLUETOOTH_ERROR_INTERNAL; + visible_timer.alarm_id = alarm_id; /* Take start time */ time(&(visible_timer.start_time)); visible_timer.event_id = g_timeout_add_seconds(1, __bt_timeout_handler, NULL); - /* Set Alarm timer to switch off BT */ - result = alarmmgr_init("bt-service"); - if (result != 0) - return BLUETOOTH_ERROR_INTERNAL; - - result = alarmmgr_set_cb(__bt_visibility_alarm_cb, NULL); - if (result != 0) - return BLUETOOTH_ERROR_INTERNAL; - - __bt_visibility_alarm_create(); - return BLUETOOTH_ERROR_NONE; } -static void __bt_get_service_list(GValue *value, bluetooth_device_info_t *dev) +static void __bt_get_service_list(GVariant *value, bluetooth_device_info_t *dev) { - int i; - char **uuids; + int i = 0; char **parts; + GVariantIter *iter; + gchar *uuid = NULL; ret_if(value == NULL); ret_if(dev == NULL); - uuids = g_value_get_boxed(value); - ret_if(uuids == NULL); - dev->service_index = 0; - for (i = 0; uuids[i] != NULL; i++) { - g_strlcpy(dev->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX); - - parts = g_strsplit(uuids[i], "-", -1); + g_variant_get(value, "as", &iter); + while (g_variant_iter_loop(iter, "s", &uuid)) { + g_strlcpy(dev->uuids[i], uuid, BLUETOOTH_UUID_STRING_MAX); + parts = g_strsplit(uuid, "-", -1); - if (parts == NULL || parts[0] == NULL) + if (parts == NULL || parts[0] == NULL) { + g_free(uuid); break; + } dev->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16); g_strfreev(parts); dev->service_index++; + i++; } -} - -static bt_remote_dev_info_t *__bt_parse_remote_device_info( - DBusMessageIter *item_iter) -{ - DBusMessageIter value_iter; - bt_remote_dev_info_t *dev_info; - - dbus_message_iter_recurse(item_iter, &value_iter); - - if (dbus_message_iter_get_arg_type(&value_iter) != - DBUS_TYPE_DICT_ENTRY) { - BT_DBG("No entry"); - return NULL; - } - - dev_info = g_malloc0(sizeof(bt_remote_dev_info_t)); - - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *value = NULL; - char *key; - DBusMessageIter dict_entry; - DBusMessageIter iter_dict_val; - - dbus_message_iter_recurse(&value_iter, &dict_entry); - - dbus_message_iter_get_basic(&dict_entry, &key); - - if (key == NULL) { - dbus_message_iter_next(&value_iter); - continue; - } - - if (!dbus_message_iter_next(&dict_entry)) { - dbus_message_iter_next(&value_iter); - continue; - } - dbus_message_iter_recurse(&dict_entry, &iter_dict_val); - - if (strcasecmp(key, "Address") == 0) { - const char *address = NULL; - dbus_message_iter_get_basic(&iter_dict_val, - &address); - dev_info->address = g_strdup(address); - } else if (strcasecmp(key, "Class") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->class); - } else if (strcasecmp(key, "Name") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &value); - if (dev_info->name == NULL) - dev_info->name = g_strdup(value); - } else if (strcasecmp(key, "Connected") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->connected); - } else if (strcasecmp(key, "Paired") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->paired); - } else if (strcasecmp(key, "Trusted") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->trust); - } else if (strcasecmp(key, "RSSI") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->rssi); - } else if (strcasecmp(key, "UUIDs") == 0) { - DBusMessageIter uuid_iter; - DBusMessageIter tmp_iter; - int i = 0; - - dbus_message_iter_recurse(&iter_dict_val, - &uuid_iter); - tmp_iter = uuid_iter; - - /* Store the uuid count */ - while (dbus_message_iter_get_arg_type(&tmp_iter) != - DBUS_TYPE_INVALID) { - - dbus_message_iter_get_basic(&tmp_iter, - &value); - - dev_info->uuid_count++; - if (!dbus_message_iter_next(&tmp_iter)) - break; - } - - /* Store the uuids */ - if (dev_info->uuid_count > 0) { - dev_info->uuids = g_new0(char *, - dev_info->uuid_count + 1); - } else { - dbus_message_iter_next(&value_iter); - continue; - } - - while (dbus_message_iter_get_arg_type(&uuid_iter) != - DBUS_TYPE_INVALID) { - dbus_message_iter_get_basic(&uuid_iter, - &value); - dev_info->uuids[i] = g_strdup(value); - i++; - if (!dbus_message_iter_next(&uuid_iter)) { - break; - } - } - } - - dbus_message_iter_next(&value_iter); - } - - return dev_info; -} - -static void __bt_extract_remote_devinfo(DBusMessageIter *msg_iter, - GArray **dev_list) -{ - bt_remote_dev_info_t *dev_info = NULL; - char *object_path = NULL; - DBusMessageIter value_iter; - - /* Parse the signature: oa{sa{sv}}} */ - ret_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_OBJECT_PATH); - - dbus_message_iter_get_basic(msg_iter, &object_path); - ret_if(object_path == NULL); - - /* object array (oa) */ - ret_if(dbus_message_iter_next(msg_iter) == FALSE); - ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY); - - dbus_message_iter_recurse(msg_iter, &value_iter); - - /* string array (sa) */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; - - dbus_message_iter_recurse(&value_iter, &interface_iter); - - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING); - - dbus_message_iter_get_basic(&interface_iter, &interface_name); - - ret_if(dbus_message_iter_next(&interface_iter) == FALSE); - - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_ARRAY); - - if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) { - BT_DBG("Found a device: %s", object_path); - dev_info = __bt_parse_remote_device_info( - &interface_iter); - - if (dev_info) { - g_array_append_vals(*dev_list, dev_info, - sizeof(bt_remote_dev_info_t)); - } - } - - dbus_message_iter_next(&value_iter); - } -} - -int _bt_get_remote_found_devices(GArray **dev_list) -{ - DBusMessage *msg; - DBusMessage *reply; - DBusMessageIter reply_iter; - DBusMessageIter value_iter; - DBusError err; - DBusConnection *conn; - - conn = _bt_get_system_conn(); - retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - - msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH, - BT_MANAGER_INTERFACE, - "GetManagedObjects"); - - retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); - - /* Synchronous call */ - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block( - conn, msg, - -1, &err); - dbus_message_unref(msg); - - if (!reply) { - BT_ERR("Can't get managed objects"); - - if (dbus_error_is_set(&err)) { - BT_ERR("%s", err.message); - dbus_error_free(&err); - } - return BLUETOOTH_ERROR_INTERNAL; - } - - if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return BLUETOOTH_ERROR_INTERNAL; - } - - dbus_message_iter_recurse(&reply_iter, &value_iter); - - /* signature of GetManagedObjects: a{oa{sa{sv}}} */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter msg_iter; - - dbus_message_iter_recurse(&value_iter, &msg_iter); - - __bt_extract_remote_devinfo(&msg_iter, dev_list); - - dbus_message_iter_next(&value_iter); - } - - return BLUETOOTH_ERROR_NONE; + g_variant_iter_free(iter); } static int __bt_get_bonded_device_info(gchar *device_path, bluetooth_device_info_t *dev_info) { - GValue *value = { 0 }; - GError *err = NULL; - DBusGProxy *device_proxy; - const gchar *address; - const gchar *name; - unsigned int cod; - gint rssi; - gboolean trust; - gboolean paired; - gboolean connected; - GHashTable *hash = NULL; + GError *error = NULL; + GDBusProxy *device_proxy; + gchar *address = NULL; + gchar *name = NULL; + gchar *alias = NULL; + unsigned int cod = 0; + gint rssi = 0; + gboolean trust = FALSE; + gboolean paired = FALSE; + guchar connected = 0; + GByteArray *manufacturer_data = NULL; int ret; - DBusGConnection *conn; + GDBusConnection *conn; + GVariant *result; + GVariantIter *property_iter; + const gchar *key; + GVariant *value; + guint8 char_value; + GVariantIter *char_value_iter; BT_CHECK_PARAMETER(device_path, return); BT_CHECK_PARAMETER(dev_info, return); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, - device_path, BT_PROPERTIES_INTERFACE); + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, + BT_BLUEZ_NAME, + device_path, + BT_PROPERTIES_INTERFACE, + NULL, NULL); retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_g_proxy_call(device_proxy, "GetAll", &err, - G_TYPE_STRING, BT_DEVICE_INTERFACE, - G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), &hash, G_TYPE_INVALID); - - g_object_unref(device_proxy); - - if (err != NULL) { - BT_ERR("Error occured in Proxy call [%s]\n", err->message); - g_error_free(err); + result = g_dbus_proxy_call_sync(device_proxy, + "GetAll", + g_variant_new("(s)", BT_DEVICE_INTERFACE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + BT_ERR("Error occured in Proxy call"); + if (error != NULL) { + BT_ERR("Error occured in Proxy call (Error: %s)", error->message); + g_clear_error(&error); + } + g_object_unref(device_proxy); return BLUETOOTH_ERROR_INTERNAL; } - if (hash != NULL) { - value = g_hash_table_lookup(hash, "Paired"); - paired = g_value_get_boolean(value); - - value = g_hash_table_lookup(hash, "Address"); - address = value ? g_value_get_string(value) : NULL; - - value = g_hash_table_lookup(hash, "Alias"); - name = value ? g_value_get_string(value) : NULL; + g_object_unref(device_proxy); - if (name != NULL) - BT_DBG("Alias Name [%s]", name); - else { - value = g_hash_table_lookup(hash, "Name"); - name = value ? g_value_get_string(value) : NULL; + g_variant_get(result, "(a{sv})", &property_iter); + + while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) { + if (!g_strcmp0(key, "Paired")) { + paired = g_variant_get_boolean(value); + } else if (!g_strcmp0(key, "Address")) { + g_variant_get(value, "s", &address); + } else if (!g_strcmp0(key, "Alias")) { + g_variant_get(value, "s", &alias); + } else if (!g_strcmp0(key, "Name")) { + g_variant_get(value, "s", &name); + } else if (!g_strcmp0(key, "Class")) { + cod = g_variant_get_uint32(value); + } else if (!g_strcmp0(key, "Connected")) { + connected = g_variant_get_byte(value); + } else if (!g_strcmp0(key, "Trusted")) { + trust = g_variant_get_boolean(value); + } else if (!g_strcmp0(key, "RSSI")) { + rssi = g_variant_get_int16(value); + } else if (!g_strcmp0(key, "UUIDs")) { + __bt_get_service_list(value, dev_info); + } else if (!g_strcmp0(key, "LegacyManufacturerDataLen")) { + dev_info->manufacturer_data.data_len = g_variant_get_uint16(value); + } else if (!g_strcmp0(key, "LegacyManufacturerData")) { + manufacturer_data = g_byte_array_new(); + g_variant_get(value, "ay", &char_value_iter); + while (g_variant_iter_loop(char_value_iter, "y", &char_value)) + g_byte_array_append(manufacturer_data, &char_value, 1); + + g_variant_iter_free(char_value_iter); + + if (manufacturer_data) { + if (manufacturer_data->len > 0) { + memcpy(dev_info->manufacturer_data.data, manufacturer_data->data, + manufacturer_data->len); + } + } + g_byte_array_free(manufacturer_data, TRUE); } + } + g_variant_iter_free(property_iter); - value = g_hash_table_lookup(hash, "Class"); - cod = value ? g_value_get_uint(value) : 0; - - value = g_hash_table_lookup(hash, "Connected"); - connected = value ? g_value_get_boolean(value) : FALSE; - - value = g_hash_table_lookup(hash, "Trusted"); - trust = value ? g_value_get_boolean(value) : FALSE; - - if ((paired == FALSE) && (trust == FALSE)) { - return BLUETOOTH_ERROR_NOT_PAIRED; - } + BT_DBG("trust: %d, paired: %d", trust, paired); - value = g_hash_table_lookup(hash, "RSSI"); - rssi = value ? g_value_get_int(value) : 0; + g_variant_unref(result); - value = g_hash_table_lookup(hash, "UUIDs"); - __bt_get_service_list(value, dev_info); + if ((paired == FALSE) && (trust == FALSE)) { + g_free(address); + g_free(alias); + g_free(name); + return BLUETOOTH_ERROR_NOT_PAIRED; + } - _bt_convert_addr_string_to_type(dev_info->device_address.addr, - address); + _bt_convert_addr_string_to_type(dev_info->device_address.addr, + address); - _bt_divide_device_class(&dev_info->device_class, cod); + _bt_divide_device_class(&dev_info->device_class, cod); - g_strlcpy(dev_info->device_name.name, name, - BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1); + g_strlcpy(dev_info->device_name.name, alias ? alias : name, + BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1); - dev_info->rssi = rssi; - dev_info->trust = trust; - dev_info->paired = paired; - dev_info->connected = connected; - g_hash_table_destroy(hash); - ret = BLUETOOTH_ERROR_NONE; - } else { - BT_ERR("Hash is NULL\n"); - ret = BLUETOOTH_ERROR_INTERNAL; - } + dev_info->rssi = rssi; + dev_info->trust = trust; + dev_info->paired = paired; + dev_info->connected = connected; + ret = BLUETOOTH_ERROR_NONE; + g_free(address); + g_free(alias); + g_free(name); return ret; } @@ -527,79 +426,43 @@ gboolean _bt_get_cancel_by_user(void) return cancel_by_user; } -static void __bt_flight_mode_cb(keynode_t *node, void *data) +void _bt_adapter_set_status(bt_status_t status) { - gboolean flight_mode = FALSE; - int bt_status; - - BT_DBG("key=%s\n", vconf_keynode_get_name(node)); - - bt_status = _bt_adapter_get_status(); - - if (vconf_keynode_get_type(node) == VCONF_TYPE_BOOL) { - flight_mode = vconf_keynode_get_bool(node); - - BT_DBG("value=%d\n", flight_mode); - - if (flight_mode == TRUE) { - BT_DBG("Deactivate Bluetooth Service\n"); - if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0) - BT_DBG("Set vconf failed+\n"); - - if (bt_status == BT_ACTIVATED) - _bt_disable_adapter(); - } else { - - int value = 0; - - if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &value)) - BT_ERR("Fail get flight mode value"); - - if (value == 0) - return; - - BT_DBG("Activate Bluetooth Service\n"); - if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0)) - BT_DBG("Set vconf failed\n"); - - if (bt_status == BT_DEACTIVATED) - _bt_enable_adapter(); - } - } + BT_INFO("adapter_status changed [%d] -> [%d]", adapter_status, status); + adapter_status = status; } -#ifdef __TIZEN_MOBILE__ -static void __launch_bt_service(int status, int run_type) +bt_status_t _bt_adapter_get_status(void) { - bundle *kb; - char status_val[5] = { 0, }; - char run_type_val[5] = { 0, }; - - snprintf(status_val, sizeof(status_val), "%d", status); - snprintf(run_type_val, sizeof(run_type_val), "%d", run_type); - - BT_DBG("status: %s, run_type: %s", status_val, run_type_val); + return adapter_status; +} - kb = bundle_create(); +void _bt_adapter_set_le_status(bt_le_status_t status) +{ + BT_INFO("adapter_le_status changed [%d] -> [%d]", adapter_le_status, status); + adapter_le_status = status; +} - bundle_add(kb, "launch-type", "setstate"); - bundle_add(kb, "status", status_val); - bundle_add(kb, "run-type", run_type_val); +bt_le_status_t _bt_adapter_get_le_status(void) +{ + return adapter_le_status; +} - aul_launch_app("com.samsung.bluetooth", kb); - bundle_free(kb); +void _bt_set_le_intended_status(gboolean value) +{ + is_le_intended = value; } -#endif -void _bt_adapter_set_status(bt_status_t status) +static void __bt_set_in_poweroff(void) { - adapter_status = status; + BT_INFO("Set in_power_off to TRUE"); + in_power_off = TRUE; } -bt_status_t _bt_adapter_get_status(void) +static gboolean __bt_is_in_poweroff(void) { - return adapter_status; + return in_power_off; } static void __bt_phone_name_changed_cb(keynode_t *node, void *data) @@ -612,365 +475,1358 @@ static void __bt_phone_name_changed_cb(keynode_t *node, void *data) if (vconf_keynode_get_type(node) == VCONF_TYPE_STRING) { phone_name = vconf_keynode_get_str(node); + if (phone_name && strlen(phone_name) != 0) { - if (!g_utf8_validate(phone_name, -1, + if (!g_utf8_validate(phone_name, -1, (const char **)&ptr)) - *ptr = '\0'; + *ptr = '\0'; + BT_INFO("device_name is changed to %s", phone_name); _bt_set_local_name(phone_name); + } else { + BT_ERR("phone_name is NOT valid"); } - } -} - -static void __bt_set_visible_mode(void) -{ - int timeout; - - if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0) - BT_ERR("Fail to get the timeout value"); - - /* -1: Always on */ - if (timeout == -1) { - if (_bt_set_discoverable_mode( - BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE, - timeout) != BLUETOOTH_ERROR_NONE) { - if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) - BT_ERR("Set vconf failed"); - } + } else { + BT_ERR("vconf type is NOT string"); } } static void __bt_set_local_name(void) { + bluetooth_device_name_t local_name; char *phone_name = NULL; char *ptr = NULL; + char *temp = NULL; - phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR); + if (_bt_get_local_name(&local_name) != BLUETOOTH_ERROR_NONE || + (temp = strstr(local_name.name, "BlueZ")) != NULL) { + phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR); - if (!phone_name) - return; + if (!phone_name) + return; - if (strlen(phone_name) != 0) { - if (!g_utf8_validate(phone_name, -1, (const char **)&ptr)) - *ptr = '\0'; - _bt_set_local_name(phone_name); + if (strlen(phone_name) != 0) { + if (!g_utf8_validate(phone_name, -1, (const char **)&ptr)) + *ptr = '\0'; + + _bt_set_local_name(phone_name); + } + free(phone_name); } - free(phone_name); } -void _bt_set_enabled(void) +static int __bt_set_enabled(void) { + int adapter_status = BT_ADAPTER_DISABLED; int result = BLUETOOTH_ERROR_NONE; - _bt_adapter_set_status(BT_ACTIVATED); - - // register agent if it was not previously done. - if (!adapter_agent) { - BT_DBG(""); - _bt_handle_adapter_added(); + if (timer_id > 0) { + BT_DBG("g_source is removed"); + g_source_remove(timer_id); + timer_id = 0; } - __bt_set_visible_mode(); + _bt_check_adapter(&adapter_status); - __bt_set_local_name(); + if (adapter_status == BT_ADAPTER_DISABLED) { + BT_ERR("Bluetoothd is not running"); + return BLUETOOTH_ERROR_INTERNAL; + } - /* Update Bluetooth Status to notify other modules */ - if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0) +#ifdef TIZEN_PROFILE_MOBILE || defined(TIZEN_PROFILE_IVI) + /* BT setting UI will control Mobile's visible mode. So in the FRWK...set the visible mode as off: */ + if (_bt_set_discoverable_mode( + BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0) != BLUETOOTH_ERROR_NONE) + BT_ERR("Set connectable mode failed"); +#else +#ifdef TIZEN_TV + if (_bt_set_discoverable_mode( + BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE, 0) != BLUETOOTH_ERROR_NONE) + BT_ERR("Fail to set discoverable mode"); +#endif +#endif + + /* Update Bluetooth Status to notify other modules */ + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0) BT_ERR("Set vconf failed\n"); if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0) BT_ERR("Set vconf failed\n"); + if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE, + EVT_VAL_BT_ON) != ES_R_OK) + BT_ERR("Fail to set value"); + /* Send enabled event to API */ _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED, - DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + g_variant_new("(i)", result)); + +#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT + _bt_audio_start_auto_connect(FALSE); +#endif + + __bt_set_local_name(); + _bt_set_discovery_status(FALSE); + + return BLUETOOTH_ERROR_NONE; } -void _bt_set_disabled(void) +void _bt_set_disabled(int result) { - int result = BLUETOOTH_ERROR_NONE; + int power_off_status = 0; + int ret; + int ret_pm_ignore; + int pm_ignore_mode = 0; + + ret = vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &power_off_status); + BT_DBG("ret : %d, power_off_status : %d", ret, power_off_status); + + ret_pm_ignore = vconf_get_int(VCONFKEY_PM_KEY_IGNORE, &pm_ignore_mode); + + /* Update the vconf BT status in normal Deactivation case only */ + if (ret == 0 && power_off_status == VCONFKEY_SYSMAN_POWER_OFF_NONE && + ret_pm_ignore == 0 && pm_ignore_mode != VCONFKEY_PM_KEY_LOCK) { + + BT_DBG("Update vconf for BT normal Deactivation"); + + if (result == BLUETOOTH_ERROR_TIMEOUT) + if (vconf_set_int(BT_OFF_DUE_TO_TIMEOUT, 1) != 0) + BT_ERR("Set vconf failed"); + + /* Update Bluetooth Status to notify other modules */ + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0) + BT_ERR("Set vconf failed"); + if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE, + EVT_VAL_BT_OFF) != ES_R_OK) + BT_ERR("Fail to set value"); + } + + if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0) + BT_ERR("Set vconf failed\n"); + + _bt_cancel_queued_transfers(); _bt_adapter_set_status(BT_DEACTIVATED); + _bt_set_discovery_status(FALSE); + +#ifndef USB_BLUETOOTH + if (_bt_adapter_get_le_status() != BT_LE_DEACTIVATED) { +#endif + /* Send disabled event */ + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED, + g_variant_new("(i)", result)); +#ifndef USB_BLUETOOTH + } +#endif + + BT_INFO("Adapter disabled"); +} + +static int __bt_set_le_enabled(void) +{ + BT_DBG("+"); + int result = BLUETOOTH_ERROR_NONE; + bt_status_t status; /* Update Bluetooth Status to notify other modules */ - if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0) - BT_ERR("Set vconf failed\n"); + if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_ON) != 0) + BT_ERR("Set vconf failed"); - if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0) + /* set packet length to max size to enable packet length extension */ + if (BLUETOOTH_ERROR_NONE != _bt_le_set_max_packet_len()) + BT_ERR("Fail to set max packet length"); + + if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE, + EVT_VAL_BT_LE_ON) != ES_R_OK) + BT_ERR("Fail to set value"); + + /* Send enabled event to API */ + /* + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED, + DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + */ + status = _bt_adapter_get_status(); + if (status == BT_DEACTIVATED) { + BT_INFO("BREDR is off, turn off PSCAN"); + _bt_set_connectable(FALSE); + } + if (le_timer_id > 0) { + g_source_remove(le_timer_id); + le_timer_id = 0; + } + + /* Send enabled event to API */ + _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_LE_ENABLED, + g_variant_new("(i)", result)); + + __bt_set_local_name(); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +void _bt_set_le_disabled(int result) +{ + int power_off_status; + int ret; + + ret = vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &power_off_status); + BT_DBG("ret : %d", ret); + BT_DBG("power_off_status : %d", power_off_status); + + /* Update Bluetooth Status to notify other modules */ + BT_DBG("Update vconf for BT LE normal Deactivation"); + if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0) BT_ERR("Set vconf failed\n"); + _bt_adapter_set_le_status(BT_LE_DEACTIVATED); + + if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE, + EVT_VAL_BT_LE_OFF) != ES_R_OK) + BT_ERR("Fail to set value"); /* Send disabled event */ - _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED, - DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_LE_DISABLED, + g_variant_new("(i)", result)); +} + +void *_bt_get_adapter_agent(void) +{ + return adapter_agent; +} + +int _bt_enable_core(void) +{ + GDBusProxy *proxy; + GVariant *result; + GError *error = NULL; + + proxy = __bt_get_core_proxy(); + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); + + /* Clean up the process */ + result = g_dbus_proxy_call_sync(proxy, + "EnableCore", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Bt core call failed(Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Bt core call failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_unref(result); + return BLUETOOTH_ERROR_NONE; +} + +#if defined(TIZEN_FEATURE_FLIGHTMODE_ENABLED) || (!defined(TIZEN_PROFILE_WEARABLE)) +static void __bt_service_flight_ps_mode_cb(keynode_t *node, void *data) +{ + gboolean flight_mode = FALSE; + int power_saving_mode = 0; + int type; + + DBG_SECURE("key=%s", vconf_keynode_get_name(node)); + type = vconf_keynode_get_type(node); + if (type == VCONF_TYPE_BOOL) { + flight_mode = vconf_keynode_get_bool(node); + if (flight_mode != TRUE) { + BT_ERR("Ignore the event"); + return; + } + } else if (type == VCONF_TYPE_INT) { + power_saving_mode = vconf_keynode_get_int(node); + if (power_saving_mode != 2) { + BT_ERR("Ignore the event"); + return; + } + } else { + BT_ERR("Invaild vconf key type : %d", type); + return; + } + + _bt_enable_core(); +} +#endif + +static void __bt_poweroff_event_filter(GDBusConnection *connection, + const gchar *sender_name, const gchar *object_path, + const gchar *interface_name, const gchar *signal_name, + GVariant *parameters, gpointer user_data) +{ + int state = 0; + + g_variant_get(parameters, "(i)", &state); + + if (state != BT_DEVICED_POWEROFF_SIGNAL_POWEROFF && + state != BT_DEVICED_POWEROFF_SIGNAL_REBOOT) { + BT_DBG("Not interested event : %d", state); + return; + } + + if (_bt_adapter_get_status() == BT_ACTIVATING) { + BT_INFO("Just update VCONFKEY_BT_STATUS in Power off"); + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON)) + BT_ERR("Set VCONFKEY_BT_STATUS failed"); + } else { + __bt_set_in_poweroff(); + } +} + +void _bt_service_register_poweroff_event(void) +{ + if (poweroff_subscribe_id) + return; + + poweroff_subscribe_id = g_dbus_connection_signal_subscribe( + _bt_gdbus_get_system_gconn(), NULL, + BT_DEVICED_POWEROFF_INTERFACE, + BT_DEVICED_POWEROFF_SIGNAL, + BT_DEVICED_POWEROFF_OBJECT_PATH, + NULL, 0, __bt_poweroff_event_filter, NULL, NULL); +} + +void _bt_service_unregister_poweroff_event(void) +{ + if (poweroff_subscribe_id == 0) + return; + + g_dbus_connection_signal_unsubscribe(_bt_gdbus_get_system_gconn(), + poweroff_subscribe_id); + poweroff_subscribe_id = 0; +} + +void _bt_service_register_vconf_handler(void) +{ + BT_DBG("+"); + +#ifdef TIZEN_FEATURE_FLIGHTMODE_ENABLED + if (vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb, NULL) < 0) + BT_ERR("Unable to register key handler"); +#else + BT_DBG("Telephony is disabled"); +#endif + +#ifndef TIZEN_PROFILE_WEARABLE + if (vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb, NULL) < 0) + BT_ERR("Unable to register key handler"); +#endif +} + +void _bt_service_unregister_vconf_handler(void) +{ + BT_DBG("+"); + +#ifdef TIZEN_FEATURE_FLIGHTMODE_ENABLED + vconf_ignore_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb); +#endif + +#ifndef TIZEN_PROFILE_WEARABLE + vconf_ignore_key_changed(VCONFKEY_SETAPPL_PSMODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb); +#endif +} + +static void __bt_state_event_handler(const char *event_name, bundle *data, void *user_data) +{ + const char *bt_status = NULL; + const char *bt_le_status = NULL; + BT_DBG("bt state set event(%s) received", event_name); + + bt_status = bundle_get_val(data, EVT_KEY_BT_STATE); + BT_DBG("bt_state: (%s)", bt_status); + + bt_le_status = bundle_get_val(data, EVT_KEY_BT_LE_STATE); + BT_DBG("bt_state: (%s)", bt_le_status); +} + +void _bt_handle_adapter_added(void) +{ + BT_DBG("+"); + bt_status_t status; + bt_le_status_t le_status; + int ret; +/* + if (timer_id > 0) { + BT_DBG("g_source is removed"); + g_source_remove(timer_id); + timer_id = 0; + } +*/ + + status = _bt_adapter_get_status(); + le_status = _bt_adapter_get_le_status(); + BT_INFO("status : %d", status); + BT_INFO("le_status : %d", le_status); + +#ifndef USB_BLUETOOTH + adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE); + if (!adapter_agent) { + BT_ERR("Fail to register agent"); + return; + } +#else + if (adapter_agent == NULL) { + adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE); + if (!adapter_agent) { + BT_ERR("Fail to register agent"); + return; + } + } +#endif + + if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE) + BT_ERR("Fail to register media player"); + + if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE) + BT_ERR("Fail to init obex server"); + +#ifdef TIZEN_BT_PAN_NAP_ENABLED + if (_bt_network_activate() != BLUETOOTH_ERROR_NONE) + BT_ERR("Fail to activate network"); +#endif + + /* add the vconf noti handler */ + ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, + __bt_phone_name_changed_cb, NULL); + if (ret < 0) + BT_ERR("Unable to register key handler"); + + if (le_status == BT_LE_ACTIVATING || + status == BT_ACTIVATING) { + __bt_set_le_enabled(); + _bt_adapter_set_le_status(BT_LE_ACTIVATED); + } + + if (status == BT_ACTIVATING) { + __bt_set_enabled(); + _bt_adapter_set_status(BT_ACTIVATED); + } + + /* eventsystem */ + if (eventsystem_register_event(SYS_EVENT_BT_STATE, &status_reg_id, + (eventsystem_handler)__bt_state_event_handler, NULL) != ES_R_OK) { + BT_ERR("Fail to register system event"); + } +} + +void _bt_handle_adapter_removed(void) +{ + int ret; + + _bt_adapter_set_status(BT_DEACTIVATED); + + __bt_visibility_alarm_remove(); + + if (alarm_mgr.is_alarm_initialized == TRUE) { + alarmmgr_fini(); + alarm_mgr.is_alarm_initialized = FALSE; + g_list_free_full(alarm_mgr.g_alarm_list, alarm_data_free); + alarm_mgr.g_alarm_list = NULL; + } + +#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT + _bt_audio_stop_auto_connect(); +#endif + + ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, + (vconf_callback_fn)__bt_phone_name_changed_cb); + if (0 != ret) + ERR("vconf_ignore_key_changed failed\n"); + +#ifndef USB_BLUETOOTH + _bt_destroy_agent(adapter_agent); + adapter_agent = NULL; + + if (is_recovery_mode == TRUE) { + /* Send disabled event */ + _bt_set_disabled(BLUETOOTH_ERROR_NONE); + + /* Will recover BT by bt-core, so set the mode as activating */ + _bt_adapter_set_status(BT_ACTIVATING); + is_recovery_mode = FALSE; + } else { + _bt_reliable_terminate_service(NULL); + } +#else + _bt_set_disabled(BLUETOOTH_ERROR_NONE); +#endif + + if (eventsystem_unregister_event(status_reg_id) != ES_R_OK) + BT_ERR("Fail to unregister system event"); +} + +static gboolean __bt_enable_timeout_cb(gpointer user_data) +{ + GDBusProxy *proxy; + GVariant *result; + GError *error = NULL; + + timer_id = 0; + + retv_if(_bt_adapter_get_status() == BT_ACTIVATED, FALSE); + + BT_ERR("EnableAdapter is failed"); + + proxy = __bt_get_core_proxy(); + if (!proxy) + return FALSE; + + /* Clean up the process */ + result = g_dbus_proxy_call_sync(proxy, + "DisableAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Bt core call failed(Error: %s)", error->message); + g_clear_error(&error); + } else { + BT_ERR("Bt core call failed"); + } + return FALSE; + } + + g_variant_unref(result); + _bt_set_disabled(BLUETOOTH_ERROR_TIMEOUT); + +#ifndef USB_BLUETOOTH + _bt_terminate_service(NULL); +#endif + + return FALSE; +} + +static gboolean __bt_enable_le_timeout_cb(gpointer user_data) +{ + GDBusProxy *proxy; + GVariant *result; + GError *error = NULL; + + le_timer_id = 0; + + retv_if(_bt_adapter_get_le_status() == BT_LE_ACTIVATED, FALSE); + + BT_ERR("EnableAdapterLE is failed"); + + proxy = __bt_get_core_proxy(); + if (!proxy) + return FALSE; + + /* Clean up the process */ + result = g_dbus_proxy_call_sync(proxy, + "DisableAdapterLe", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Bt core call failed(Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Bt core call failed"); + return FALSE; + } + + g_variant_unref(result); + _bt_adapter_set_le_status(BT_LE_DEACTIVATED); + + _bt_set_le_disabled(BLUETOOTH_ERROR_TIMEOUT); + + if (_bt_adapter_get_status() == BT_DEACTIVATED) + _bt_terminate_service(NULL); + + return FALSE; +} + +void _bt_adapter_start_le_enable_timer(void) +{ + if (le_timer_id > 0) { + g_source_remove(le_timer_id); + le_timer_id = 0; + } + + le_timer_id = g_timeout_add(BT_ENABLE_TIMEOUT, + __bt_enable_le_timeout_cb, NULL); + + return; +} + +void _bt_adapter_start_enable_timer(void) +{ + if (timer_id > 0) { + g_source_remove(timer_id); + timer_id = 0; + } + + timer_id = g_timeout_add(BT_ENABLE_TIMEOUT, + __bt_enable_timeout_cb, NULL); + + return; +} + +#ifdef TIZEN_TV +static gboolean __bt_adapter_enabled_cb(gpointer user_data) +{ + BT_DBG("+"); + + __bt_set_enabled(); + _bt_adapter_set_status(BT_ACTIVATED); + + return FALSE; +} +#endif + +int _bt_enable_adapter_check_status(void) +{ + bt_status_t status = _bt_adapter_get_status(); + bt_le_status_t le_status = _bt_adapter_get_le_status(); + + BT_DBG(""); + + if (status == BT_ACTIVATING) { + BT_ERR("Enabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (status == BT_ACTIVATED) { + BT_ERR("Already enabled"); + return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + } + + if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) { + BT_ERR("Disabling in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_enable_adapter(void) +{ + GDBusProxy *proxy; + GError *error = NULL; + int ret; + GVariant *result = NULL; + bt_status_t status = _bt_adapter_get_status(); + bt_le_status_t le_status = _bt_adapter_get_le_status(); + + BT_DBG(""); + + if (status == BT_ACTIVATING) { + BT_ERR("Enabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (status == BT_ACTIVATED) { + BT_ERR("Already enabled"); + return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + } + + if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) { + BT_ERR("Disabling in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; + } + + _bt_adapter_set_status(BT_ACTIVATING); + +#ifdef TIZEN_TV +{ + int adapter_status = BT_ADAPTER_DISABLED; + + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0) + BT_ERR("Set vconf failed"); + + _bt_check_adapter(&adapter_status); + if (adapter_status == BT_ADAPTER_ENABLED) { + g_idle_add(__bt_adapter_enabled_cb, NULL); + _bt_adapter_start_enable_timer(); + return BLUETOOTH_ERROR_NONE; + } +} +#endif + + if (__bt_is_in_poweroff() == TRUE) { + BT_INFO("Just update VCONFKEY_BT_STATUS in Power off"); + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0) + BT_ERR("Set VCONFKEY_BT_STATUS failed"); + return BLUETOOTH_ERROR_NONE; + } + + proxy = __bt_get_core_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; + + if (le_status == BT_LE_ACTIVATED) { + BT_INFO("LE Already enabled. Just turn on PSCAN"); + ret = _bt_set_connectable(TRUE); + if (ret == BLUETOOTH_ERROR_NONE) + _bt_adapter_set_status(BT_ACTIVATED); + else + return BLUETOOTH_ERROR_INTERNAL; + } + + result = g_dbus_proxy_call_sync(proxy, "EnableAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT, + NULL, &error); + if (error) { + BT_ERR("EnableAdapterLe failed: %s", error->message); + _bt_adapter_set_status(BT_DEACTIVATED); + g_clear_error(&error); + error = NULL; + result = g_dbus_proxy_call_sync(proxy, + "DisableAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (error != NULL) { + BT_ERR("Bt core call failed(Error: %s)", error->message); + g_clear_error(&error); + } + g_variant_unref(result); +#ifndef USB_BLUETOOTH + /* Terminate myself */ + g_idle_add((GSourceFunc)_bt_terminate_service, NULL); +#endif + return BLUETOOTH_ERROR_INTERNAL; + } + g_variant_unref(result); + if (le_status == BT_LE_ACTIVATED) + __bt_set_enabled(); + else + _bt_adapter_start_enable_timer(); + + return BLUETOOTH_ERROR_NONE; } -void *_bt_get_adapter_agent(void) -{ - return adapter_agent; -} +static gboolean __bt_disconnect_all(void) +{ + int i; + GDBusConnection *conn; + GDBusProxy *dev_proxy; + gboolean ret = FALSE; + GVariant *result; + GError *error = NULL; + GArray *device_list; + bluetooth_device_info_t info; + guint size; + char *device_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + + BT_DBG(""); + + conn = _bt_gdbus_get_system_gconn(); + + device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); + + if (_bt_get_bonded_devices(&device_list) + != BLUETOOTH_ERROR_NONE) { + g_array_free(device_list, TRUE); + return FALSE; + } + + size = (device_list->len) / sizeof(bluetooth_device_info_t); + + for (i = 0; i < size; i++) { + + info = g_array_index(device_list, + bluetooth_device_info_t, i); + + if (info.connected != BLUETOOTH_CONNECTED_LINK_NONE) { + BT_DBG("Found Connected device"); + _bt_convert_addr_type_to_string(address, info.device_address.addr); + device_path = _bt_get_device_object_path(address); + if (device_path == NULL) + continue; + + BT_DBG("Disconnecting : %s", device_path); + + dev_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, + BT_BLUEZ_NAME, + device_path, + BT_DEVICE_INTERFACE, + NULL, NULL); + + if (dev_proxy == NULL) + continue; + + result = g_dbus_proxy_call_sync(dev_proxy, + "Disconnect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Disconnect call failed(Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Disconnect call failed"); + g_object_unref(dev_proxy); + return FALSE; + } + + g_variant_unref(result); + g_object_unref(dev_proxy); + } + } + ret = TRUE; + g_array_free(device_list, TRUE); + + return ret; +} + +#if 0 +static gboolean __bt_set_disabled_timeout_cb(gpointer user_data) +{ + BT_DBG(""); + _bt_set_disabled(BLUETOOTH_ERROR_NONE); + + return FALSE; +} +#endif + +int _bt_disable_cb(void) +{ + FN_START; + GDBusProxy *proxy; +#if 0 + int ret; +#endif + GVariant *result; + GError *error = NULL; + + _bt_adapter_set_status(BT_DEACTIVATING); +#if 0 + bt_le_status_t le_status; + le_status = _bt_adapter_get_le_status(); + BT_DBG("le_status : %d", le_status); + if (le_status == BT_LE_ACTIVATED) { + BT_INFO("LE is enabled. Just turn off PSCAN"); + + if (_bt_is_discovering()) + _bt_cancel_discovery(); + + if (_bt_is_connectable() == FALSE) { + g_timeout_add(100, (GSourceFunc)__bt_set_disabled_timeout_cb, NULL); + } else { + ret = _bt_set_connectable(FALSE); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_set_connectable fail!"); + _bt_adapter_set_status(BT_ACTIVATED); + return BLUETOOTH_ERROR_INTERNAL; + } + } + } +#endif + proxy = __bt_get_core_proxy(); + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(proxy, + "DisableAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to DisableAdapter (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to DisableAdapter"); + _bt_adapter_set_status(BT_ACTIVATED); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_unref(result); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_disable_adapter_check_status(void) +{ + bt_status_t status = _bt_adapter_get_status(); + + BT_DBG(""); + + if (status == BT_DEACTIVATING) { + BT_DBG("Disabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (status == BT_DEACTIVATED) { + BT_DBG("Already disabled"); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_disable_adapter(void) +{ + BT_DBG("+"); + int ret; + + if (_bt_adapter_get_status() == BT_DEACTIVATING) { + BT_DBG("Disabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (_bt_adapter_get_status() == BT_DEACTIVATED) { + BT_DBG("Already disabled"); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + if (timer_id > 0) { + g_source_remove(timer_id); + timer_id = 0; + } + + __bt_disconnect_all(); + ret = _bt_disable_cb(); + + BT_DBG("-"); + return ret; +} + +int _bt_recover_adapter(void) +{ + BT_DBG("+"); + GDBusProxy *proxy; + GVariant *result; + GError *error = NULL; + + if (_bt_adapter_get_status() == BT_DEACTIVATING) { + BT_ERR("Disabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (_bt_adapter_get_status() == BT_DEACTIVATED) { + BT_ERR("Already disabled"); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + _bt_adapter_set_status(BT_DEACTIVATING); + + proxy = __bt_get_core_proxy(); + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(proxy, + "RecoverAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to RecoverAdapter (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to RecoverAdapter"); + return BLUETOOTH_ERROR_INTERNAL; + } + + is_recovery_mode = TRUE; + + g_variant_unref(result); + __bt_disconnect_all(); -void _bt_handle_flight_mode_noti(void) -{ - BT_DBG("+"); - vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, - __bt_flight_mode_cb, NULL); BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; } -void _bt_handle_adapter_added(void) +int _bt_reset_adapter(void) { + GDBusProxy *proxy; + GVariant *result; + GError *error = NULL; + BT_DBG(""); - adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE); - if (!adapter_agent) { - BT_ERR("Fail to register agent"); - return; + proxy = __bt_get_core_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; + + result = g_dbus_proxy_call_sync(proxy, + "ResetAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to ResetAdapter (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to ResetAdapter"); + return BLUETOOTH_ERROR_INTERNAL; } -#ifdef __TIZEN_MOBILE__ - if (!aul_app_is_running("com.samsung.bluetooth")) - __launch_bt_service(0, 0); + g_variant_unref(result); + /* Terminate myself */ + if (_bt_adapter_get_status() == BT_DEACTIVATED) + g_idle_add((GSourceFunc)_bt_terminate_service, NULL); - if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE) - BT_ERR("Fail to register media player"); -#endif + return BLUETOOTH_ERROR_NONE; +} - if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE) - BT_ERR("Fail to init obex server"); -/* - if (_bt_network_activate() != BLUETOOTH_ERROR_NONE) - BT_ERR("Fail to activate network"); -*/ +#ifndef TIZEN_TV +int _bt_check_adapter(int *status) +{ - /* add the vconf noti handler */ - vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, - __bt_phone_name_changed_cb, NULL); + char *adapter_path = NULL; - vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, - __bt_flight_mode_cb, NULL); -} + BT_CHECK_PARAMETER(status, return); -void _bt_handle_adapter_removed(void) -{ - BT_DBG(""); + *status = BT_ADAPTER_DISABLED; - vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, - (vconf_callback_fn)__bt_phone_name_changed_cb); + adapter_path = _bt_get_adapter_path(); - _bt_destroy_agent(adapter_agent); - adapter_agent = NULL; - _bt_terminate_service(NULL); -} + if (adapter_path != NULL) + *status = BT_ADAPTER_ENABLED; -DBusGProxy *_bt_init_core_proxy(void) + g_free(adapter_path); + return BLUETOOTH_ERROR_NONE; +} +#else +int _bt_check_adapter(int *status) { - DBusGProxy *proxy; - DBusGConnection *conn; + GDBusProxy *proxy; + GError *error = NULL; + GVariant *result; + GVariant *temp; + gboolean powered = FALSE; - conn = _bt_get_system_gconn(); - if (!conn) - return NULL; + BT_CHECK_PARAMETER(status, return); - proxy = dbus_g_proxy_new_for_name(conn, BT_CORE_NAME, - BT_CORE_PATH, BT_CORE_INTERFACE); - if (!proxy) - return NULL; + *status = BT_ADAPTER_DISABLED; - core_proxy = proxy; + proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - return proxy; -} + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "Powered"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + BT_ERR("Failed to get local address"); + if (error != NULL) { + BT_ERR("Failed to get local address (Error: %s)", error->message); + g_clear_error(&error); + } + return BLUETOOTH_ERROR_INTERNAL; + } -static DBusGProxy *__bt_get_core_proxy(void) -{ - return (core_proxy) ? core_proxy : _bt_init_core_proxy(); + g_variant_get(result, "(v)", &temp); + powered = g_variant_get_boolean(temp); + BT_DBG("powered: %d", powered); + + if (powered) + *status = BT_ADAPTER_ENABLED; + + g_variant_unref(result); + g_variant_unref(temp); + return BLUETOOTH_ERROR_NONE; } +#endif -int _bt_enable_adapter(void) +int _bt_enable_adapter_le(void) { - DBusGProxy *proxy; - GError *err = NULL; + BT_DBG("+"); + GDBusProxy *proxy; + GError *error = NULL; + bt_status_t status = _bt_adapter_get_status(); + bt_le_status_t le_status = _bt_adapter_get_le_status(); + GVariant *result; - BT_DBG(""); + if (le_status == BT_LE_ACTIVATING) { + BT_ERR("Enabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } - if (_bt_adapter_get_status() == BT_ACTIVATING) { - BT_DBG("Enabling in progress"); - return BLUETOOTH_ERROR_IN_PROGRESS; + if (le_status == BT_LE_ACTIVATED) { + BT_ERR("Already enabled"); + return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; } - if (_bt_adapter_get_status() == BT_ACTIVATED) { - BT_DBG("Already enabled"); - return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) { + BT_ERR("Disabling in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; } - _bt_adapter_set_status(BT_ACTIVATING); + _bt_adapter_set_le_status(BT_LE_ACTIVATING); proxy = __bt_get_core_proxy(); - if (!proxy) - return BLUETOOTH_ERROR_INTERNAL; - - if (dbus_g_proxy_call_with_timeout(proxy, "EnableAdapter", - BT_ENABLE_TIMEOUT, &err, - G_TYPE_INVALID, - G_TYPE_INVALID) == FALSE) { - - _bt_adapter_set_status(BT_DEACTIVATED); + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); - if (err != NULL) { - BT_ERR("Bt core call failed: [%s]", err->message); - g_error_free(err); - } + result = g_dbus_proxy_call_sync(proxy, "EnableAdapterLe", + NULL, + G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT, + NULL, &error); + if (error) { + BT_ERR("EnableAdapterLe failed: %s", error->message); + _bt_adapter_set_le_status(BT_DEACTIVATED); + g_clear_error(&error); /* Clean up the process */ - if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL, - G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + result = g_dbus_proxy_call_sync(proxy, + "DisableAdapterLe", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { BT_ERR("Bt core call failed"); + if (error) { + BT_ERR("EnableAdapterLE Failed %s", error->message); + g_clear_error(&error); + } } - - /* Display notification */ - notification_status_message_post(BT_STR_NOT_SUPPORT); - + g_variant_unref(result); /* Terminate myself */ - g_idle_add((GSourceFunc)_bt_terminate_service, NULL); + if (_bt_adapter_get_status() == BT_DEACTIVATED) + g_idle_add((GSourceFunc)_bt_terminate_service, NULL); return BLUETOOTH_ERROR_INTERNAL; } + if (result) + g_variant_unref(result); + + _bt_adapter_start_le_enable_timer(); + + if (status == BT_ACTIVATED) { + _bt_adapter_set_le_status(BT_LE_ACTIVATED); + __bt_set_le_enabled(); + } + BT_DBG("le status : %d", _bt_adapter_get_le_status()); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } -int _bt_disable_adapter(void) +int _bt_disable_adapter_le(void) { - DBusGProxy *proxy; - - BT_DBG(""); + BT_DBG("+"); + GDBusProxy *proxy; + bt_le_status_t bt_le_state; + GVariant *result; + GError *error = NULL; - if (_bt_adapter_get_status() == BT_DEACTIVATING) { - BT_DBG("Disabling in progress"); - return BLUETOOTH_ERROR_IN_PROGRESS; + bt_le_state = _bt_adapter_get_le_status(); + if (bt_le_state == BT_LE_DEACTIVATING) { + BT_DBG("Disabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; } - if (_bt_adapter_get_status() == BT_DEACTIVATED) { - BT_DBG("Already disabled"); - return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + if (bt_le_state == BT_LE_DEACTIVATED) { + BT_DBG("Already disabled"); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; } - _bt_adapter_set_status(BT_DEACTIVATING); + _bt_adapter_set_le_status(BT_LE_DEACTIVATING); proxy = __bt_get_core_proxy(); if (!proxy) return BLUETOOTH_ERROR_INTERNAL; - if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL, - G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { - BT_ERR("Bt core call failed"); - _bt_adapter_set_status(BT_ACTIVATED); + result = g_dbus_proxy_call_sync(proxy, + "DisableAdapterLe", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Bt core call failed (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Bt core call failed"); + _bt_adapter_set_le_status(BT_LE_ACTIVATED); return BLUETOOTH_ERROR_INTERNAL; } + g_variant_unref(result); + _bt_set_le_disabled(BLUETOOTH_ERROR_NONE); + BT_DBG("le status : %d", _bt_adapter_get_le_status()); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } -int _bt_reset_adapter(void) +int _bt_get_local_address(bluetooth_device_address_t *local_address) { - DBusGProxy *proxy; - BT_DBG(""); + GDBusProxy *proxy; + GError *error = NULL; + const char *address; + GVariant *result; + GVariant *temp; - proxy = __bt_get_core_proxy(); - if (!proxy) - return BLUETOOTH_ERROR_INTERNAL; + BT_CHECK_PARAMETER(local_address, return); - if (dbus_g_proxy_call(proxy, "ResetAdapter", NULL, - G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { - BT_ERR("Bt core call failed"); - return BLUETOOTH_ERROR_INTERNAL; - } + proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - /* Terminate myself */ - if (_bt_adapter_get_status() == BT_DEACTIVATED) { - g_idle_add((GSourceFunc)_bt_terminate_service, NULL); + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "Address"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + BT_ERR("Failed to get local address"); + if (error != NULL) { + BT_ERR("Failed to get local address (Error: %s)", error->message); + g_clear_error(&error); + } + return BLUETOOTH_ERROR_INTERNAL; } - return BLUETOOTH_ERROR_NONE; -} - -int _bt_check_adapter(int *status) -{ - BT_CHECK_PARAMETER(status, return); - - *status = 0; /* 0: disabled */ + g_variant_get(result, "(v)", &temp); + address = g_variant_get_string(temp, NULL); + BT_DBG("Address:%s", address); - if (_bt_get_adapter_power()) - *status = 1; /* 1: enabled */ + if (address) + _bt_convert_addr_string_to_type(local_address->addr, address); + else + return BLUETOOTH_ERROR_INTERNAL; + g_variant_unref(result); + g_variant_unref(temp); return BLUETOOTH_ERROR_NONE; } -int _bt_get_local_address(bluetooth_device_address_t *local_address) +int _bt_get_local_version(bluetooth_version_t *local_version) { - DBusGProxy *proxy; - GError *err = NULL; - char *address; - GValue address_v = { 0 }; + GDBusProxy *proxy; + const char *ver = NULL; + char *ptr = NULL; + int ret = BLUETOOTH_ERROR_NONE; + GVariant *result; + GVariant *temp; - BT_CHECK_PARAMETER(local_address, return); + BT_CHECK_PARAMETER(local_version, return); + + GError *error = NULL; proxy = _bt_get_adapter_properties_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - if (!dbus_g_proxy_call(proxy, "Get", &err, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Address", - G_TYPE_INVALID, - G_TYPE_VALUE, &address_v, - G_TYPE_INVALID)) { - if (err != NULL) { - BT_ERR("Getting property failed: [%s]\n", err->message); - g_error_free(err); - } + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "Version"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to get local version (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to get local version"); return BLUETOOTH_ERROR_INTERNAL; } - address = (char *)g_value_get_string(&address_v); + g_variant_get(result, "(v)", &temp); + ver = g_variant_get_string(temp, NULL); + BT_DBG("VERSION: %s", ver); + + if (ver && (strlen(ver) > 0)) { + /* Check the utf8 valitation & Fill the NULL in the invalid location*/ + if (!g_utf8_validate(ver, -1, (const char **)&ptr)) + *ptr = '\0'; + + g_strlcpy(local_version->version, ver, + BLUETOOTH_VERSION_LENGTH_MAX + 1); - if (address) { - _bt_convert_addr_string_to_type(local_address->addr, address); } else { - return BLUETOOTH_ERROR_INTERNAL; + ret = BLUETOOTH_ERROR_INTERNAL; } - return BLUETOOTH_ERROR_NONE; + g_variant_unref(result); + g_variant_unref(temp); + return ret; } int _bt_get_local_name(bluetooth_device_name_t *local_name) { - DBusGProxy *proxy; - GError *err = NULL; - GValue name_v = { 0 }; - char *name = NULL; + GDBusProxy *proxy; + const char *name = NULL; char *ptr = NULL; int ret = BLUETOOTH_ERROR_NONE; + GVariant *result; + GVariant *temp; + GError *error = NULL; BT_CHECK_PARAMETER(local_name, return); proxy = _bt_get_adapter_properties_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - if (!dbus_g_proxy_call(proxy, "Get", &err, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Alias", - G_TYPE_INVALID, - G_TYPE_VALUE, &name_v, - G_TYPE_INVALID)) { - if (err != NULL) { - BT_ERR("Getting property failed: [%s]\n", err->message); - g_error_free(err); - } + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "Alias"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to get local name (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to get local name"); return BLUETOOTH_ERROR_INTERNAL; } - name = (char *)g_value_get_string(&name_v); + g_variant_get(result, "(v)", &temp); + name = g_variant_get_string(temp, NULL); + BT_DBG("LOCAL NAME:%s", name); if (name && (strlen(name) > 0)) { /* Check the utf8 valitation & Fill the NULL in the invalid location*/ @@ -982,112 +1838,139 @@ int _bt_get_local_name(bluetooth_device_name_t *local_name) } else { ret = BLUETOOTH_ERROR_INTERNAL; } - + g_variant_unref(result); + g_variant_unref(temp); return ret; } int _bt_set_local_name(char *local_name) { - GValue name = { 0 }; - DBusGProxy *proxy; + GDBusProxy *proxy; GError *error = NULL; char *ptr = NULL; + GVariant *result; BT_CHECK_PARAMETER(local_name, return); proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); if (!g_utf8_validate(local_name, -1, (const char **)&ptr)) *ptr = '\0'; - g_value_init(&name, G_TYPE_STRING); - g_value_set_string(&name, local_name); - - dbus_g_proxy_call(proxy, "Set", &error, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Alias", - G_TYPE_VALUE, &name, - G_TYPE_INVALID, G_TYPE_INVALID); - - g_value_unset(&name); - - if (error) { - BT_ERR("SetProperty Fail: %s", error->message); - g_error_free(error); + result = g_dbus_proxy_call_sync(proxy, + "Set", + g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, + "Alias", g_variant_new("s", local_name)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to set Alias (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to set Alias"); return BLUETOOTH_ERROR_INTERNAL; } + g_variant_unref(result); return BLUETOOTH_ERROR_NONE; } int _bt_is_service_used(char *service_uuid, gboolean *used) { - char **uuids; - int i; - DBusGProxy *proxy; - GHashTable *hash = NULL; - GValue *value; + GDBusProxy *proxy; + GError *error = NULL; int ret = BLUETOOTH_ERROR_NONE; + GVariant *result; + GVariant *temp = NULL; + GVariantIter *iter = NULL; + gchar *uuid = NULL; + BT_DBG("+"); BT_CHECK_PARAMETER(service_uuid, return); BT_CHECK_PARAMETER(used, return); - proxy = _bt_get_adapter_proxy(); + proxy = _bt_get_adapter_properties_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_g_proxy_call(proxy, "GetProperties", NULL, - G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), &hash, G_TYPE_INVALID); - - retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); - - value = g_hash_table_lookup(hash, "UUIDs"); - uuids = g_value_get_boxed(value); - - if (uuids == NULL) { - /* Normal case */ - *used = FALSE; - goto done; + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "UUIDs"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to get UUIDs (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to get UUIDs"); + return BLUETOOTH_ERROR_INTERNAL; } - for (i = 0; uuids[i] != NULL; i++) { - if (strcasecmp(uuids[i], service_uuid) == 0) { + g_variant_get(result, "(v)", &temp); + g_variant_get(temp, "as", &iter); + + *used = FALSE; + while (g_variant_iter_loop(iter, "&s", &uuid)) { + if (strcasecmp(uuid, service_uuid) == 0) { *used = TRUE; - goto done; + break; } } + g_variant_iter_free(iter); + g_variant_unref(result); + + BT_DBG("Service Used? %d", *used); - *used = FALSE; -done: - g_hash_table_destroy(hash); return ret; } static gboolean __bt_get_discoverable_property(void) { - DBusGProxy *proxy; - GValue discoverable_v = { 0 }; - GError *err = NULL; + GDBusProxy *proxy; + gboolean discoverable_v; + GError *error = NULL; + GVariant *result; + GVariant *temp; proxy = _bt_get_adapter_properties_proxy(); - retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - - if (!dbus_g_proxy_call(proxy, "Get", &err, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Discoverable", - G_TYPE_INVALID, - G_TYPE_VALUE, &discoverable_v, - G_TYPE_INVALID)) { - if (err != NULL) { - BT_ERR("Getting property failed: [%s]\n", err->message); - g_error_free(err); - } + retv_if(proxy == NULL, FALSE); + + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "Discoverable"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to get Discoverable property (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to get Discoverable property"); return BLUETOOTH_ERROR_INTERNAL; } - return g_value_get_boolean(&discoverable_v); + g_variant_get(result, "(v)", &temp); + discoverable_v = g_variant_get_boolean(temp); + BT_DBG("discoverable_v:%d", discoverable_v); + + g_variant_unref(result); + g_variant_unref(temp); + + return discoverable_v; } int _bt_get_discoverable_mode(int *mode) @@ -1111,23 +1994,32 @@ int _bt_get_discoverable_mode(int *mode) return BLUETOOTH_ERROR_NONE; } + int _bt_set_discoverable_mode(int discoverable_mode, int timeout) { int ret = BLUETOOTH_ERROR_NONE; gboolean inq_scan; gboolean pg_scan; GError *error = NULL; - GValue connectable = { 0 }; - GValue discoverable = { 0 }; - GValue val_timeout = { 0 }; - DBusGProxy *proxy; + GDBusProxy *proxy; + GVariant *result; proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - g_value_init(&connectable, G_TYPE_BOOLEAN); - g_value_init(&discoverable, G_TYPE_BOOLEAN); - g_value_init(&val_timeout, G_TYPE_UINT); +#ifdef TIZEN_DPM_ENABLE + if (discoverable_mode != BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE && + _bt_dpm_get_bluetooth_limited_discoverable_state() == DPM_RESTRICTED) { + _bt_launch_dpm_popup("DPM_POLICY_DISABLE_BT_HANDSFREE"); + return BLUETOOTH_ERROR_ACCESS_DENIED; + } + if (discoverable_mode != BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE && + _bt_dpm_get_bluetooth_limited_discoverable_state() == DPM_RESTRICTED) { + _bt_launch_dpm_popup("DPM_POLICY_DISABLE_BT"); + return BLUETOOTH_ERROR_ACCESS_DENIED; + } +#endif switch (discoverable_mode) { case BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE: @@ -1148,395 +2040,654 @@ int _bt_set_discoverable_mode(int discoverable_mode, int timeout) return BLUETOOTH_ERROR_INVALID_PARAM; } - g_value_set_boolean(&connectable, pg_scan); - g_value_set_boolean(&discoverable, inq_scan); - g_value_set_uint(&val_timeout, timeout); - - dbus_g_proxy_call(proxy, "Set", &error, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Powered", - G_TYPE_VALUE, &connectable, - G_TYPE_INVALID, G_TYPE_INVALID); - - if (error != NULL) { - BT_ERR("Powered set err:[%s]", error->message); - g_error_free(error); - ret = BLUETOOTH_ERROR_INTERNAL; - goto done; + BT_INFO("Req. discoverable_mode : %d, timeout : %d", + discoverable_mode, timeout); + + result = g_dbus_proxy_call_sync(proxy, + "Set", + g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, + "Connectable", g_variant_new("b", pg_scan)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to set connectable property (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to set connectable property"); + return BLUETOOTH_ERROR_INTERNAL; } - - dbus_g_proxy_call(proxy, "Set", &error, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Discoverable", - G_TYPE_VALUE, &discoverable, - G_TYPE_INVALID, G_TYPE_INVALID); - - if (error != NULL) { - BT_ERR("Discoverable set err:[%s]", error->message); - g_error_free(error); - ret = BLUETOOTH_ERROR_INTERNAL; - goto done; + g_variant_unref(result); + result = g_dbus_proxy_call_sync(proxy, + "Set", + g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, "Discoverable", + g_variant_new("b", inq_scan)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to set Discoverable property (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to set Discoverable property"); + return BLUETOOTH_ERROR_INTERNAL; } - - dbus_g_proxy_call(proxy, "Set", &error, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "DiscoverableTimeout", - G_TYPE_VALUE, &val_timeout, - G_TYPE_INVALID, G_TYPE_INVALID); - - if (error != NULL) { - BT_ERR("Timeout set err:[%s]", error->message); - g_error_free(error); - ret = BLUETOOTH_ERROR_INTERNAL; - goto done; + g_variant_unref(result); + result = g_dbus_proxy_call_sync(proxy, + "Set", + g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, + "DiscoverableTimeout", g_variant_new("u", timeout)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to set DiscoverableTimeout property"); + return BLUETOOTH_ERROR_INTERNAL; } if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE) timeout = -1; - __bt_set_visible_time(timeout); + ret = __bt_set_visible_time(timeout); -done: - g_value_unset(&val_timeout); - g_value_unset(&connectable); - g_value_unset(&discoverable); + g_variant_unref(result); return ret; } int _bt_start_discovery(void) { - DBusGProxy *proxy; + GDBusProxy *proxy; + GError *error = NULL; + GVariant *result; if (_bt_is_discovering() == TRUE) { BT_ERR("BT is already in discovering"); return BLUETOOTH_ERROR_IN_PROGRESS; + } else if (_bt_is_device_creating() == TRUE) { + BT_ERR("Bonding device is going on"); + return BLUETOOTH_ERROR_DEVICE_BUSY; } proxy = _bt_get_adapter_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - if (!dbus_g_proxy_call(proxy, "StartDiscovery", NULL, - G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_ERR("Discover start failed"); + result = g_dbus_proxy_call_sync(proxy, + "StartDiscovery", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("StartDiscovery failed (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("StartDiscovery failed"); return BLUETOOTH_ERROR_INTERNAL; } - _bt_stop_discovery_timeout(); + is_discovering = TRUE; + cancel_by_user = FALSE; + /* discovery status will be change in event */ + g_variant_unref(result); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_start_custom_discovery(bt_discovery_role_type_t role) +{ + GDBusProxy *proxy; + GVariant *result; + GError *error = NULL; + const gchar *disc_type; + + if (_bt_is_discovering() == TRUE) { + BT_ERR("BT is already in discovering"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (role == DISCOVERY_ROLE_BREDR) + disc_type = "BREDR"; + else if (role == DISCOVERY_ROLE_LE) + disc_type = "LE"; + else if (role == DISCOVERY_ROLE_LE_BREDR) + disc_type = "LE_BREDR"; + else + return BLUETOOTH_ERROR_INVALID_PARAM; + + result = g_dbus_proxy_call_sync(proxy, + "StartCustomDiscovery", + g_variant_new("s", disc_type), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("StartCustomDiscovery failed (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("StartCustomDiscovery failed"); + return BLUETOOTH_ERROR_INTERNAL; + } is_discovering = TRUE; cancel_by_user = FALSE; /* discovery status will be change in event */ + g_variant_unref(result); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_cancel_discovery(void) +{ + GDBusProxy *proxy; + GError *error = NULL; + GVariant *result; + + if (_bt_is_discovering() == FALSE) { + BT_ERR("BT is not in discovering"); + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(proxy, + "StopDiscovery", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + int ret = BLUETOOTH_ERROR_INTERNAL; + if (error != NULL) { + BT_ERR("StopDiscovery failed (Error: %s)", error->message); + + if (g_strrstr(error->message, "No discovery started")) + ret = BLUETOOTH_ERROR_NOT_IN_OPERATION; + + g_clear_error(&error); + } else { + BT_ERR("StopDiscovery failed"); + } + + return ret; + } + cancel_by_user = TRUE; + /* discovery status will be change in event */ + g_variant_unref(result); return BLUETOOTH_ERROR_NONE; } -int _bt_cancel_discovery(void) +gboolean _bt_is_discovering(void) +{ + return is_discovering; +} + +gboolean _bt_is_connectable(void) +{ + GDBusProxy *proxy; + GError *error = NULL; + gboolean is_connectable = FALSE; + GVariant *result; + GVariant *temp; + + proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "Connectable"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to get connectable property (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to get connectable property"); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_get(result, "(v)", &temp); + is_connectable = g_variant_get_boolean(temp); + BT_DBG("discoverable_v:%d", is_connectable); + + g_variant_unref(result); + g_variant_unref(temp); + + BT_INFO("Get connectable [%d]", is_connectable); + return is_connectable; +} + +int _bt_set_connectable(gboolean is_connectable) { - DBusGProxy *proxy; + GDBusProxy *proxy; + GError *error = NULL; + GVariant *result; - if (_bt_is_discovering() == FALSE) { - BT_ERR("BT is not in discovering"); - return BLUETOOTH_ERROR_NOT_IN_OPERATION; + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to set connectable in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; } - proxy = _bt_get_adapter_proxy(); + proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - if (!dbus_g_proxy_call(proxy, "StopDiscovery", NULL, - G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_ERR("Discover stop failed"); + result = g_dbus_proxy_call_sync(proxy, + "Set", + g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, "Connectable", + g_variant_new("b", is_connectable)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to set connectable property (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to set connectable property"); return BLUETOOTH_ERROR_INTERNAL; } - cancel_by_user = TRUE; - /* discovery status will be change in event */ - + BT_INFO_C("### Set connectable [%d]", is_connectable); + g_variant_unref(result); return BLUETOOTH_ERROR_NONE; } -gboolean _bt_is_discovering(void) -{ - return is_discovering; -} - -gboolean _bt_get_discovering_property(void) +gboolean _bt_get_discovering_property(bt_discovery_role_type_t discovery_type) { - DBusGProxy *proxy; - GValue discovering_v = { 0 }; - GError *err = NULL; + GDBusProxy *proxy; + gboolean discovering_v; + GError *error = NULL; + char *discovering_type = NULL; + GVariant *result; + GVariant *temp; proxy = _bt_get_adapter_properties_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - if (!dbus_g_proxy_call(proxy, "Get", &err, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Discovering", - G_TYPE_INVALID, - G_TYPE_VALUE, &discovering_v, - G_TYPE_INVALID)) { - if (err != NULL) { - BT_ERR("Getting property failed: [%s]\n", err->message); - g_error_free(err); - } + if (discovery_type == DISCOVERY_ROLE_BREDR) + discovering_type = "Discovering"; + else if (discovery_type == DISCOVERY_ROLE_LE) + discovering_type = "LEDiscovering"; + + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + discovering_type), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to get discovering property (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to get discovering property"); return BLUETOOTH_ERROR_INTERNAL; } - return g_value_get_boolean(&discovering_v); + g_variant_get(result, "(v)", &temp); + discovering_v = g_variant_get_boolean(temp); + BT_DBG("discoverable_v:%d", discovering_v); + + g_variant_unref(result); + g_variant_unref(temp); + + return discovering_v; } unsigned int _bt_get_discoverable_timeout_property(void) { - DBusGProxy *proxy; - GValue timeout_v = { 0 }; - GError *err = NULL; + GDBusProxy *proxy; + unsigned int timeout_v; + GError *error = NULL; + GVariant *result; + GVariant *temp; proxy = _bt_get_adapter_properties_proxy(); retv_if(proxy == NULL, 0); - if (!dbus_g_proxy_call(proxy, "Get", &err, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "DiscoverableTimeout", - G_TYPE_INVALID, - G_TYPE_VALUE, &timeout_v, - G_TYPE_INVALID)) { - if (err != NULL) { - BT_ERR("Getting property failed: [%s]\n", err->message); - g_error_free(err); + result = g_dbus_proxy_call_sync(proxy, + "Get", + g_variant_new("(ss)", BT_ADAPTER_INTERFACE, + "DiscoverableTimeout"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + BT_ERR("Fail to get discoverable timeout"); + if (error != NULL) { + BT_ERR("Fail to get discoverable timeout (Error: %s)", error->message); + g_clear_error(&error); } return 0; } - return g_value_get_uint(&timeout_v); + g_variant_get(result, "(v)", &temp); + timeout_v = g_variant_get_uint32(temp); + BT_DBG("discoverable_v:%d", timeout_v); + + g_variant_unref(result); + g_variant_unref(temp); + + return timeout_v; } -static bluetooth_device_info_t *__bt_parse_device_info(DBusMessageIter *item_iter) +static bluetooth_device_info_t *__bt_parse_device_info(GVariantIter *item_iter) { - DBusMessageIter value_iter; bluetooth_device_info_t *dev_info; - - dbus_message_iter_recurse(item_iter, &value_iter); - - if (dbus_message_iter_get_arg_type(&value_iter) != DBUS_TYPE_DICT_ENTRY) { - BT_DBG("No entry"); - return NULL; - } + GVariant *value; + const gchar *key; + GByteArray *manufacturer_data = NULL; + guint8 char_value; + GVariantIter *char_value_iter; dev_info = g_malloc0(sizeof(bluetooth_device_info_t)); - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *value = NULL; - char *key; - DBusMessageIter dict_entry; - DBusMessageIter iter_dict_val; - - dbus_message_iter_recurse(&value_iter, &dict_entry); - - dbus_message_iter_get_basic(&dict_entry, &key); - - if (key == NULL) { - dbus_message_iter_next(&value_iter); - continue; - } + while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) { - if (!dbus_message_iter_next(&dict_entry)) { - dbus_message_iter_next(&value_iter); + if (key == NULL) continue; - } - dbus_message_iter_recurse(&dict_entry, &iter_dict_val); - if (strcasecmp(key, "Address") == 0) { + if (!g_strcmp0(key, "Address")) { const char *address = NULL; - dbus_message_iter_get_basic(&iter_dict_val, &address); + address = g_variant_get_string(value, NULL); _bt_convert_addr_string_to_type(dev_info->device_address.addr, address); - - } else if (strcasecmp(key, "Class") == 0) { + } else if (!g_strcmp0(key, "Class")) { unsigned int cod; - dbus_message_iter_get_basic(&iter_dict_val, &cod); + cod = g_variant_get_uint32(value); _bt_divide_device_class(&dev_info->device_class, cod); - } else if (strcasecmp(key, "Name") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, &value); - + } else if (!g_strcmp0(key, "Name")) { + const char *name = NULL; + name = g_variant_get_string(value, NULL); /* If there is no Alias */ if (strlen(dev_info->device_name.name) == 0) { - g_strlcpy(dev_info->device_name.name, value, + g_strlcpy(dev_info->device_name.name, name, BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1); } - } else if (strcasecmp(key, "Alias") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, &value); - + } else if (!g_strcmp0(key, "Alias")) { + const char *alias = NULL; + alias = g_variant_get_string(value, NULL); /* Overwrite the name */ - if (value) { + if (alias) { memset(dev_info->device_name.name, 0x00, BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1); - g_strlcpy(dev_info->device_name.name, value, + g_strlcpy(dev_info->device_name.name, alias, BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1); } - } else if (strcasecmp(key, "Connected") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->connected); - } else if (strcasecmp(key, "Paired") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->paired); - } else if (strcasecmp(key, "Trusted") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->trust); - } else if (strcasecmp(key, "RSSI") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->rssi); - } else if (strcasecmp(key, "UUIDs") == 0) { - DBusMessageIter uuid_iter; + } else if (!g_strcmp0(key, "IsAliasSet")) { + dev_info->is_alias_set = g_variant_get_boolean(value); + } else if (!g_strcmp0(key, "Connected")) { + dev_info->connected = g_variant_get_byte(value); + } else if (!g_strcmp0(key, "Paired")) { + dev_info->paired = g_variant_get_boolean(value); + } else if (!g_strcmp0(key, "Trusted")) { + dev_info->trust = g_variant_get_boolean(value); + } else if (!g_strcmp0(key, "RSSI")) { + dev_info->rssi = g_variant_get_int16(value); + } else if (!g_strcmp0(key, "UUIDs")) { + GVariantIter *iter; + gchar *uuid = NULL; char **parts; int i = 0; - dbus_message_iter_recurse(&iter_dict_val, &uuid_iter); + dev_info->service_index = 0; + g_variant_get(value, "as", &iter); + while (g_variant_iter_loop(iter, "s", &uuid)) { + g_strlcpy(dev_info->uuids[i], uuid, BLUETOOTH_UUID_STRING_MAX); + parts = g_strsplit(uuid, "-", -1); - while (dbus_message_iter_get_arg_type(&uuid_iter) != DBUS_TYPE_INVALID) { - dbus_message_iter_get_basic(&uuid_iter, - &value); - - g_strlcpy(dev_info->uuids[i], value, - BLUETOOTH_UUID_STRING_MAX); - - parts = g_strsplit(value, "-", -1); - - if (parts == NULL || parts[0] == NULL) + if (parts == NULL || parts[0] == NULL) { + g_free(uuid); break; + } dev_info->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16); g_strfreev(parts); i++; - if (!dbus_message_iter_next(&uuid_iter)) { - break; - } } - dev_info->service_index = i; + g_variant_iter_free(iter); + } else if (strcasecmp(key, "LegacyManufacturerDataLen") == 0) { + dev_info->manufacturer_data.data_len = g_variant_get_uint16(value); + } else if (strcasecmp(key, "LegacyManufacturerData") == 0) { + manufacturer_data = g_byte_array_new(); + g_variant_get(value, "ay", &char_value_iter); + while (g_variant_iter_loop(char_value_iter, "y", &char_value)) + g_byte_array_append(manufacturer_data, &char_value, 1); + + if (manufacturer_data) { + if (manufacturer_data->len > 0) + memcpy(dev_info->manufacturer_data.data, manufacturer_data->data, manufacturer_data->len); + } + g_variant_iter_free(char_value_iter); + g_byte_array_free(manufacturer_data, TRUE); } - - dbus_message_iter_next(&value_iter); } return dev_info; } -static void __bt_extract_device_info(DBusMessageIter *msg_iter, +static void __bt_extract_device_info(GVariantIter *iter, GArray **dev_list) { bluetooth_device_info_t *dev_info = NULL; char *object_path = NULL; - DBusMessageIter value_iter; + GVariantIter *interface_iter; + GVariantIter *svc_iter; + char *interface_str = NULL; /* Parse the signature: oa{sa{sv}}} */ - ret_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_OBJECT_PATH); - - dbus_message_iter_get_basic(msg_iter, &object_path); - ret_if(object_path == NULL); - - /* object array (oa) */ - ret_if(dbus_message_iter_next(msg_iter) == FALSE); - ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY); - - dbus_message_iter_recurse(msg_iter, &value_iter); + while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, + &interface_iter)) { - /* string array (sa) */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; - - dbus_message_iter_recurse(&value_iter, &interface_iter); - - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING); - - dbus_message_iter_get_basic(&interface_iter, &interface_name); - - ret_if(dbus_message_iter_next(&interface_iter) == FALSE); - - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_ARRAY); - - if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) { - BT_DBG("Found a device: %s", object_path); - dev_info = __bt_parse_device_info(&interface_iter); + if (object_path == NULL) + continue; - if (dev_info) { - if (dev_info->paired == TRUE) { - g_array_append_vals(*dev_list, dev_info, - sizeof(bluetooth_device_info_t)); - } else { + while (g_variant_iter_loop(interface_iter, "{sa{sv}}", + &interface_str, &svc_iter)) { + if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) { + BT_DBG("Found a device: %s", object_path); + dev_info = __bt_parse_device_info(svc_iter); + if (dev_info) { + if (dev_info->paired == TRUE) { + g_array_append_vals(*dev_list, dev_info, + sizeof(bluetooth_device_info_t)); + } g_free(dev_info); } + g_free(interface_str); + g_variant_iter_free(svc_iter); + break; } - - return; } - - dbus_message_iter_next(&value_iter); } - - BT_DBG("There is no device interface"); + BT_DBG("-"); } int _bt_get_bonded_devices(GArray **dev_list) { - DBusMessage *msg; - DBusMessage *reply; - DBusMessageIter reply_iter; - DBusMessageIter value_iter; - DBusError err; - DBusConnection *conn; + BT_DBG("+"); + GDBusConnection *conn; + GDBusProxy *manager_proxy; + GVariant *result = NULL; + GVariantIter *iter = NULL; + GError *error = NULL; - conn = _bt_get_system_conn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH, - BT_MANAGER_INTERFACE, - "GetManagedObjects"); + manager_proxy = _bt_get_manager_proxy(); + retv_if(manager_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to GetManagedObjects (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to Failed to GetManagedObjects"); + return BLUETOOTH_ERROR_INTERNAL; + } + + /* signature of GetManagedObjects: a{oa{sa{sv}}} */ + g_variant_get(result, "(a{oa{sa{sv}}})", &iter); + + __bt_extract_device_info(iter, dev_list); + g_variant_iter_free(iter); + g_variant_unref(result); - retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} - /* Synchronous call */ - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block( - conn, msg, - -1, &err); - dbus_message_unref(msg); +int _bt_get_profile_connected_devices(char *profile_uuid, GArray **addr_list) +{ + BT_DBG("+"); + GDBusConnection *conn; + GDBusProxy *manager_proxy; + GVariant *result = NULL; + GVariant *result1 = NULL; + GVariantIter *iter = NULL; + GError *error = NULL; + char *object_path = NULL; + GVariantIter *interface_iter; + char *interface_str = NULL; + GDBusProxy *device_proxy = NULL; + gboolean is_connected = FALSE; - if (!reply) { - BT_ERR("Can't get managed objects"); + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - if (dbus_error_is_set(&err)) { - BT_ERR("%s", err.message); - dbus_error_free(&err); - } + manager_proxy = _bt_get_manager_proxy(); + retv_if(manager_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to GetManagedObjects (Error: %s)", error->message); + g_clear_error(&error); + error = NULL; + } else + BT_ERR("Failed to Failed to GetManagedObjects"); return BLUETOOTH_ERROR_INTERNAL; } - if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return BLUETOOTH_ERROR_INTERNAL; - } + /* signature of GetManagedObjects: a{oa{sa{sv}}} */ + g_variant_get(result, "(a{oa{sa{sv}}})", &iter); + + /* Parse the signature: oa{sa{sv}}} */ + while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) { + if (object_path == NULL) + continue; - dbus_message_iter_recurse(&reply_iter, &value_iter); + while (g_variant_iter_loop(interface_iter, "{sa{sv}}", + &interface_str, NULL)) { + if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) { + BT_DBG("Found a device: %s", object_path); + g_free(interface_str); - /* signature of GetManagedObjects: a{oa{sa{sv}}} */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter msg_iter; + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE, NULL, NULL); + + if (device_proxy == NULL) { + BT_DBG("Device don't have this service"); + break; + } + + result1 = g_dbus_proxy_call_sync(device_proxy, "IsConnectedProfile", + g_variant_new("(s)", profile_uuid), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (result1 == NULL) { + BT_ERR("Error occured in Proxy call"); + if (error) { + BT_ERR("Error occured in Proxy call [%s]\n", error->message); + g_error_free(error); + error = NULL; + } + g_object_unref(device_proxy); + break; + } + g_variant_get(result1, "(b)", &is_connected); - dbus_message_iter_recurse(&value_iter, &msg_iter); + if (is_connected == TRUE) { + char address[BT_ADDRESS_STRING_SIZE]; + bluetooth_device_address_t *addr = NULL; - __bt_extract_device_info(&msg_iter, dev_list); + _bt_convert_device_path_to_address(object_path, address); - dbus_message_iter_next(&value_iter); + addr = g_malloc0(sizeof(bluetooth_device_address_t)); + _bt_convert_addr_string_to_type(addr->addr, address); + + g_array_append_vals(*addr_list, addr, + sizeof(bluetooth_device_address_t)); + } + + g_variant_unref(result1); + g_object_unref(device_proxy); + + break; + } + } } + g_variant_unref(result); + g_variant_iter_free(iter); + + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } @@ -1544,8 +2695,9 @@ int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address, bluetooth_device_info_t *dev_info) { char *object_path = NULL; - DBusGProxy *adapter_proxy; + GDBusProxy *adapter_proxy; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + int ret = BLUETOOTH_ERROR_NONE; BT_CHECK_PARAMETER(device_address, return); BT_CHECK_PARAMETER(dev_info, return); @@ -1557,15 +2709,80 @@ int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address, object_path = _bt_get_device_object_path(address); - retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND); + retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + ret = __bt_get_bonded_device_info(object_path, dev_info); + g_free(object_path); + + return ret; +} + +int _bt_is_alias_set(bluetooth_device_address_t *device_address, gboolean *is_alias_set) +{ + char *object_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gboolean alias_set = FALSE; + + GDBusConnection *conn; + GDBusProxy *device_proxy; + GError *error = NULL; + GVariant *result = NULL; + GVariant *temp = NULL; + + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_PARAMETER(is_alias_set, return); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + conn = _bt_gdbus_get_system_gconn(); + if (conn == NULL) { + g_free(object_path); + return BLUETOOTH_ERROR_INTERNAL; + } + + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, + BT_BLUEZ_NAME, + object_path, + BT_PROPERTIES_INTERFACE, + NULL, NULL); + if (device_proxy == NULL) { + g_free(object_path); + return BLUETOOTH_ERROR_INTERNAL; + } - if (__bt_get_bonded_device_info(object_path, - dev_info) != BLUETOOTH_ERROR_NONE) { - BT_ERR("Can't get the paired device path \n"); + result = g_dbus_proxy_call_sync(device_proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "IsAliasSet"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + BT_ERR("Error occured in Proxy call"); + if (error != NULL) { + BT_ERR("Getting is_alias_set property failed: [%s]\n", error->message); + g_error_free(error); + } + g_object_unref(device_proxy); g_free(object_path); return BLUETOOTH_ERROR_INTERNAL; } + + g_variant_get(result, "(v)", &temp); + alias_set = g_variant_get_boolean(temp); + *is_alias_set = alias_set; + BT_DBG("address: [%s] | *is_alias_set: %s", address, *is_alias_set ? "TRUE" : "FALSE"); + g_variant_unref(temp); + g_variant_unref(result); + g_object_unref(device_proxy); + g_free(object_path); + return BLUETOOTH_ERROR_NONE; } @@ -1585,3 +2802,326 @@ int _bt_get_timeout_value(int *timeout) return BLUETOOTH_ERROR_NONE; } +int _bt_set_le_privacy(gboolean set_privacy) +{ + GDBusProxy *proxy; + GError *error = NULL; + GVariant *result = NULL; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to set le privacy in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(proxy, + "SetLePrivacy", + g_variant_new("(b)", set_privacy), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to SetLePrivacy (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to SetLePrivacy"); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_unref(result); + BT_INFO("SetLePrivacy as %d", set_privacy); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_le_static_random_address(gboolean is_enable) +{ + GDBusProxy *proxy; + GError *error = NULL; + GVariant *result = NULL; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to set le random address in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(proxy, + "SetLeStaticRandomAddress", + g_variant_new("(b)", is_enable), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Failed to SetLeStaticRandomAddress (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Failed to SetLeStaticRandomAddress"); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_unref(result); + BT_INFO("SetLeStaticRandomAddress as %d", is_enable); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_manufacturer_data(bluetooth_manufacturer_data_t *m_data) +{ + GDBusProxy *proxy; + GError *error = NULL; + int i; + GVariant *val; + GVariant *result; + GVariantBuilder *builder; + + BT_CHECK_PARAMETER(m_data, return); + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + + for (i = 0; i < (m_data->data_len) + 2; i++) + g_variant_builder_add(builder, "y", m_data->data[i]); + + val = g_variant_new("(ay)", builder); + + result = g_dbus_proxy_call_sync(proxy, + "SetManufacturerData", + val, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + g_variant_builder_unref(builder); + if (!result) { + if (error != NULL) { + BT_ERR("Failed to SetManufacturerData (Error: %s)", error->message); + g_clear_error(&error); + } else { + BT_ERR("Failed to SetManufacturerData"); + } + return BLUETOOTH_ERROR_INTERNAL; + } + builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + + for (i = 0; i < (m_data->data_len) + 2; i++) + g_variant_builder_add(builder, "y", m_data->data[i]); + + val = g_variant_new("(ay)", builder); + + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED, + val); + + BT_INFO("Set manufacturer data"); + + g_variant_builder_unref(builder); + g_variant_unref(result); + + return BLUETOOTH_ERROR_NONE; +} + + +int _bt_service_set_alarm(int timeout, bt_set_alarm_cb call_back, void *user_data, alarm_id_t *alarm_id) +{ + int result = BLUETOOTH_ERROR_NONE; + bt_service_alarm_t *alarm = NULL; + + if (!call_back || !alarm_id) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (!alarm_mgr.is_alarm_initialized) { + result = alarmmgr_init("bt-service"); + if (result != 0) { + BT_ERR("Failed to initialize alarm = %d", result); + result = BLUETOOTH_ERROR_INTERNAL; + goto finish; + } + result = alarmmgr_set_cb(alarm_cb, NULL); + if (result != 0) { + BT_ERR("Failed to set the callback = %d", result); + result = BLUETOOTH_ERROR_INTERNAL; + goto finish; + } + alarm_mgr.is_alarm_initialized = TRUE; + } + + alarm = g_malloc0(sizeof(bt_service_alarm_t)); + if (!alarm) + return BLUETOOTH_ERROR_MEMORY_ALLOCATION; + + result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, timeout, + 0, NULL, alarm_id); + if (result != 0) { + BT_ERR("Failed to create alarm error = %d", result); + result = BLUETOOTH_ERROR_INTERNAL; + g_free(alarm); + goto finish; + } + alarm->alarm_id = *alarm_id; + alarm->callback = call_back; + alarm->user_data = user_data; + + alarm_mgr.g_alarm_list = g_list_append(alarm_mgr.g_alarm_list, alarm); + result = BLUETOOTH_ERROR_NONE; +finish: + return result; +} + +static int alarm_cb(alarm_id_t alarm_id, void* user_param) +{ + GList *node = NULL; + bt_service_alarm_t *p_data; + bt_set_alarm_cb callback = NULL; + void *user_data = NULL; + + node = g_list_find_custom(alarm_mgr.g_alarm_list, + GINT_TO_POINTER(alarm_id), compare_alarm); + if (!node) + return 0; + + p_data = (bt_service_alarm_t *)node->data; + alarm_mgr.g_alarm_list = g_list_delete_link(alarm_mgr.g_alarm_list, + node); + + if (!p_data) + return 0; + + callback = p_data->callback; + user_data = p_data->user_data; + g_free(p_data); + + if (callback) + callback(alarm_id, user_data); + + return 0; +} + +int _bt_service_remove_alarm(alarm_id_t alarm_id) +{ + GList *list = NULL; + bt_service_alarm_t *p_data; + list = g_list_find_custom(alarm_mgr.g_alarm_list, GINT_TO_POINTER(alarm_id), compare_alarm); + + if (list != NULL) { + alarmmgr_remove_alarm(alarm_id); + p_data = (bt_service_alarm_t *)list->data; + alarm_mgr.g_alarm_list = g_list_remove(alarm_mgr.g_alarm_list, list->data); + g_free(p_data); + } + + return 0; +} + +gint compare_alarm(gconstpointer list_data, gconstpointer data) +{ + alarm_id_t alarm_id = (alarm_id_t)data; + bt_service_alarm_t *p_data = (bt_service_alarm_t *)list_data; + + if (p_data->alarm_id == alarm_id) + return 0; + + return 1; +} + +static void alarm_data_free(void *data) +{ + bt_service_alarm_t *p_data = (bt_service_alarm_t *)data; + g_free(p_data); + return; +} + +static gboolean _bt_adapter_request_delayed_cb(gpointer user_data) +{ + int result; + int function = (int)user_data; + + switch (function) { + case BT_ENABLE_ADAPTER: + result = _bt_enable_adapter(); + if (result != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_enable_adapter is failed"); + /* Send enabled event to API */ + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED, + g_variant_new("(i)", result)); + } + break; + case BT_DISABLE_ADAPTER: + result = _bt_disable_adapter(); + if (result != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_disable_adapter is failed"); + /* Send disabled event to API */ + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED, + g_variant_new("(i)", result)); + } + break; + default: + BT_ERR("function is NOT matched"); + break; + } + + return FALSE; +} + +int _bt_adapter_request_delayed(int function) +{ + int ret; + + switch (function) { + case BT_ENABLE_ADAPTER: + ret = _bt_enable_adapter_check_status(); + if (ret == BLUETOOTH_ERROR_NONE) + _bt_adapter_set_status(BT_ACTIVATING); + else + return ret; + + break; + case BT_DISABLE_ADAPTER: + ret = _bt_disable_adapter_check_status(); + if (ret == BLUETOOTH_ERROR_NONE) + _bt_adapter_set_status(BT_DEACTIVATING); + else + return ret; + + break; + default: + BT_ERR("function is NOT matched"); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_idle_add((GSourceFunc)_bt_adapter_request_delayed_cb, (void*)function); + + return BLUETOOTH_ERROR_NONE; +} + + +int _bt_get_enable_timer_id(void) +{ + return timer_id; +} +