X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service%2Fbt-service-device.c;h=83c358a3e9f2e0125932af5872feaa4abd77a7fc;hb=d3f64e9c21a3743c3b8fb36e4524a030945e3333;hp=8a2fd798943588a4a59529597038bafec32bfb50;hpb=552c67fee3d0ebc596d922cf7afb4104dd3202aa;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service/bt-service-device.c b/bt-service/bt-service-device.c index 8a2fd79..83c358a 100644 --- a/bt-service/bt-service-device.c +++ b/bt-service/bt-service-device.c @@ -1,11 +1,5 @@ /* - * Bluetooth-frwk - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Hocheol Seo - * Girishashok Joshi - * Chanyeol Park + * 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. @@ -25,14 +19,16 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif +#include +#include + #include "bluetooth-api.h" #include "bt-internal-types.h" #include "bt-service-common.h" +#include "bt-service-adapter-le.h" #include "bt-service-event.h" #include "bt-service-device.h" #include "bt-service-rfcomm-client.h" @@ -40,6 +36,7 @@ #include "bt-service-agent.h" #include "bt-service-network.h" #include "bt-service-adapter.h" +#include "bt-service-gap-agent.h" #define BT_SYSPOPUP_IPC_RESPONSE_OBJECT "/org/projectx/bt_syspopup_res" #define BT_SYSPOPUP_INTERFACE "User.Bluetooth.syspopup" @@ -52,6 +49,23 @@ #define BT_LE_CONN_SLAVE_LATENCY_MAX 499 #define BT_LE_CONN_INTERVAL_SPLIT 1.25 /* msec */ #define BT_LE_CONN_TO_SPLIT 10 /* msec */ +#define BT_DEVICE_PIN_CODE_SLOT_MAX 10 + +#define BT_LE_CONN_PARAM_DEFAULT_SUPERVISION_TIMEOUT 6000 /* msec */ + +#define BT_LE_CONN_PARAM_BALANCED_MIN_INTERVAL 30 /* msec */ +#define BT_LE_CONN_PARAM_BALANCED_MAX_INTERVAL 50 /* msec */ +#define BT_LE_CONN_PARAM_BALANCED_SLAVE_LATENCY 0 /* event */ + +#define BT_LE_CONN_PARAM_LOW_LATENCY_MIN_INTERVAL 10 /* msec */ +#define BT_LE_CONN_PARAM_LOW_LATENCY_MAX_INTERVAL 30 /* msec */ +#define BT_LE_CONN_PARAM_LOW_LATENCY_SLAVE_LATENCY 0 /* event */ + +#define BT_LE_CONN_PARAM_LOW_POWER_MIN_INTERVAL 80 /* msec */ +#define BT_LE_CONN_PARAM_LOW_POWER_MAX_INTERVAL 100 /* msec */ +#define BT_LE_CONN_PARAM_LOW_POWER_SLAVE_LATENCY 2 /* event */ + +#define PROFILE_SUPPORTED 0x3 /* This corresponds to binary 0b11*/ typedef struct { int req_id; @@ -62,11 +76,45 @@ typedef struct { GDBusProxy *adapter_proxy; void *agent; unsigned short conn_type; + gboolean bonding_wo_discovery; } bt_funcion_data_t; +typedef struct { + char *address; + char *pin_code; +} bt_pin_code_info_t; + +typedef struct { + int req_id; + bluetooth_device_address_t bd_addr; + gboolean auto_connect; +} bt_pending_le_conn_info_s; + +typedef struct { + char *address; + float interval_min; + float interval_max; + GSList *senders; +} bt_connected_le_dev_t; + +typedef struct { + char *sender; + float interval_min; + float interval_max; + guint16 latency; + guint16 time_out; + float key; +} bt_le_conn_param_t; + gboolean is_device_creating; bt_funcion_data_t *bonding_info; bt_funcion_data_t *searching_info; +bt_funcion_data_t *att_mtu_req_info; + +static GSList *le_connected_dev_list = NULL; +static GSList *pin_info_list = NULL; +static bt_pending_le_conn_info_s *pending_le_conn_info = NULL; +static guint pending_le_conn_timer_id = 0; /* This HID Mouse does not support pairing precedure. need to skip it. */ #define SMB_MOUSE_LAP_ADDR "00:12:A1" @@ -74,9 +122,6 @@ bt_funcion_data_t *searching_info; static void __bt_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data); -static int __bt_retry_bond(void); - - /*static void __bt_decline_pair_request() { GVariant *out_param1; @@ -160,7 +205,7 @@ done: BT_DBG("-"); } */ -#ifdef TIZEN_WEARABLE +#ifdef TIZEN_PROFILE_WEARABLE static gboolean __bt_syspopup_timer_cb(gpointer user_data) { int ret; @@ -169,9 +214,7 @@ static gboolean __bt_syspopup_timer_cb(gpointer user_data) b = (bundle *)user_data; -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) ret = syspopup_launch("bt-syspopup", b); -#endif if (ret < 0) { BT_ERR("Sorry!! Cannot launch popup return = %d, Retrying...", ret); } else { @@ -188,7 +231,7 @@ static gboolean __bt_launch_unable_to_pairing_syspopup(int result) bundle *b = NULL; GDBusConnection *conn; - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); if (conn == NULL) return FALSE; @@ -198,16 +241,14 @@ static gboolean __bt_launch_unable_to_pairing_syspopup(int result) bundle_add(b, "event-type", "unable-to-pairing"); - if (result == BLUETOOTH_ERROR_TIMEOUT ) + if (result == BLUETOOTH_ERROR_TIMEOUT) bundle_add(b, "error", "timeout"); else if (result == BLUETOOTH_ERROR_AUTHENTICATION_FAILED) bundle_add(b, "error", "authfailed"); else bundle_add(b, "error", "error"); -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) ret = syspopup_launch("bt-syspopup", b); -#endif if (0 > ret) { BT_ERR("Popup launch failed...retry %d \n", ret); g_timeout_add(200, (GSourceFunc) __bt_syspopup_timer_cb, @@ -246,29 +287,6 @@ void _bt_set_autopair_status_in_bonding_info(gboolean is_autopair) bonding_info->is_autopair = is_autopair; } -void _bt_device_path_to_address(const char *device_path, - char *device_address) -{ - char address[BT_ADDRESS_STRING_SIZE] = { 0 }; - char *dev_addr; - char *pos; - - ret_if(device_path == NULL); - ret_if(device_address == NULL); - - dev_addr = strstr(device_path, "dev_"); - ret_if(dev_addr == NULL); - - dev_addr += 4; - g_strlcpy(address, dev_addr, sizeof(address)); - - while ((pos = strchr(address, '_')) != NULL) { - *pos = ':'; - } - - g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE); -} - void __bt_cancel_search_service_done(void) { int result = BLUETOOTH_ERROR_CANCEL_BY_USER; @@ -318,40 +336,52 @@ static void __bt_get_uuids(GVariant *value, bt_remote_dev_info_t *info) bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) { - bt_remote_dev_info_t *dev_info; char *object_path = NULL; + bt_remote_dev_info_t *dev_info; + + retv_if(address == NULL, NULL); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, NULL); + + dev_info = _bt_get_remote_device_info_by_object_path(object_path); + + g_free(object_path); + return dev_info; +} + +bt_remote_dev_info_t *_bt_get_remote_device_info_by_object_path( + const char *object_path) +{ + bt_remote_dev_info_t *dev_info; GDBusProxy *adapter_proxy; GDBusProxy *device_proxy; GVariant *value; GVariant *tmp_value; gchar *name; - gchar *manufacturer_data = NULL; + gchar * address; GDBusConnection *conn; GError *error = NULL; GVariant *result = NULL; - - retv_if(address == NULL, NULL); + GVariantIter *value_iter; + guint8 m_value; + int i = 0; adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, NULL); - - object_path = _bt_get_device_object_path(address); - retv_if(object_path == NULL, NULL); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); if (conn == NULL) { BT_ERR("conn == NULL"); - g_free(object_path); return NULL; } device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, - NULL, BT_BLUEZ_NAME, - object_path, BT_PROPERTIES_INTERFACE, NULL, NULL); + NULL, BT_BLUEZ_NAME, object_path, + BT_PROPERTIES_INTERFACE, NULL, NULL); - g_free(object_path); retv_if(device_proxy == NULL, NULL); result = g_dbus_proxy_call_sync(device_proxy, "GetAll", @@ -369,7 +399,7 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) g_variant_get(result , "(@a{sv})", &value); g_variant_unref(result); - tmp_value = g_variant_lookup_value (value, "Alias", G_VARIANT_TYPE_STRING); + tmp_value = g_variant_lookup_value(value, "Alias", G_VARIANT_TYPE_STRING); g_variant_get(tmp_value, "s", &name); g_variant_unref(tmp_value); @@ -381,57 +411,103 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) g_variant_unref(tmp_value); } + tmp_value = g_variant_lookup_value(value, "IsAliasSet", G_VARIANT_TYPE_BOOLEAN); + if (tmp_value) { + dev_info->is_alias_set = g_variant_get_boolean(tmp_value); + g_variant_unref(tmp_value); + } else { + dev_info->is_alias_set = FALSE; + } + BT_DBG("IsAliasSet: [%s]", dev_info->is_alias_set ? "TRUE" : "FALSE"); + tmp_value = g_variant_lookup_value(value, "Class", G_VARIANT_TYPE_UINT32); - dev_info->class = tmp_value ? g_variant_get_uint32(tmp_value) : 0; - g_variant_unref(tmp_value); + if (tmp_value) { + dev_info->class = g_variant_get_uint32(tmp_value); + g_variant_unref(tmp_value); + } else + dev_info->class = 0; - tmp_value = g_variant_lookup_value(value, "Connected", G_VARIANT_TYPE_BOOLEAN); - dev_info->connected = tmp_value ? g_variant_get_boolean(tmp_value) : BLUETOOTH_CONNECTED_LINK_NONE; - g_variant_unref(tmp_value); + tmp_value = g_variant_lookup_value(value, "Connected", G_VARIANT_TYPE_BYTE); + if (tmp_value) { + dev_info->connected = g_variant_get_byte(tmp_value); + g_variant_unref(tmp_value); + } else + dev_info->connected = BLUETOOTH_CONNECTED_LINK_NONE; + BT_DBG("connected link : %d", dev_info->connected); tmp_value = g_variant_lookup_value(value, "Trusted", G_VARIANT_TYPE_BOOLEAN); - dev_info->trust = tmp_value ? g_variant_get_boolean(tmp_value) : FALSE; - g_variant_unref(tmp_value); + if (tmp_value) { + dev_info->trust = g_variant_get_boolean(tmp_value); + g_variant_unref(tmp_value); + } else + dev_info->trust = FALSE; tmp_value = g_variant_lookup_value(value, "Paired", G_VARIANT_TYPE_BOOLEAN); - dev_info->paired = tmp_value ? g_variant_get_boolean(tmp_value) : FALSE; - g_variant_unref(tmp_value); - - BT_DBG("Paired %d", dev_info->paired ); + if (tmp_value) { + dev_info->paired = g_variant_get_boolean(tmp_value); + g_variant_unref(tmp_value); + } else + dev_info->paired = FALSE; - tmp_value = g_variant_lookup_value(value, "RSSI", G_VARIANT_TYPE_INT32); - dev_info->rssi = tmp_value ? g_variant_get_int32(tmp_value) : 0; - g_variant_unref(tmp_value); + tmp_value = g_variant_lookup_value(value, "RSSI", G_VARIANT_TYPE_INT16); + if (tmp_value) { + dev_info->rssi = g_variant_get_int16(tmp_value); + g_variant_unref(tmp_value); + } else + dev_info->rssi = 0; - tmp_value = g_variant_lookup_value(value, "LastAddrType", G_VARIANT_TYPE_UINT32); - dev_info->addr_type = tmp_value ? g_variant_get_uint32(tmp_value) : 0; - g_variant_unref(tmp_value); + tmp_value = g_variant_lookup_value(value, "LastAddrType", G_VARIANT_TYPE_BYTE); + if (tmp_value) { + dev_info->addr_type = g_variant_get_byte(tmp_value); + g_variant_unref(tmp_value); + } else + dev_info->addr_type = 0; tmp_value = g_variant_lookup_value(value, "UUIDs", G_VARIANT_TYPE_STRING_ARRAY); - __bt_get_uuids(tmp_value, dev_info); - g_variant_unref(tmp_value); - - tmp_value = g_variant_lookup_value(value, "ManufacturerDataLen", G_VARIANT_TYPE_UINT32); - dev_info->manufacturer_data_len = tmp_value ? g_variant_get_uint32(tmp_value) : 0; - if (dev_info->manufacturer_data_len > BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX) { - BT_ERR("manufacturer_data_len is too long(len = %d)", dev_info->manufacturer_data_len); - dev_info->manufacturer_data_len = BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX; + if (tmp_value) { + __bt_get_uuids(tmp_value, dev_info); + g_variant_unref(tmp_value); } - g_variant_unref(tmp_value); - tmp_value = g_variant_lookup_value(value, "ManufacturerData", G_VARIANT_TYPE_BYTESTRING); - manufacturer_data = value ? (gchar *)g_variant_get_bytestring(tmp_value) : NULL; - if (manufacturer_data) { - if (dev_info->manufacturer_data_len > 0) { + tmp_value = g_variant_lookup_value(value, "LegacyManufacturerDataLen", G_VARIANT_TYPE_UINT16); + if (tmp_value) { + dev_info->manufacturer_data_len = g_variant_get_uint16(tmp_value); + if (dev_info->manufacturer_data_len > BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX) { + BT_ERR("manufacturer_data_len is too long(len = %d)", dev_info->manufacturer_data_len); + dev_info->manufacturer_data_len = BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX; + } + g_variant_unref(tmp_value); + } else + dev_info->manufacturer_data_len = 0; + + tmp_value = g_variant_lookup_value(value, "LegacyManufacturerData", G_VARIANT_TYPE_ARRAY); + if (tmp_value) { + if ((dev_info->manufacturer_data_len == 0) || + dev_info->manufacturer_data_len != g_variant_get_size(tmp_value)) { + BT_ERR("manufacturer data length doesn't match"); + dev_info->manufacturer_data_len = 0; + dev_info->manufacturer_data = NULL; + } else { dev_info->manufacturer_data = g_malloc0(dev_info->manufacturer_data_len); - memcpy(dev_info->manufacturer_data, manufacturer_data, dev_info->manufacturer_data_len); + g_variant_get(tmp_value, "ay", &value_iter); + while (g_variant_iter_loop(value_iter, "y", &m_value)) + dev_info->manufacturer_data[i++] = m_value; + + g_variant_iter_free(value_iter); } + g_variant_unref(tmp_value); + } else { + BT_INFO("manufacture data is not a G_VARIANT_TYPE_ARRAY "); + dev_info->manufacturer_data_len = 0; + dev_info->manufacturer_data = NULL; } + + tmp_value = g_variant_lookup_value(value, "Address", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &address); g_variant_unref(tmp_value); - dev_info->address = g_strdup(address); - dev_info->name = g_strdup(name); - g_free(name); + dev_info->address = address; + dev_info->name = name; g_variant_unref(value); } else { BT_ERR("result is NULL\n"); @@ -442,20 +518,70 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) return dev_info; } -char *_bt_get_bonded_device_name(char *address) +char *_bt_get_device_name(const char *bdaddress) { - bluetooth_device_address_t device_address = { {0} }; - bluetooth_device_info_t dev_info; + char *device_path = NULL; + const gchar *name = NULL; + gchar *dev_name = NULL; + gsize name_len = 0; + GVariant *result = NULL; + GError *err = NULL; + GDBusProxy *device_proxy; + GDBusConnection *conn; - retv_if(address == NULL, strdup("")); + retv_if(bdaddress == NULL, NULL); - _bt_convert_addr_string_to_type(device_address.addr, address); + device_path = _bt_get_device_object_path((char *)bdaddress); + retv_if(device_path == NULL, NULL); - memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, NULL); + INFO_SECURE("Device_path %s", device_path); + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, device_path, + BT_PROPERTIES_INTERFACE, NULL, &err); + + g_free(device_path); + retv_if(device_proxy == NULL, NULL); - _bt_get_bonded_device_info(&device_address, &dev_info); + result = g_dbus_proxy_call_sync(device_proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "Alias"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); + if (err) { + BT_ERR("DBus Error : %s", err->message); + g_clear_error(&err); + } else { + GVariant *value; + g_variant_get(result, "(v)", &value); + name = g_variant_get_string(value, &name_len); + INFO_SECURE("Alias Name [%s]", name); + if (name_len) + dev_name = g_strdup(name); + g_variant_unref(value); + g_variant_unref(result); + } + + if (name_len == 0) { + GVariant *value; + result = g_dbus_proxy_call_sync(device_proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "Name"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); + if (err) { + ERR("DBus Error : %s", err->message); + g_clear_error(&err); + } else { + g_variant_get(result, "(v)", &value); + name = g_variant_get_string(value, &name_len); + INFO_SECURE("Name = %s", name); + if (name_len) + dev_name = g_strdup(name); + g_variant_unref(value); + g_variant_unref(result); + } + } - return g_strdup(dev_info.device_name.name); + g_object_unref(device_proxy); + return dev_name; } static gboolean __ignore_auto_pairing_request(const char *address) @@ -497,12 +623,6 @@ static gboolean __ignore_auto_pairing_request(const char *address) } buffer = g_malloc0(sizeof(char) * size); - /* Fix : NULL_RETURNS */ - if (buffer == NULL) { - BT_ERR("Memory allocation error\n"); - fclose(fp); - return FALSE; - } result = fread((char *)buffer, 1, size, fp); fclose(fp); if (result != size) { @@ -551,98 +671,46 @@ static gboolean __ignore_auto_pairing_request(const char *address) return FALSE; } -static int __bt_retry_bond(void) +static int __bt_cancel_bonding(void) { BT_CHECK_PARAMETER(bonding_info, return); BT_CHECK_PARAMETER(bonding_info->addr, return); - - g_dbus_proxy_call(bonding_info->device_proxy, "Pair", - g_variant_new("(y)", bonding_info->conn_type), - G_DBUS_CALL_FLAGS_NONE, - BT_MAX_DBUS_TIMEOUT, - NULL, - (GAsyncReadyCallback)__bt_bond_device_cb, - NULL); - - return BLUETOOTH_ERROR_NONE; -} - - -static int __bt_remove_and_bond(void) -{ - GDBusProxy *adapter_proxy; - GVariant *result = NULL; + /* First Cancel the ongoing pairing in bluez otherwise if we send + * pair request bluez will send inprogress and we again retry bond so + * this cycle continues */ GError *err = NULL; - char *device_path = NULL; - - BT_CHECK_PARAMETER(bonding_info, return); - BT_CHECK_PARAMETER(bonding_info->addr, return); - - adapter_proxy = _bt_get_adapter_proxy(); - retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - - result = g_dbus_proxy_call_sync(adapter_proxy, "FindDevice", - g_variant_new("(s)", bonding_info->addr), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL); - if (result == NULL) - return BLUETOOTH_ERROR_INTERNAL; - - g_variant_get(result , "(&o)", &device_path); - g_variant_unref(result); - - retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); - - result = g_dbus_proxy_call_sync(adapter_proxy, "UnpairDevice", - g_variant_new("(o)", device_path), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &err); - - if (err != NULL) { - BT_ERR("UnpairDevice Fail: %s", err->message); - g_error_free(err); - return BLUETOOTH_ERROR_INTERNAL; - } - - return __bt_retry_bond(); -} - -static int __bt_cancel_and_bond(void) -{ - int ret = BLUETOOTH_ERROR_NONE; - - ret = _bt_agent_reply_cancellation(); - if (ret != BLUETOOTH_ERROR_NONE){ - BT_ERR("Fail to call reply cancellation"); - return ret; + GVariant *result; + result = g_dbus_proxy_call_sync(bonding_info->device_proxy, "CancelPairing", + NULL, G_DBUS_CALL_FLAGS_NONE, + 10000, NULL, &err); + if (!result) { + if (err) { + BT_ERR("Cancelling bonding request error msg (%s)", err->message); + g_clear_error(&err); + return BLUETOOTH_ERROR_PARING_FAILED; + } + } else { + g_variant_unref(result); } - - return __bt_retry_bond(); + return BLUETOOTH_ERROR_NONE; } - static void __bt_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { int result = BLUETOOTH_ERROR_NONE; GError *err = NULL; + GVariant *reply; GVariant *out_param1; request_info_t *req_info; bluetooth_device_info_t dev_info; - bt_remote_dev_info_t *remote_dev_info = NULL; - GVariant *manufacture_data; - GVariant *param; -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) /* Terminate ALL system popup */ syspopup_destroy_all(); -#endif - g_dbus_proxy_call_finish(proxy, res, &err); + reply = g_dbus_proxy_call_finish(proxy, res, &err); + if (reply) + g_variant_unref(reply); is_device_creating = FALSE; @@ -661,33 +729,30 @@ static void __bt_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res, } if (err != NULL) { + g_dbus_error_strip_remote_error(err); BT_ERR("Error occured in CreateBonding [%s]", err->message); - if (!strcmp(err->message, "Already Exists")) { - BT_INFO("Existing Bond, remove and retry"); - ret_if(__bt_remove_and_bond() == BLUETOOTH_ERROR_NONE); - - result = BLUETOOTH_ERROR_PARING_FAILED; + if (g_strrstr(err->message, "Already Exists")) { + BT_INFO("Existing Bond"); + result = BLUETOOTH_ERROR_ALREADY_CONNECT; } else if (_bt_agent_is_canceled() || - !strcmp(err->message, "Authentication Canceled")) { + g_strrstr(err->message, "Authentication Canceled")) { BT_INFO("Cancelled by USER"); result = BLUETOOTH_ERROR_CANCEL_BY_USER; - } else if (!strcmp(err->message, "Authentication Rejected")) { + } else if (g_strrstr(err->message, "Authentication Rejected")) { BT_INFO("REJECTED"); result = BLUETOOTH_ERROR_ACCESS_DENIED; - } else if (!strcmp(err->message, "In Progress")) { - BT_INFO("Bond in progress, cancel and retry"); - ret_if(__bt_cancel_and_bond() == BLUETOOTH_ERROR_NONE); - - result = BLUETOOTH_ERROR_PARING_FAILED; - } else if (!strcmp(err->message, "Authentication Failed")) { + } else if (g_strrstr(err->message, "In Progress")) { + BT_INFO("Bond in progress"); + result = BLUETOOTH_ERROR_IN_PROGRESS; + } else if (g_strrstr(err->message, "Authentication Failed")) { BT_INFO("Authentication Failed"); if (bonding_info->is_autopair == TRUE) { _bt_set_autopair_status_in_bonding_info(FALSE); __ignore_auto_pairing_request(bonding_info->addr); } result = BLUETOOTH_ERROR_AUTHENTICATION_FAILED; - } else if (!strcmp(err->message, "Page Timeout")) { + } else if (g_strrstr(err->message, "Page Timeout")) { BT_INFO("Page Timeout"); /* This is the special case As soon as call bluetooth_bond_device, try to cancel bonding. @@ -695,19 +760,17 @@ static void __bt_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res, the procedure is stopped. So 'Cancle' error is not return. */ result = BLUETOOTH_ERROR_HOST_DOWN; - } else if (!strcmp(err->message, BT_TIMEOUT_MESSAGE)) { - g_dbus_proxy_call_sync(proxy, "CancelDeviceCreation", - g_variant_new("(s)", bonding_info->addr), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL); - + } else if (g_strrstr(err->message, BT_DBUS_TIMEOUT_MESSAGE)) { + BT_INFO("Cancel already running bonding"); + if (__bt_cancel_bonding() != BLUETOOTH_ERROR_NONE) { + BT_INFO("Error while Cancelling bonding"); + /* we need to unref proxy so continue */ + } result = BLUETOOTH_ERROR_INTERNAL; - } else if (!strcmp(err->message, "Connection Timeout")) { + } else if (g_strrstr(err->message, "Connection Timeout")) { /* Pairing request timeout */ result = BLUETOOTH_ERROR_TIMEOUT; - } else if (!strcmp(err->message, "Authentication Timeout")) { + } else if (g_strrstr(err->message, "Authentication Timeout")) { /* Pairing request timeout */ result = BLUETOOTH_ERROR_TIMEOUT; } else { @@ -720,58 +783,62 @@ static void __bt_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res, result == BLUETOOTH_ERROR_AUTHENTICATION_FAILED || result == BLUETOOTH_ERROR_TIMEOUT || result == BLUETOOTH_ERROR_HOST_DOWN) { - bonding_info->result = result; -#ifdef TIZEN_WEARABLE - __bt_launch_unable_to_pairing_syspopup(result); +#ifdef TIZEN_PROFILE_WEARABLE + int is_sw_running = 0; + + if (vconf_get_int(VCONFKEY_SETUP_WIZARD_STATE, &is_sw_running)) + BT_ERR("vconf_get_int for setup wizard state failed"); + + if (!is_sw_running) + __bt_launch_unable_to_pairing_syspopup(result); + else + BT_ERR("Unable to pair"); #endif + bonding_info->result = result; } g_object_unref(proxy); bonding_info->device_proxy = NULL; - if (result != BLUETOOTH_ERROR_NONE) - goto dbus_return; + if (result != BLUETOOTH_ERROR_NONE) { + if (bonding_info->bonding_wo_discovery) { + GDBusProxy *adapter_proxy; + GVariant *ret = NULL; + GError *error = NULL; + char *device_path; - remote_dev_info = _bt_get_remote_device_info(bonding_info->addr); - if (NULL == remote_dev_info) { - BT_ERR("Failed to get remote device info"); - goto dbus_return; - } + BT_ERR("Bond was tried without discovery. Remove it"); - GVariant *uuids = NULL; - GVariantBuilder *builder = NULL; - int i = 0; - builder = g_variant_builder_new(G_VARIANT_TYPE("as")); - for (i=0; i < remote_dev_info->uuid_count; i++) { - g_variant_builder_add(builder, "s", - remote_dev_info->uuids[i]); - } - uuids = g_variant_new("as", builder); - g_variant_builder_unref(builder); - manufacture_data = g_variant_new_from_data((const GVariantType *)"ay", - remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len, - TRUE, NULL, NULL); + adapter_proxy = _bt_get_adapter_proxy(); + if (adapter_proxy == NULL) { + BT_ERR("Cannot get adapter_proxy"); + goto dbus_return; + } - param = g_variant_new("(isunsbub@asn@ay)", - result, - bonding_info->addr, - remote_dev_info->class, - remote_dev_info->rssi, - remote_dev_info->name, - remote_dev_info->paired, - remote_dev_info->connected, - remote_dev_info->trust, - uuids, - remote_dev_info->manufacturer_data_len, - manufacture_data); + device_path = _bt_get_device_object_path(bonding_info->addr); + if (device_path == NULL) { + BT_ERR("Cannot get device path"); + goto dbus_return; + } + ret = g_dbus_proxy_call_sync(adapter_proxy, + "RemoveDevice", + g_variant_new("(o)", device_path), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, + &error); + if (error != NULL) { + BT_ERR("RemoveDevice Fail: %s", error->message); + g_clear_error(&error); + } - /* Send the event to application */ - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_BONDING_FINISHED, - param); + if (ret) + g_variant_unref(ret); - _bt_free_device_info(remote_dev_info); + g_free(device_path); + } + + goto dbus_return; + } dbus_return: if (req_info->context == NULL) @@ -791,7 +858,6 @@ dbus_return: g_variant_new("(iv)", result, out_param1)); g_variant_unref(out_param1); -// g_variant_unref(out_param2); _bt_delete_request_list(req_info->req_id); done: @@ -818,6 +884,7 @@ int _bt_bond_device(int request_id, char *device_path = NULL; GDBusProxy *adapter_proxy; GError *error = NULL; + gboolean bonding_wo_discovery = FALSE; BT_CHECK_PARAMETER(device_address, return); @@ -834,7 +901,7 @@ int _bt_bond_device(int request_id, return BLUETOOTH_ERROR_DEVICE_BUSY; } - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); _bt_convert_addr_type_to_string(address, device_address->addr); @@ -873,6 +940,7 @@ int _bt_bond_device(int request_id, } else { BT_INFO("device_path is created[%s]", device_path); } + bonding_wo_discovery = TRUE; } proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, @@ -888,6 +956,7 @@ int _bt_bond_device(int request_id, bonding_info->device_proxy = proxy; bonding_info->conn_type = conn_type; + bonding_info->bonding_wo_discovery = bonding_wo_discovery; is_device_creating = TRUE; @@ -926,7 +995,7 @@ int _bt_cancel_bonding(void) retv_if(bonding_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); ret = _bt_agent_reply_cancellation(); - if (ret != BLUETOOTH_ERROR_NONE){ + if (ret != BLUETOOTH_ERROR_NONE) { BT_ERR("Fail to call reply cancellation"); return ret; } @@ -940,13 +1009,16 @@ static void __bt_unbond_cb(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { GError *err = NULL; + GVariant *reply; GVariant *out_param1; int result = BLUETOOTH_ERROR_NONE; bt_funcion_data_t *unbonding_info; bluetooth_device_info_t dev_info; request_info_t *req_info; - g_dbus_proxy_call_finish(proxy, res, &err); + reply = g_dbus_proxy_call_finish(proxy, res, &err); + if (reply) + g_variant_unref(reply); unbonding_info = user_data; @@ -1014,12 +1086,6 @@ int _bt_unbond_device(int request_id, /* allocate user data so that it can be retrieved in callback */ unbonding_info = g_malloc0(sizeof(bt_funcion_data_t)); - /* Fix : NULL_RETURNS */ - if (unbonding_info == NULL) { - BT_ERR("Memory not allocated !"); - return BLUETOOTH_ERROR_MEMORY_ALLOCATION; - } - unbonding_info->addr = g_malloc0(BT_ADDRESS_STRING_SIZE); unbonding_info->req_id = request_id; @@ -1034,7 +1100,7 @@ int _bt_unbond_device(int request_id, goto fail; } - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); if (conn == NULL) { BT_ERR("conn is NULL"); result = BLUETOOTH_ERROR_INTERNAL; @@ -1076,7 +1142,7 @@ int _bt_unbond_device(int request_id, BT_MAX_DBUS_TIMEOUT, NULL, (GAsyncReadyCallback)__bt_unbond_cb, - NULL); + unbonding_info); g_free(device_path); return BLUETOOTH_ERROR_NONE; @@ -1098,17 +1164,20 @@ static void __bt_discover_cb(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { GError *err = NULL; + GVariant *reply; GVariant *out_param1; int result = BLUETOOTH_ERROR_NONE; bluetooth_device_info_t dev_info; - bt_remote_dev_info_t *remote_dev_info = NULL; + bt_remote_dev_info_t *remote_dev_info; request_info_t *req_info; GVariant *uuid_list, *manufacture_data; GVariant *param; GVariantBuilder *builder = NULL; int i = 0; - g_dbus_proxy_call_finish(proxy, res, &err); + reply = g_dbus_proxy_call_finish(proxy, res, &err); + if (reply) + g_variant_unref(reply); g_object_unref(proxy); @@ -1125,17 +1194,17 @@ static void __bt_discover_cb(GDBusProxy *proxy, GAsyncResult *res, } if (err != NULL) { + g_dbus_error_strip_remote_error(err); BT_ERR("Error occured in Proxy call [%s]\n", err->message); - if (!strcmp("Operation canceled", err->message)) { + if (g_strrstr("Operation canceled", err->message)) result = BLUETOOTH_ERROR_CANCEL_BY_USER; - } else if (!strcmp("In Progress", err->message)) { + else if (g_strrstr("In Progress", err->message)) result = BLUETOOTH_ERROR_IN_PROGRESS; - } else if (!strcmp("Host is down", err->message)) { + else if (g_strrstr("Host is down", err->message)) result = BLUETOOTH_ERROR_HOST_DOWN; - } else { + else result = BLUETOOTH_ERROR_CONNECTION_ERROR; - } if (result == BLUETOOTH_ERROR_HOST_DOWN || result == BLUETOOTH_ERROR_CONNECTION_ERROR) { @@ -1151,14 +1220,12 @@ static void __bt_discover_cb(GDBusProxy *proxy, GAsyncResult *res, } remote_dev_info = _bt_get_remote_device_info(searching_info->addr); - if (NULL == remote_dev_info) { - BT_ERR("Failed to get remote device info"); + if (!remote_dev_info) goto dbus_return; - } event: builder = g_variant_builder_new(G_VARIANT_TYPE("as")); - for (i=0; i < remote_dev_info->uuid_count; i++) { + for (i = 0; i < remote_dev_info->uuid_count; i++) { g_variant_builder_add(builder, "s", remote_dev_info->uuids[i]); } @@ -1181,7 +1248,6 @@ event: remote_dev_info->manufacturer_data_len, manufacture_data); - /* Send the event to application */ _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_SERVICE_SEARCHED, @@ -1249,7 +1315,7 @@ int _bt_search_device(int request_id, _bt_convert_addr_type_to_string(searching_info->addr, device_address->addr); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -1282,8 +1348,6 @@ int _bt_search_device(int request_id, return BLUETOOTH_ERROR_NONE; fail: - if (device_proxy) - g_object_unref(device_proxy); g_free(searching_info->addr); g_free(searching_info); @@ -1293,17 +1357,20 @@ fail: int _bt_cancel_search_device(void) { + GVariant *ret = NULL; GError *err = NULL; retv_if(searching_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); if (searching_info->device_proxy) { - g_dbus_proxy_call_sync(searching_info->device_proxy, "CancelDiscovery", + ret = g_dbus_proxy_call_sync(searching_info->device_proxy, "CancelDiscovery", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); + if (ret) + g_variant_unref(ret); } __bt_cancel_search_service_done(); @@ -1317,6 +1384,7 @@ int _bt_set_alias(bluetooth_device_address_t *device_address, gchar *device_path = NULL; GDBusProxy *adapter_proxy; GDBusProxy *device_proxy; + GVariant *ret = NULL; GError *error = NULL; GDBusConnection *conn; @@ -1326,7 +1394,7 @@ int _bt_set_alias(bluetooth_device_address_t *device_address, adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); _bt_convert_addr_type_to_string(address, device_address->addr); @@ -1345,12 +1413,14 @@ int _bt_set_alias(bluetooth_device_address_t *device_address, g_free(device_path); retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - g_dbus_proxy_call_sync(device_proxy, "Set", + ret = g_dbus_proxy_call_sync(device_proxy, "Set", g_variant_new("(ssv)", BT_DEVICE_INTERFACE, "Alias", g_variant_new("s", alias)), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (ret) + g_variant_unref(ret); g_object_unref(device_proxy); @@ -1373,11 +1443,12 @@ int _bt_set_authorization(bluetooth_device_address_t *device_address, GError *error = NULL; GDBusConnection *conn; GVariant *result = NULL; + GVariant *temp = NULL; int ret = BLUETOOTH_ERROR_NONE; BT_CHECK_PARAMETER(device_address, return); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); _bt_convert_addr_type_to_string(address, device_address->addr); @@ -1397,7 +1468,7 @@ int _bt_set_authorization(bluetooth_device_address_t *device_address, retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); result = g_dbus_proxy_call_sync(device_proxy, "Get", - g_variant_new("(ss)", BT_DEVICE_INTERFACE, "Trusted" ), + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "Trusted"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, @@ -1409,7 +1480,9 @@ int _bt_set_authorization(bluetooth_device_address_t *device_address, return BLUETOOTH_ERROR_INTERNAL; } - previous_value = g_variant_get_boolean(result); + g_variant_get(result, "(v)", &temp); + previous_value = g_variant_get_boolean(temp); + g_variant_unref(temp); g_variant_unref(result); /* If the input is same with previous value, return error. */ if (previous_value == authorize) { @@ -1419,8 +1492,8 @@ int _bt_set_authorization(bluetooth_device_address_t *device_address, goto done; } - g_dbus_proxy_call_sync(device_proxy, "Set", - g_variant_new("(ssv)", BT_DEVICE_INTERFACE, "Trusted", g_variant_new("b",authorize)), + result = g_dbus_proxy_call_sync(device_proxy, "Set", + g_variant_new("(ssv)", BT_DEVICE_INTERFACE, "Trusted", g_variant_new("b", authorize)), G_DBUS_CALL_FLAGS_NONE, -1, NULL, @@ -1433,6 +1506,9 @@ int _bt_set_authorization(bluetooth_device_address_t *device_address, ret = BLUETOOTH_ERROR_INTERNAL; } done: + if (result) + g_variant_unref(result); + return ret; } @@ -1445,14 +1521,13 @@ int _bt_is_gatt_connected(bluetooth_device_address_t *device_address, GDBusProxy *device_proxy; GError *error = NULL; GVariant *value; - GVariant *tmp_value; GDBusConnection *conn; GVariant *result = NULL; int ret = BLUETOOTH_ERROR_NONE; BT_CHECK_PARAMETER(device_address, return); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); _bt_convert_addr_type_to_string(address, device_address->addr); @@ -1461,37 +1536,33 @@ int _bt_is_gatt_connected(bluetooth_device_address_t *device_address, retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, - NULL, BT_BLUEZ_NAME, - object_path, BT_PROPERTIES_INTERFACE, NULL, NULL); + NULL, BT_BLUEZ_NAME, object_path, + BT_PROPERTIES_INTERFACE, NULL, NULL); g_free(object_path); retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - result = g_dbus_proxy_call_sync(device_proxy, "GetAll", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - - if (error != NULL || result == NULL) { - BT_ERR("Error occured in Proxy call [%s]\n", error->message); - g_error_free(error); + result = g_dbus_proxy_call_sync(device_proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, + "GattConnected"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (result == NULL) { + if (error != NULL) { + BT_ERR("Error occured in Proxy call [%s]\n", error->message); + g_error_free(error); + } g_object_unref(device_proxy); return BLUETOOTH_ERROR_INTERNAL; } - g_variant_get(result , "(@a{sv})", &value); + g_variant_get(result, "(v)", &value); + *is_connected = g_variant_get_boolean(value); g_variant_unref(result); - tmp_value = g_variant_lookup_value (value, "GattConnected", G_VARIANT_TYPE_BOOLEAN); - if (tmp_value != NULL) { - g_object_unref(device_proxy); - return BLUETOOTH_ERROR_INTERNAL; - } - *is_connected = g_variant_get_boolean (tmp_value); - BT_DBG("gatt is connected : %d", *is_connected); - g_variant_unref(tmp_value); + g_variant_unref(value); g_object_unref(device_proxy); @@ -1503,6 +1574,7 @@ int _bt_is_device_connected(bluetooth_device_address_t *device_address, { char *object_path = NULL; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 }; GDBusProxy *device_proxy = NULL; GDBusProxy *adapter_proxy = NULL; GDBusConnection *conn; @@ -1515,23 +1587,29 @@ int _bt_is_device_connected(bluetooth_device_address_t *device_address, retv_if(device_address == NULL, BLUETOOTH_ERROR_INVALID_PARAM); retv_if(is_connected == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + _bt_convert_addr_type_to_string(address, device_address->addr); + _bt_convert_addr_string_to_secure_string(secure_address, address); + *is_connected = FALSE; - BT_DBG("connection_type: %d", connection_type); + BT_DBG("%s connection_type: 0x%02x", secure_address, connection_type); + if (connection_type == BLUETOOTH_RFCOMM_SERVICE) return _bt_rfcomm_is_device_connected(device_address, is_connected); else if (connection_type == BLUETOOTH_GATT_SERVICE) return _bt_is_gatt_connected(device_address, is_connected); + else if (connection_type == BLUETOOTH_PBAP_SERVICE) + return _bt_pbap_is_connected(device_address, is_connected); adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); _bt_convert_addr_type_to_string(address, device_address->addr); - if(connection_type == BLUETOOTH_NAP_SERVER_SERVICE) { + if (connection_type == BLUETOOTH_NAP_SERVER_SERVICE) { object_path = _bt_get_adapter_path(); device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL, BT_BLUEZ_NAME, @@ -1550,37 +1628,38 @@ int _bt_is_device_connected(bluetooth_device_address_t *device_address, &error); if (result == NULL) { - BT_ERR("Error occured in Proxy call"); + BT_ERR("[GetProperties] Error occured in Proxy call"); if (error) { - BT_ERR("Error occured in Proxy call [%s]\n", error->message); + BT_ERR("%s", error->message); g_error_free(error); } + *is_connected = FALSE; g_object_unref(device_proxy); - return BLUETOOTH_ERROR_INTERNAL; + return BLUETOOTH_ERROR_NONE; } g_variant_get(result , "(@a{sv})", &value); g_variant_unref(result); - - tmp_value = g_variant_lookup_value (value, "Connected", G_VARIANT_TYPE_BOOLEAN); - if (tmp_value != NULL) { - g_object_unref(device_proxy); - return BLUETOOTH_ERROR_INTERNAL; + if (value) { + tmp_value = g_variant_lookup_value(value, + "Connected", + G_VARIANT_TYPE_BOOLEAN); + if (tmp_value) { + *is_connected = g_variant_get_boolean(tmp_value); + g_variant_unref(tmp_value); + } + g_variant_unref(value); } - *is_connected = g_variant_get_boolean (tmp_value); - g_variant_unref(tmp_value); - g_variant_unref(value); - } else if(connection_type == BLUETOOTH_NAP_SERVICE) { + } else if (connection_type == BLUETOOTH_NAP_SERVICE) { return _bt_is_network_connected(_bt_get_net_conn(), device_address->addr, is_connected); } else { uuid = _bt_get_profile_uuid128(connection_type); if (uuid == NULL) { - BT_ERR("uuid is NULL"); + BT_ERR("connection_type: %d, uuid is NULL", connection_type); return BLUETOOTH_ERROR_INTERNAL; } - - BT_DBG("uuid: %s", uuid); + BT_DBG("uuid %s [%s]", uuid, _bt_convert_uuid_to_string(uuid)); object_path = _bt_get_device_object_path(address); retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); @@ -1603,13 +1682,17 @@ int _bt_is_device_connected(bluetooth_device_address_t *device_address, &error); if (result == NULL) { - BT_ERR("Error occured in Proxy call"); + BT_ERR("[IsConnectedProfile] Error occured in Proxy call"); if (error) { - BT_ERR("Error occured in Proxy call [%s]\n", error->message); + BT_ERR("%s", error->message); + if (g_strrstr(error->message, "Not Connected")) + BT_DBG("Not connected"); g_error_free(error); } + *is_connected = FALSE; g_object_unref(device_proxy); - return BLUETOOTH_ERROR_INTERNAL; + g_free(uuid); + return BLUETOOTH_ERROR_NONE; } g_variant_get(result, "(b)", is_connected); g_free(uuid); @@ -1629,15 +1712,12 @@ int _bt_get_connected_link(bluetooth_device_address_t *device_address, GDBusProxy *device_proxy; GError *error = NULL; GDBusConnection *conn; - GVariant *tmp_value = NULL; GVariant *value = NULL; GVariant *result = NULL; - int ret = BLUETOOTH_ERROR_NONE; - BT_CHECK_PARAMETER(device_address, return); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); _bt_convert_addr_type_to_string(address, device_address->addr); @@ -1654,38 +1734,266 @@ int _bt_get_connected_link(bluetooth_device_address_t *device_address, return BLUETOOTH_ERROR_NONE; } - result = g_dbus_proxy_call_sync(device_proxy, "GetAll", - g_variant_new("(s)", BT_DEVICE_INTERFACE), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); + result = g_dbus_proxy_call_sync(device_proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "Connected"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { BT_ERR("Error occured in Proxy call [%s]\n", error->message); g_error_free(error); g_object_unref(device_proxy); return BLUETOOTH_ERROR_INTERNAL; + } else { + g_variant_get(result, "(v)", &value); + *connected = g_variant_get_byte(value); + g_variant_unref(value); + g_variant_unref(result); } - g_variant_get(result , "(@a{sv})", &value); - g_variant_unref(result); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_NONE; +} + +static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res, + gpointer user_data) +{ + GError *err = NULL; + GVariant *out_param1; + GVariant *reply; + int result = BLUETOOTH_ERROR_NONE; + bt_function_data_t *func_data = user_data; + request_info_t *req_info = NULL; + bluetooth_device_address_t device_addr = { {0} }; + + reply = g_dbus_proxy_call_finish(proxy, res, &err); + g_object_unref(proxy); + + if (reply == NULL) { + BT_ERR("ConnectLE / DisconnectLE DBus call error"); + if (err) { + BT_ERR("Error: %s", err->message); + g_clear_error(&err); + } + result = BLUETOOTH_ERROR_INTERNAL; + } else { + g_variant_unref(reply); + } + + if (func_data == NULL) { + BT_ERR("func_data is NULL"); + goto done; + } + + req_info = _bt_get_request_info(func_data->req_id); + if (req_info == NULL) { + BT_ERR("req_info is NULL"); + goto done; + } + + if (req_info->context == NULL) { + BT_ERR("req_info->context is NULL"); + goto done; + } + + _bt_convert_addr_string_to_type(device_addr.addr, + (const char *)func_data->address); + + out_param1 = g_variant_new_from_data((const GVariantType *)"ay", + &device_addr, sizeof(bluetooth_device_address_t), TRUE, + NULL, NULL); + + g_dbus_method_invocation_return_value(req_info->context, + g_variant_new("(iv)", result, out_param1)); - tmp_value = g_variant_lookup_value (value, "Connected", G_VARIANT_TYPE_BOOLEAN); - if (tmp_value != NULL) { +done: + if (req_info) + _bt_delete_request_list(req_info->req_id); + + if (func_data) { + g_free(func_data->address); + g_free(func_data); + } +} + +static int __bt_connect_le_device_internal(int req_id, const bluetooth_device_address_t *bd_addr, + gboolean auto_connect) +{ + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + GDBusProxy *device_proxy = NULL; + GDBusConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + bt_function_data_t *func_data; + + BT_CHECK_PARAMETER(bd_addr, return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)bd_addr->addr); + device_path = _bt_get_device_object_path(device_address); + if (device_path == NULL) { + BT_ERR_C("device_path NULL : [%s]", device_address); + ret = BLUETOOTH_ERROR_INTERNAL; + return ret; + } + + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE, NULL, NULL); + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + func_data = g_malloc0(sizeof(bt_function_data_t)); + func_data->address = g_strdup(device_address); + if (func_data->address == NULL) { + BT_ERR("Unable to allocate memory for address"); + ret = BLUETOOTH_ERROR_MEMORY_ALLOCATION; + goto fail; + } + + _bt_convert_addr_string_to_secure_string(secure_address, device_address); + BT_INFO("Connect LE [%s]", secure_address); + + func_data->req_id = req_id; + + g_dbus_proxy_call(device_proxy, "ConnectLE", + g_variant_new("(b)", auto_connect), + G_DBUS_CALL_FLAGS_NONE, + BT_MAX_DBUS_TIMEOUT, + NULL, + (GAsyncReadyCallback)__le_connection_req_cb, func_data); + + return ret; + +fail: + if (device_proxy) g_object_unref(device_proxy); - g_variant_unref(value); - return BLUETOOTH_ERROR_INTERNAL; + + g_free(func_data->address); + g_free(func_data); + + return ret; +} + +static gboolean __bt_connect_le_timer_cb(gpointer user_data) +{ + BT_INFO("Try to initiate pending LE connection"); + + pending_le_conn_timer_id = 0; + + __bt_connect_le_device_internal(pending_le_conn_info->req_id, + &pending_le_conn_info->bd_addr, + pending_le_conn_info->auto_connect); + + g_free(pending_le_conn_info); + pending_le_conn_info = NULL; + + return FALSE; +} + +void _bt_pending_connect_le_device(void) +{ + if (pending_le_conn_timer_id > 0) { + g_source_remove(pending_le_conn_timer_id); + __bt_connect_le_timer_cb(NULL); } - *connected = g_variant_get_boolean (tmp_value); - g_variant_unref(tmp_value); - g_variant_unref(value); - g_object_unref(device_proxy); +} + +int _bt_connect_le_device(int req_id, const bluetooth_device_address_t *bd_addr, + gboolean auto_connect) +{ + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(bd_addr, return); + + ret = _bt_hold_current_advertising(); + if (ret == BLUETOOTH_ERROR_NONE) { + BT_INFO("Current advertising is held"); + pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s)); + pending_le_conn_info->req_id = req_id; + memcpy(pending_le_conn_info->bd_addr.addr, bd_addr->addr, + BLUETOOTH_ADDRESS_LENGTH); + pending_le_conn_info->auto_connect = auto_connect; + + pending_le_conn_timer_id = + g_timeout_add(1000, __bt_connect_le_timer_cb, NULL); + + return BLUETOOTH_ERROR_NONE; + } else if (ret != BLUETOOTH_ERROR_NOT_IN_OPERATION) { + BT_ERR("Unable to hold advertising"); + } + + return __bt_connect_le_device_internal(req_id, bd_addr, auto_connect); +} + +int _bt_disconnect_le_device(int req_id, + const bluetooth_device_address_t *bd_addr) +{ + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path; + GDBusProxy *device_proxy; + GDBusConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + bt_function_data_t *func_data; + + BT_CHECK_PARAMETER(bd_addr, return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)bd_addr->addr); + device_path = _bt_get_device_object_path(device_address); + if (device_path == NULL) { + BT_DBG("device_path NULL"); + ret = BLUETOOTH_ERROR_INTERNAL; + return ret; + } + + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE, NULL, NULL); + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + func_data = g_malloc0(sizeof(bt_function_data_t)); + func_data->address = g_strdup(device_address); + if (func_data->address == NULL) { + BT_ERR("Unable to allocate memory for address"); + ret = BLUETOOTH_ERROR_MEMORY_ALLOCATION; + goto fail; + } + + _bt_convert_addr_string_to_secure_string(secure_address, device_address); + BT_INFO("Disconnect LE [%s]", secure_address); + + func_data->req_id = req_id; + + g_dbus_proxy_call(device_proxy, "DisconnectLE", + NULL, + G_DBUS_CALL_FLAGS_NONE, + BT_MAX_DBUS_TIMEOUT, + NULL, + (GAsyncReadyCallback)__le_connection_req_cb, func_data); + return ret; + +fail: + if (device_proxy) + g_object_unref(device_proxy); + + g_free(func_data->address); + g_free(func_data); return ret; } -int _bt_connect_le_device(const bluetooth_device_address_t *bd_addr, gboolean auto_connect) +int _bt_connect_le_ipsp_device(const bluetooth_device_address_t *bd_addr) { char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; gchar *device_path = NULL; @@ -1694,13 +2002,14 @@ int _bt_connect_le_device(const bluetooth_device_address_t *bd_addr, gboolean au GDBusProxy *adapter_proxy; GDBusConnection *conn; int ret = BLUETOOTH_ERROR_NONE; + GVariant *result; BT_CHECK_PARAMETER(bd_addr, return); _bt_convert_addr_type_to_string(device_address, (unsigned char *)bd_addr->addr); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); adapter_proxy = _bt_get_adapter_proxy(); @@ -1716,23 +2025,26 @@ int _bt_connect_le_device(const bluetooth_device_address_t *bd_addr, gboolean au retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, - NULL, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE, NULL, NULL); + NULL, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE, NULL, NULL); g_free(device_path); retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - g_dbus_proxy_call_sync(device_proxy, "ConnectLE", - g_variant_new("(b)", auto_connect), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - - if (error) { - BT_ERR("ConnectLE Call Error %s[%s]", error->message, device_address); - g_error_free(error); - g_object_unref(device_proxy); - return BLUETOOTH_ERROR_INTERNAL; + result = g_dbus_proxy_call_sync(device_proxy, "ConnectIpsp", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!result) { + if (error) { + BT_ERR("ConnectIpsp Call Error %s[%s]", error->message, device_address); + g_error_free(error); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + } else { + g_variant_unref(result); } g_object_unref(device_proxy); @@ -1740,7 +2052,7 @@ int _bt_connect_le_device(const bluetooth_device_address_t *bd_addr, gboolean au return ret; } -int _bt_disconnect_le_device(const bluetooth_device_address_t *bd_addr) +int _bt_disconnect_le_ipsp_device(const bluetooth_device_address_t *bd_addr) { char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; gchar *device_path = NULL; @@ -1749,13 +2061,14 @@ int _bt_disconnect_le_device(const bluetooth_device_address_t *bd_addr) GDBusProxy *adapter_proxy; GDBusConnection *conn; int ret = BLUETOOTH_ERROR_NONE; + GVariant *result; BT_CHECK_PARAMETER(bd_addr, return); _bt_convert_addr_type_to_string(device_address, (unsigned char *)bd_addr->addr); - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); adapter_proxy = _bt_get_adapter_proxy(); @@ -1771,22 +2084,26 @@ int _bt_disconnect_le_device(const bluetooth_device_address_t *bd_addr) retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, - NULL, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE, NULL, NULL); + NULL, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE, NULL, NULL); g_free(device_path); retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - g_dbus_proxy_call_sync(device_proxy, "DisconnectLE", + result = g_dbus_proxy_call_sync(device_proxy, "DisconnectIpsp", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (error) { - BT_ERR("DisconnectLE Call Error %s[%s]", error->message, device_address); - g_error_free(error); - g_object_unref(device_proxy); - return BLUETOOTH_ERROR_INTERNAL; + if (!result) { + if (error) { + BT_ERR("DisconnectIpsp Call Error %s[%s]", error->message, device_address); + g_error_free(error); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + } else { + g_variant_unref(result); } g_object_unref(device_proxy); @@ -1801,9 +2118,10 @@ int _bt_connect_profile(char *address, char *uuid, GDBusProxy *proxy; GDBusConnection *conn; GDBusProxy *adapter_proxy; + GVariant *result = NULL; GError *error = NULL; - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); object_path = _bt_get_device_object_path(address); @@ -1813,7 +2131,7 @@ int _bt_connect_profile(char *address, char *uuid, adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice", + result = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice", g_variant_new("(s)", address), G_DBUS_CALL_FLAGS_NONE, -1, @@ -1824,6 +2142,8 @@ int _bt_connect_profile(char *address, char *uuid, BT_ERR("CreateDevice Fail: %s", error->message); g_error_free(error); } + if (result) + g_variant_unref(result); object_path = _bt_get_device_object_path(address); } @@ -1846,6 +2166,47 @@ int _bt_connect_profile(char *address, char *uuid, return BLUETOOTH_ERROR_NONE; } +int _bt_disconnect_all(char *address) +{ + int ret = BLUETOOTH_ERROR_NONE; + char *object_path; + GDBusProxy *proxy; + GDBusConnection *conn; + GVariant *result = NULL; + GError *err = NULL; + + BT_DBG(""); + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE, NULL, NULL); + g_free(object_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(proxy, "Disconnect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, + &err); + + if (err != NULL) { + BT_ERR("Dbus Call Error:[%s]", err->message); + g_error_free(err); + ret = BLUETOOTH_ERROR_INTERNAL; + } + + g_object_unref(proxy); + if (result) + g_variant_unref(result); + + return ret; +} + int _bt_disconnect_profile(char *address, char *uuid, void *cb, gpointer func_data) { @@ -1853,7 +2214,7 @@ int _bt_disconnect_profile(char *address, char *uuid, GDBusProxy *proxy; GDBusConnection *conn; - conn = _bt_get_system_gconn(); + conn = _bt_gdbus_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); object_path = _bt_get_device_object_path(address); @@ -1881,6 +2242,7 @@ int _bt_enable_rssi(bluetooth_device_address_t *bd_addr, int link_type, { int ret = BLUETOOTH_ERROR_NONE; GDBusProxy *proxy; + GVariant *result = NULL; GError *error = NULL; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; @@ -1898,7 +2260,7 @@ int _bt_enable_rssi(bluetooth_device_address_t *bd_addr, int link_type, proxy = _bt_get_adapter_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - g_dbus_proxy_call_sync(proxy, "EnableRssi", + result = g_dbus_proxy_call_sync(proxy, "EnableRssi", g_variant_new("(siiii)", address, link_type, low_threshold, in_range_threshold, high_threshold), G_DBUS_CALL_FLAGS_NONE, -1, @@ -1909,6 +2271,10 @@ int _bt_enable_rssi(bluetooth_device_address_t *bd_addr, int link_type, g_error_free(error); ret = BLUETOOTH_ERROR_INTERNAL; } + + if (result) + g_variant_unref(result); + return ret; } @@ -1917,6 +2283,7 @@ int _bt_get_rssi_strength(bluetooth_device_address_t *bd_addr, { int ret = BLUETOOTH_ERROR_NONE; GDBusProxy *proxy; + GVariant *result = NULL; GError *error = NULL; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; @@ -1932,7 +2299,7 @@ int _bt_get_rssi_strength(bluetooth_device_address_t *bd_addr, proxy = _bt_get_adapter_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - g_dbus_proxy_call_sync(proxy, "GetRssiStrength", + result = g_dbus_proxy_call_sync(proxy, "GetRssiStrength", g_variant_new("(si)", address, link_type), G_DBUS_CALL_FLAGS_NONE, -1, @@ -1944,30 +2311,310 @@ int _bt_get_rssi_strength(bluetooth_device_address_t *bd_addr, g_error_free(error); ret = BLUETOOTH_ERROR_INTERNAL; } + + if (result) + g_variant_unref(result); + return ret; } -int _bt_le_conn_update(unsigned char *device_address, - guint16 interval_min, guint16 interval_max, +static int __bt_le_set_conn_parameter(const char *address, + float interval_min, float interval_max, guint16 latency, guint16 time_out) { - char address[BT_ADDRESS_STRING_SIZE] = { 0 }; gchar *device_path = NULL; GError *error = NULL; GDBusProxy *device_proxy = NULL; GDBusConnection *conn; GVariant *reply; guint32 min, max, to; - guint32 min_supervision_to; int ret = BLUETOOTH_ERROR_NONE; - BT_DBG("+"); + BT_CHECK_PARAMETER(address, return); - BT_CHECK_PARAMETER(device_address, return); - - BT_DBG("Min interval: %u, Max interval: %u, Latency: %u, Supervision timeout: %u", + BT_INFO("Min interval: %f, Max interval: %f, Latency: %u, Supervision timeout: %u", interval_min, interval_max, latency, time_out); + device_path = _bt_get_device_object_path((char *)address); + + if (device_path == NULL) { + BT_ERR("device_path NULL"); + ret = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + conn = _bt_gdbus_get_system_gconn(); + if (conn == NULL) { + BT_ERR("conn NULL"); + ret = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE, NULL, NULL); + + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + min = interval_min / BT_LE_CONN_INTERVAL_SPLIT; + max = interval_max / BT_LE_CONN_INTERVAL_SPLIT; + to = time_out / BT_LE_CONN_TO_SPLIT; + + reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate", + g_variant_new("(uuuu)", min, max, latency, to), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + g_object_unref(device_proxy); + if (reply == NULL) { + if (error) { + BT_ERR("Error %s[%s]", error->message, address); + if (g_strrstr(error->message, "In Progress")) + ret = BLUETOOTH_ERROR_IN_PROGRESS; + else + ret = BLUETOOTH_ERROR_INTERNAL; + g_error_free(error); + return ret; + } + } + g_variant_unref(reply); + +fail: + return ret; +} + +static void __bt_le_conn_param_free(void *data) +{ + bt_le_conn_param_t *param = (bt_le_conn_param_t *)data; + + BT_DBG("%s", param->sender); + g_free(param->sender); + g_free(param); +} + +static gint __bt_compare_le_conn_param_key(gpointer *a, gpointer *b) +{ + bt_le_conn_param_t *parama = (bt_le_conn_param_t *)a; + bt_le_conn_param_t *paramb = (bt_le_conn_param_t *)b; + + return parama->key > paramb->key; +} + +static bt_connected_le_dev_t *__bt_get_le_connected_dev_info(const char *address) +{ + GSList *l = NULL; + bt_connected_le_dev_t *dev; + + if (!address) + return NULL; + + for (l = le_connected_dev_list; l; l = g_slist_next(l)) { + dev = l->data; + + if (g_strcmp0(dev->address, address) == 0) + return dev; + } + return NULL; +} + +static bt_le_conn_param_t *__bt_get_le_conn_param_info(bt_connected_le_dev_t *dev, const char *sender) +{ + GSList *l = NULL; + bt_le_conn_param_t *param = NULL; + + if (!dev || !sender) + return NULL; + + for (l = dev->senders; l; l = g_slist_next(l)) { + param = l->data; + if (g_strcmp0(param->sender, sender) == 0) + return param; + } + + return NULL; +} + +int _bt_add_le_conn_param_info(const char *address, const char *sender, + float interval_min, float interval_max, guint16 latency, guint16 time_out) +{ + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + bt_le_conn_param_t *data = NULL; + + if (!address || !sender) + return BLUETOOTH_ERROR_INVALID_PARAM; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return BLUETOOTH_ERROR_INTERNAL; + + param = __bt_get_le_conn_param_info(dev, sender); + + data = g_malloc0(sizeof(bt_le_conn_param_t)); + data->sender = g_strdup(sender); + data->interval_min = interval_min; + data->interval_max = interval_max; + data->latency = latency; + data->time_out = time_out; + data->key = interval_min + (interval_max - interval_min)/2; + + if (param == NULL) { + BT_DBG("Add param %s %s %f %f", address, sender, interval_min, interval_max); + dev->senders = g_slist_append(dev->senders, data); + } else { + BT_DBG("Update param %s %s %f %f", address, sender, interval_min, interval_max); + dev->senders = g_slist_remove(dev->senders, param); + g_free(param->sender); + g_free(param); + dev->senders = g_slist_append(dev->senders, data); + } + + /* Sorting. First element have the minimum interval */ + dev->senders = g_slist_sort(dev->senders, + (GCompareFunc)__bt_compare_le_conn_param_key); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_remove_le_conn_param_info(const char *address, const char *sender, gboolean *is_removed) +{ + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + + if (!address || !sender) + return BLUETOOTH_ERROR_INVALID_PARAM; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return BLUETOOTH_ERROR_INTERNAL; + + param = __bt_get_le_conn_param_info(dev, sender); + if (param) { + BT_DBG("Remove param %s %s ", address, sender); + dev->senders = g_slist_remove(dev->senders, param); + g_free(param->sender); + g_free(param); + *is_removed = TRUE; + } else + *is_removed = FALSE; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_remove_all_le_conn_param_info(const char *sender) +{ + GSList *l = NULL; + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + gboolean is_removed = FALSE; + char *sender_new = NULL; + unsigned char addr[BLUETOOTH_ADDRESS_LENGTH]; + int ret = BLUETOOTH_ERROR_NONE; + + if (!sender) + return BLUETOOTH_ERROR_INVALID_PARAM; + + for (l = le_connected_dev_list; l; l = g_slist_next(l)) { + dev = l->data; + _bt_remove_le_conn_param_info(dev->address, sender, &is_removed); + + if (is_removed) { + BT_INFO("Sender terminated. Update le conn interval [senders %d]", + g_slist_length(dev->senders)); + if (g_slist_length(dev->senders) > 0) { + param = dev->senders->data; + BT_DBG("dev %f %f, param %f %f", dev->interval_min, dev->interval_max, + param->interval_min, param->interval_max); + + if (dev->interval_min != param->interval_min || + dev->interval_max != param->interval_max) { + sender_new = g_strdup(param->sender); + + _bt_convert_addr_string_to_type(addr, dev->address); + ret = _bt_le_conn_update(sender_new, addr, + param->interval_min, param->interval_max, + param->latency, param->time_out); + g_free(sender_new); + + if (ret != BLUETOOTH_ERROR_NONE) + BT_ERR("Unable to set le connection parameter"); + } + } else { + BT_INFO("Set the default interval"); + + bluetooth_le_connection_param_t param = { 0 }; + _bt_get_le_connection_parameter( + BLUETOOTH_LE_CONNECTION_MODE_LOW_POWER, + ¶m); + + ret = __bt_le_set_conn_parameter(dev->address, + param.interval_min, param.interval_max, + param.latency, param.timeout); + if (ret == BLUETOOTH_ERROR_NONE) { + dev->interval_min = param.interval_min; + dev->interval_max = param.interval_max; + } + } + } + } + + return ret; +} + +void _bt_add_le_connected_dev_info(const char *address) +{ + bt_connected_le_dev_t *dev = NULL; + + if (!address) + return; + + dev = g_malloc0(sizeof(bt_connected_le_dev_t)); + dev->address = g_strdup(address); + + le_connected_dev_list = g_slist_append(le_connected_dev_list, dev); + + return; +} + +void _bt_remove_le_connected_dev_info(const char *address) +{ + bt_connected_le_dev_t *dev = NULL; + + if (!address) + return; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return; + + g_slist_free_full(dev->senders, __bt_le_conn_param_free); + le_connected_dev_list = g_slist_remove(le_connected_dev_list, dev); + g_free(dev->address); + g_free(dev); + + return; +} + +int _bt_le_conn_update(const char *sender, + unsigned char *device_address, + float interval_min, float interval_max, + guint16 latency, guint16 time_out) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + guint32 min_supervision_to; + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + gboolean is_removed = FALSE; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(device_address, return); + + BT_DBG("Sender %s, Min interval: %f, Max interval: %f, Latency: %u, Supervision timeout: %u", + sender, interval_min, interval_max, latency, time_out); + if (interval_min > interval_max || interval_min < BT_LE_CONN_INTERVAL_MIN || interval_max > BT_LE_CONN_INTERVAL_MAX) { @@ -1998,54 +2645,805 @@ int _bt_le_conn_update(unsigned char *device_address, } _bt_convert_addr_type_to_string(address, device_address); - BT_DBG("Remote device address: %s", address); - device_path = _bt_get_device_object_path(address); + _bt_add_le_conn_param_info(address, sender, interval_min, interval_max, 0, 2000); - if (device_path == NULL) { - BT_DBG("device_path NULL"); - ret = BLUETOOTH_ERROR_INTERNAL; + dev = __bt_get_le_connected_dev_info(address); + if (dev == NULL) { + ret = BLUETOOTH_ERROR_NOT_CONNECTED; goto fail; } - conn = _bt_get_system_gconn(); - if (conn == NULL) { - BT_DBG("conn NULL"); - ret = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } + if (g_slist_length(dev->senders) == 1) + goto update; + else { + param = dev->senders->data; - device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, - NULL, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE, NULL, NULL); + BT_DBG("dev %f, param %f, input %f", dev->interval_min, param->interval_min, interval_min); - g_free(device_path); - retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + if (dev->interval_min == param->interval_min && dev->interval_max == param->interval_max) { + BT_DBG("Skip due to same interval"); + return ret; + } - min = interval_min / BT_LE_CONN_INTERVAL_SPLIT; - max = interval_max / BT_LE_CONN_INTERVAL_SPLIT; - to = time_out / BT_LE_CONN_TO_SPLIT; + interval_min = param->interval_min; + interval_max = param->interval_max; + } - reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate", - g_variant_new("(uuuu)", min, max, latency, to), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); +update: + ret = __bt_le_set_conn_parameter(address, interval_min, interval_max, latency, time_out); - g_object_unref(device_proxy); - BT_ERR("LeConnUpdate Call Error for %s", address); - if (reply == NULL) { - if (error) { - BT_ERR("Error %s[%s]", error->message, address); - g_error_free(error); - return BLUETOOTH_ERROR_INTERNAL; - } + if (ret != BLUETOOTH_ERROR_NONE) { + _bt_remove_le_conn_param_info(address, sender, &is_removed); + return ret; } - g_variant_unref(reply); - BT_DBG("-"); + + dev->interval_min = interval_min; + dev->interval_max = interval_max; fail: return ret; } + +int _bt_set_pin_code(bluetooth_device_address_t *device_address, + bluetooth_device_pin_code_t *pin_code) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GSList *l = NULL; + bt_pin_code_info_t *pin_info = NULL; + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_PARAMETER(pin_code, return); + retv_if(g_slist_length(pin_info_list) >= BT_DEVICE_PIN_CODE_SLOT_MAX, + BLUETOOTH_ERROR_NO_RESOURCES); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + for (l = pin_info_list; l != NULL; l = l->next) { + pin_info = l->data; + + if (g_strcmp0(pin_info->address, address) == 0) { + g_free(pin_info->pin_code); + pin_info->pin_code = g_strdup(pin_code->pin_code); + return BLUETOOTH_ERROR_NONE; + } + } + + pin_info = g_malloc0(sizeof(bt_pin_code_info_t)); + pin_info->address = g_strdup(address); + pin_info->pin_code = g_strdup(pin_code->pin_code); + pin_info_list = g_slist_append(pin_info_list, pin_info); + + return BLUETOOTH_ERROR_NONE; +} + +gint __bt_compare_address(gpointer *a, gpointer *b) +{ + bt_pin_code_info_t *pin_info = (bt_pin_code_info_t *)a; + char *address = (char *)b; + return g_strcmp0(pin_info->address, address); +} + +int _bt_unset_pin_code(bluetooth_device_address_t *device_address) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GSList *l = NULL; + bt_pin_code_info_t *pin_info = NULL; + + BT_CHECK_PARAMETER(device_address, return); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + l = g_slist_find_custom(pin_info_list, address, + (GCompareFunc)__bt_compare_address); + if (l) + pin_info = l->data; + if (pin_info) { + pin_info_list = g_slist_remove(pin_info_list, pin_info); + g_free(pin_info->address); + g_free(pin_info->pin_code); + g_free(pin_info); + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_device_pin_code(const char *address, char *pin_code) +{ + GSList *l = NULL; + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(pin_code, return); + + for (l = pin_info_list; l != NULL; l = l->next) { + bt_pin_code_info_t *pin_info = l->data; + + if (g_strcmp0(pin_info->address, address) == 0) { + g_strlcpy(pin_code, pin_info->pin_code, + BLUETOOTH_PIN_CODE_MAX_LENGTH + 1); + + return BLUETOOTH_ERROR_NONE; + } + } + + return BLUETOOTH_ERROR_NOT_FOUND; +} + +int _bt_get_le_connection_parameter(bluetooth_le_connection_mode_t mode, + bluetooth_le_connection_param_t *param) +{ + if (param == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (mode < BLUETOOTH_LE_CONNECTION_MODE_BALANCED || + mode > BLUETOOTH_LE_CONNECTION_MODE_LOW_POWER) + return BLUETOOTH_ERROR_INVALID_PARAM; + + memset(param, 0x00, sizeof(bluetooth_le_connection_param_t)); + + switch (mode) { + case BLUETOOTH_LE_CONNECTION_MODE_BALANCED: + param->interval_min = BT_LE_CONN_PARAM_BALANCED_MIN_INTERVAL; + param->interval_max = BT_LE_CONN_PARAM_BALANCED_MAX_INTERVAL; + param->latency = BT_LE_CONN_PARAM_BALANCED_SLAVE_LATENCY; + param->timeout = BT_LE_CONN_PARAM_DEFAULT_SUPERVISION_TIMEOUT; + break; + + case BLUETOOTH_LE_CONNECTION_MODE_LOW_LATENCY: + param->interval_min = BT_LE_CONN_PARAM_LOW_LATENCY_MIN_INTERVAL; + param->interval_max = BT_LE_CONN_PARAM_LOW_LATENCY_MAX_INTERVAL; + param->latency = BT_LE_CONN_PARAM_LOW_LATENCY_SLAVE_LATENCY; + param->timeout = BT_LE_CONN_PARAM_DEFAULT_SUPERVISION_TIMEOUT; + break; + + case BLUETOOTH_LE_CONNECTION_MODE_LOW_POWER: + param->interval_min = BT_LE_CONN_PARAM_LOW_POWER_MIN_INTERVAL; + param->interval_max = BT_LE_CONN_PARAM_LOW_POWER_MAX_INTERVAL; + param->latency = BT_LE_CONN_PARAM_LOW_POWER_SLAVE_LATENCY; + param->timeout = BT_LE_CONN_PARAM_DEFAULT_SUPERVISION_TIMEOUT; + break; + + default: + BT_ERR("Unhandled mode : %d", mode); + break; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_trusted_profile_from_flag(bluetooth_trusted_profile_t profile, + guint trusted_profile_flag, guint *trusted) +{ + int trust_profile; + *trusted = FALSE; + + switch (profile) { + case TRUSTED_PROFILE_PBAP: + if (trusted_profile_flag & (PROFILE_SUPPORTED << 0)) + trust_profile = trusted_profile_flag & (1 << 1); + else + return BLUETOOTH_ERROR_NOT_SUPPORT; + break; + case TRUSTED_PROFILE_MAP: + if (trusted_profile_flag & (PROFILE_SUPPORTED << 2)) + trust_profile = trusted_profile_flag & (1 << 3); + else + return BLUETOOTH_ERROR_NOT_SUPPORT; + break; + case TRUSTED_PROFILE_SAP: + if (trusted_profile_flag & (PROFILE_SUPPORTED << 4)) + trust_profile = trusted_profile_flag & (1 << 5); + else + return BLUETOOTH_ERROR_NOT_SUPPORT; + break; + case TRUSTED_PROFILE_ALL: /* Return Flag for All profiles*/ + *trusted = trusted_profile_flag; + return BLUETOOTH_ERROR_NONE; + default: + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + if (trust_profile) + *trusted = TRUE; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_restricted_profile_from_flag(bluetooth_restricted_profile_t profile, + guint restricted_profile_flag, guint *restricted) +{ + int restrict_profile; + *restricted = FALSE; + + switch (profile) { + case RESTRICTED_PROFILE_HFP_HS: + restrict_profile = restricted_profile_flag & (1 << 0); + break; + case RESTRICTED_PROFILE_A2DP: + restrict_profile = restricted_profile_flag & (1 << 2); + break; + default: + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + if (restrict_profile) + *restricted = TRUE; + + return BLUETOOTH_ERROR_NONE; +} + +char *_bt_get_trusted_profile_uuid(bluetooth_trusted_profile_t profile) +{ + switch (profile) { + case TRUSTED_PROFILE_PBAP: + return g_strdup("00001130-0000-1000-8000-00805f9b34fb"); + case TRUSTED_PROFILE_MAP: + return g_strdup("00001134-0000-1000-8000-00805f9b34fb"); + case TRUSTED_PROFILE_SAP: + return g_strdup("0000112D-0000-1000-8000-00805f9b34fb"); + case TRUSTED_PROFILE_ALL: + return NULL; + } + + return NULL; +} + +char *_bt_get_restricted_profile_uuid(bluetooth_restricted_profile_t profile) +{ + switch (profile) { + case RESTRICTED_PROFILE_HFP_HS: + return g_strdup("0000111e-0000-1000-8000-00805f9b34fb"); + case RESTRICTED_PROFILE_A2DP: + return g_strdup("0000110b-0000-1000-8000-00805f9b34fb"); + } + + return NULL; +} + +bluetooth_trusted_profile_t _bt_get_trusted_profile_enum(const char *uuid) +{ + if (g_strcmp0("0000112f-0000-1000-8000-00805f9b34fb", uuid) == 0) + return TRUSTED_PROFILE_PBAP; + else if (g_strcmp0("00001132-0000-1000-8000-00805f9b34fb", uuid) == 0) + return TRUSTED_PROFILE_MAP; + else if (g_strcmp0("0000112D-0000-1000-8000-00805f9b34fb", uuid) == 0) + return TRUSTED_PROFILE_SAP; + + return 0; /* 0 - Unknown Profile */ +} + +int _bt_set_trust_profile(bluetooth_device_address_t *bd_addr, + bluetooth_trusted_profile_t profile, gboolean trust) +{ + int ret = BLUETOOTH_ERROR_NONE; + GDBusConnection *conn; + GDBusProxy *proxy; + GError *error = NULL; + char *device_path = NULL; + char *uuid = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GVariant *reply; + + BT_CHECK_PARAMETER(bd_addr, return); + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X] profile[%d] trust[%d]", + bd_addr->addr[0], bd_addr->addr[1], + bd_addr->addr[2], bd_addr->addr[3], + bd_addr->addr[4], bd_addr->addr[5], + profile, trust); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, bd_addr->addr); + + device_path = _bt_get_device_object_path(address); + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, device_path, + BT_DEVICE_INTERFACE, NULL, NULL); + + g_free(device_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + uuid = _bt_get_trusted_profile_uuid(profile); + if (uuid == NULL) { + g_object_unref(proxy); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + reply = g_dbus_proxy_call_sync(proxy, "SetTrustedProfile", + g_variant_new("(sb)", uuid, trust), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + g_object_unref(proxy); + + if (reply == NULL) { + BT_ERR("Failed to Set Profile Trusted"); + ret = BLUETOOTH_ERROR_INTERNAL; + if (error) { + BT_ERR("Error %s[%s]", error->message, address); + g_error_free(error); + } + goto finish; + } + g_variant_unref(reply); + +finish: + g_free(uuid); + return ret; +} + +int _bt_get_trust_profile(bluetooth_device_address_t *bd_addr, + bluetooth_trusted_profile_t profile, guint *trust) +{ + int ret = BLUETOOTH_ERROR_NONE; + GDBusConnection *conn; + GDBusProxy *proxy; + GError *error = NULL; + char *device_path = NULL; + guint trusted_profile_flag; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GVariant *reply; + + BT_CHECK_PARAMETER(bd_addr, return); + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X] profile[%d] trust[%d]", + bd_addr->addr[0], bd_addr->addr[1], + bd_addr->addr[2], bd_addr->addr[3], + bd_addr->addr[4], bd_addr->addr[5], + profile, *trust); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, bd_addr->addr); + + device_path = _bt_get_device_object_path(address); + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, device_path, + BT_PROPERTIES_INTERFACE, NULL, NULL); + + g_free(device_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + reply = g_dbus_proxy_call_sync(proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "TrustedProfiles"), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + g_object_unref(proxy); + + if (reply == NULL) { + BT_ERR("Failed to Get Profile Trusted"); + ret = BLUETOOTH_ERROR_INTERNAL; + if (error) { + BT_ERR("Error %s[%s]", error->message, address); + g_error_free(error); + } + *trust = 0; + } else { + GVariant *temp; + g_variant_get(reply, "(v)", &temp); + trusted_profile_flag = g_variant_get_uint32(temp); + BT_DBG("TRUST_FLAG %d", trusted_profile_flag); + + ret = _bt_get_trusted_profile_from_flag(profile, + trusted_profile_flag, trust); + g_variant_unref(temp); + g_variant_unref(reply); + } + + BT_DBG("TRUST %d", *trust); + return ret; +} + +int _bt_set_restrict_profile(bluetooth_device_address_t *bd_addr, + bluetooth_restricted_profile_t profile, gboolean restricted) +{ + int ret = BLUETOOTH_ERROR_NONE; + GDBusConnection *conn; + GDBusProxy *proxy; + GError *error = NULL; + char *device_path = NULL; + char *uuid = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GVariant *reply; + + BT_CHECK_PARAMETER(bd_addr, return); + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X] profile[%d] restricted[%d]", + bd_addr->addr[0], bd_addr->addr[1], + bd_addr->addr[2], bd_addr->addr[3], + bd_addr->addr[4], bd_addr->addr[5], + profile, restricted); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, bd_addr->addr); + + device_path = _bt_get_device_object_path(address); + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, device_path, + BT_DEVICE_INTERFACE, NULL, NULL); + + g_free(device_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + uuid = _bt_get_restricted_profile_uuid(profile); + if (uuid == NULL) { + g_object_unref(proxy); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + reply = g_dbus_proxy_call_sync(proxy, "SetRestrictedProfile", + g_variant_new("(sb)", uuid, restricted), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + g_object_unref(proxy); + + if (reply == NULL) { + BT_ERR("Failed to Set Profile Restricted"); + ret = BLUETOOTH_ERROR_INTERNAL; + if (error) { + BT_ERR("Error %s[%s]", error->message, address); + g_error_free(error); + } + goto finish; + } + g_variant_unref(reply); + +finish: + g_free(uuid); + return ret; +} + +int _bt_get_restrict_profile(bluetooth_device_address_t *bd_addr, + bluetooth_restricted_profile_t profile, guint *restricted) +{ + int ret = BLUETOOTH_ERROR_NONE; + GDBusConnection *conn; + GDBusProxy *proxy; + GError *error = NULL; + char *device_path = NULL; + guint restricted_profile_flag; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GVariant *reply; + + BT_CHECK_PARAMETER(bd_addr, return); + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X] profile[%d] restricted[%d]", + bd_addr->addr[0], bd_addr->addr[1], + bd_addr->addr[2], bd_addr->addr[3], + bd_addr->addr[4], bd_addr->addr[5], + profile, *restricted); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, bd_addr->addr); + + device_path = _bt_get_device_object_path(address); + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, device_path, + BT_PROPERTIES_INTERFACE, NULL, NULL); + + g_free(device_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + reply = g_dbus_proxy_call_sync(proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "RestrictedProfiles"), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + g_object_unref(proxy); + + if (reply == NULL) { + BT_ERR("Failed to Get Profile Restricted"); + ret = BLUETOOTH_ERROR_INTERNAL; + if (error) { + BT_ERR("Error %s[%s]", error->message, address); + g_error_free(error); + } + *restricted = 0; + } else { + GVariant *temp; + g_variant_get(reply, "(v)", &temp); + restricted_profile_flag = g_variant_get_uint32(temp); + BT_DBG("Restricted_FLAG %d", restricted_profile_flag); + + ret = _bt_get_restricted_profile_from_flag(profile, + restricted_profile_flag, restricted); + g_variant_unref(temp); + g_variant_unref(reply); + } + + BT_DBG("TRUST %d", *restricted); + return ret; +} + +static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res, + gpointer user_data) +{ + GError *err = NULL; + GVariant *out_param1; + request_info_t *req_info; + GVariant *val = NULL; + GVariant *param = NULL; + guint8 status = 0; + guint16 mtu = 0; + bluetooth_device_address_t device_addr = { {0} }; + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG("+"); + val = g_dbus_proxy_call_finish(proxy, res, &err); + + req_info = _bt_get_request_info(att_mtu_req_info->req_id); + if (req_info == NULL) { + BT_ERR("req_info == NULL"); + g_object_unref(proxy); + att_mtu_req_info->device_proxy = NULL; + goto done; + } + + if (err != NULL) { + BT_ERR("Error occured in RequestAttMtu [%s]", err->message); + + if (g_strrstr(err->message, "NotSupported")) { + BT_INFO("Connection Not Supported"); + result = BLUETOOTH_ERROR_NOT_SUPPORT; + } else if (g_strrstr(err->message, "NotConnected")) { + BT_INFO("Not connected"); + result = BLUETOOTH_ERROR_NOT_CONNECTED; + } else if (g_strrstr(err->message, "InvalidArguments")) { + BT_INFO("Not connected"); + result = BLUETOOTH_ERROR_INVALID_PARAM; + } else { + BT_DBG("Default case"); + result = BLUETOOTH_ERROR_INTERNAL; + } + } + + g_object_unref(proxy); + att_mtu_req_info->device_proxy = NULL; + + if (result != BLUETOOTH_ERROR_NONE) + goto dbus_return; + + if (val) { + g_variant_get(val, "(qy)", &mtu, &status); + g_variant_unref(val); + } + + BT_DBG("MTU %d, Status %d, %s", mtu, status, att_mtu_req_info->addr); + + param = g_variant_new("(isqy)", + result, + att_mtu_req_info->addr, + mtu, + status); + + /* Send the event to application */ + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED, + param); + +dbus_return: + if (req_info->context == NULL) + goto done; + + _bt_convert_addr_string_to_type(device_addr.addr, + (const char *)att_mtu_req_info->addr); + + out_param1 = g_variant_new_from_data((const GVariantType *)"ay", + &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL); + g_dbus_method_invocation_return_value(req_info->context, + g_variant_new("(iv)", result, out_param1)); + + _bt_delete_request_list(req_info->req_id); +done: + if (err) + g_error_free(err); + + g_free(att_mtu_req_info->addr); + g_free(att_mtu_req_info); + att_mtu_req_info = NULL; + + BT_DBG("-"); +} + +int _bt_request_att_mtu(int request_id, bluetooth_device_address_t *device_address, + unsigned int mtu) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + GDBusProxy *adapter_proxy; + GDBusProxy *device_proxy; + GDBusConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(device_address, return); + + if (att_mtu_req_info) { + BT_ERR("ATT MTU request in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; + } + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + BT_DBG("Remote device address: %s", address); + + device_path = _bt_get_device_object_path(address); + + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE, NULL, NULL); + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + att_mtu_req_info = g_malloc0(sizeof(bt_funcion_data_t)); + att_mtu_req_info->addr = (char *)g_strdup(address); + att_mtu_req_info->req_id = request_id; + att_mtu_req_info->device_proxy = device_proxy; + + g_dbus_proxy_call(device_proxy, "RequestAttMtu", + g_variant_new("(q)", mtu), + G_DBUS_CALL_FLAGS_NONE, + BT_MAX_DBUS_TIMEOUT, + NULL, + (GAsyncReadyCallback)__bt_request_att_mtu_device_cb, + NULL); + + return ret; +} + +int _bt_get_att_mtu(bluetooth_device_address_t *device_address, + unsigned int *mtu) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char *object_path = NULL; + + GDBusProxy *device_proxy; + GError *error = NULL; + GVariant *value; + GDBusConnection *conn; + GVariant *result = NULL; + + BT_CHECK_PARAMETER(device_address, return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _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); + + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, object_path, + BT_PROPERTIES_INTERFACE, NULL, NULL); + g_free(object_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(device_proxy, "Get", + g_variant_new("(ss)", BT_DEVICE_INTERFACE, "AttMtu"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("DBus Error : %s", error->message); + g_clear_error(&error); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } else { + g_variant_get(result, "(v)", &value); + *mtu = g_variant_get_uint16(value); + BT_DBG("ATT MTU : %d", *mtu); + g_variant_unref(value); + g_variant_unref(result); + + if (*mtu == 0) { + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + } + + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_device_ida(bluetooth_device_address_t *device_address, + bluetooth_device_address_t *id_address) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + const gchar *idaddress = NULL; + GDBusProxy *device_proxy; + GError *error = NULL; + GVariant *result = NULL; + GDBusConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(device_address, return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + device_path = _bt_get_device_object_path(address); + retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE, NULL, NULL); + g_free(device_path); + if (!device_proxy) { + BT_ERR("Unable to get proxy"); + return BLUETOOTH_ERROR_INTERNAL; + } + + result = g_dbus_proxy_call_sync(device_proxy, "GetIDAddress", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (result == NULL) { + BT_ERR("Failed to get device ID address"); + + ret = BLUETOOTH_ERROR_INTERNAL; + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + BT_ERR("Error occured in Proxy call [%s]", error->message); + if (g_strcmp0(error->message, "Does Not Exist") == 0) + ret = BLUETOOTH_ERROR_NOT_PAIRED; + g_error_free(error); + } + g_object_unref(device_proxy); + return ret; + } + + g_variant_get(result , "(&s)", &idaddress); + + DBG_SECURE("ID Address : %s", idaddress); + _bt_convert_addr_string_to_type(id_address->addr, idaddress); + + g_variant_unref(result); + g_object_unref(device_proxy); + + return ret; +} + +int _bt_passkey_reply(const char *passkey, gboolean authentication_reply) +{ + GapAgentPrivate *agent = _bt_get_adapter_agent(); + retv_if(!agent, BLUETOOTH_ERROR_INTERNAL); + + if (authentication_reply) + gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, passkey, NULL); + else + gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, passkey, NULL); + + BT_DBG("BT_PASSKEY_REPLY"); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_passkey_confirmation_reply(gboolean confirmation_reply) +{ + GapAgentPrivate *agent = _bt_get_adapter_agent(); + retv_if(!agent, BLUETOOTH_ERROR_INTERNAL); + + if (confirmation_reply) + gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL); + else + gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL); + + BT_DBG("BT_PASSKEY_CONFIRMATION_REPLY"); + return BLUETOOTH_ERROR_NONE; +}