X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service%2Fbt-service-agent.c;h=b6b82d202148d806be306bac346902a547a0cc7b;hb=15a8da0024995b8eef2d95dac6f278d03e879c1b;hp=d48af2a1195df9d7fc5c7e198f2cac4f452a1722;hpb=25986f9247de588fc3bb272c5acf6544434f46bf;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service/bt-service-agent.c b/bt-service/bt-service-agent.c index d48af2a..b6b82d2 100644 --- a/bt-service/bt-service-agent.c +++ b/bt-service/bt-service-agent.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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, @@ -22,8 +26,21 @@ #include #include #include + +#if defined(LIBNOTIFY_SUPPORT) +#include "bt-popup.h" +#elif defined(LIBNOTIFICATION_SUPPORT) +#include "bt-service-agent-notification.h" +#else +#include +#endif + #include +#include + +#ifdef TIZEN_NETWORK_TETHERING_ENABLE #include +#endif #include "bt-internal-types.h" #include "bt-service-common.h" @@ -35,18 +52,11 @@ #include "bt-service-device.h" #include "bt-service-audio.h" -#if defined(LIBNOTIFY_SUPPORT) -#include "bt-popup.h" -#elif defined(LIBNOTIFICATION_SUPPORT) -#include "bt-service-agent-notification.h" -#else -#include -#endif - #define BT_APP_AUTHENTICATION_TIMEOUT 35 #define BT_APP_AUTHORIZATION_TIMEOUT 15 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb" +#define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb" #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB" #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb" #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb" @@ -58,8 +68,13 @@ #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb" #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb" #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb" +#define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00" +#define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a" #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent" + +#define BT_AGENT_INTERFACE "org.bluez.Agent1" + #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize" #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize" @@ -67,6 +82,13 @@ #define BT_PASSKEY_MAX_LENGTH 4 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200 +#define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3 +#define BT_PAN_MAX_CONNECTION 4 +extern guint nap_connected_device_count; + +#define G_VARIANT_UNREF(variant) \ + g_variant_unref(variant); \ + variant = NULL static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address, const gchar *name); @@ -82,41 +104,225 @@ static void __bt_agent_release_memory(void) stack_trim(); } -static int __syspopup_launch(gpointer user_data) +static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data) { int ret; - bundle *b = (bundle *) user_data; + static int retry_count; + bundle *b = (bundle *)user_data; + retv_if(user_data == NULL, FALSE); + + ++retry_count; #if defined(LIBNOTIFY_SUPPORT) - ret = notify_launch(b); + ret = notify_launch(b); #elif defined(LIBNOTIFICATION_SUPPORT) - ret = notification_launch(b); + ret = notification_launch(b); #else - ret = syspopup_launch("bt-syspopup", b); + ret = syspopup_launch("bt-syspopup", b); #endif - return ret; + if (ret < 0) { + BT_ERR("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..", + ret, retry_count); + if (retry_count >= BT_AGENT_SYSPOPUP_MAX_ATTEMPT) { + BT_ERR("Sorry!! Max retry %d reached", retry_count); + bundle_free(b); + retry_count = 0; + return FALSE; + } + } else { + BT_DBG("Hurray!! Finally Popup launched"); + retry_count = 0; + bundle_free(b); + } + + return (ret < 0) ? TRUE : FALSE; } -static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data) +#ifdef TIZEN_WEARABLE +static void __bt_unbond_cb(GDBusProxy *proxy, + GAsyncResult *res, gpointer user_data) { - int ret; - bundle *b = (bundle *) user_data; + GError *err = NULL; + GVariant *value; + + value = g_dbus_proxy_call_finish(proxy, res, &err); + if (value == NULL) { + BT_ERR("Error: Unbond Failed"); + if (err) { + BT_ERR("errCode[%x], message[%s]\n", err->code, err->message); + g_clear_error(&err); + } + return; + } + g_variant_unref(value); + BT_INFO("Unbonding is done"); + return; +} - if (NULL == b) { - BT_DBG("There is some problem with the user data..popup can not be created\n"); +static gboolean __bt_unpair_device(void) +{ + GArray *device_list; + int no_of_device; + int i; + + device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); + if (device_list == NULL) { + BT_ERR("g_array_new is failed"); + return FALSE; + } + + if (_bt_get_bonded_devices(&device_list) != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_get_bonded_devices is failed"); + g_array_free(device_list, TRUE); return FALSE; } - ret = __syspopup_launch(b); - if (0 > ret) - BT_DBG("Sorry Can not launch popup\n"); - else - BT_DBG("Hurray Popup launched \n"); + no_of_device = device_list->len / sizeof(bluetooth_device_info_t); + for (i = 0; i < no_of_device; i++) { + GDBusProxy *adapter_proxy; + bluetooth_device_info_t info; + char addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + char *device_path = NULL; + + info = g_array_index(device_list, bluetooth_device_info_t, i); + if (info.device_class.major_class == + BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) + continue; + + adapter_proxy = _bt_get_adapter_proxy(); + if (!adapter_proxy) { + BT_ERR("adapter_proxy is NULL"); + g_array_free(device_list, TRUE); + return FALSE; + } + + _bt_convert_addr_type_to_string(addr, info.device_address.addr); + device_path = _bt_get_device_object_path(addr); + if (device_path == NULL) { + BT_ERR("device_path is NULL"); + g_array_free(device_list, TRUE); + return FALSE; + } + + g_dbus_proxy_call(adapter_proxy, + "UnpairDevice", g_variant_new("o", device_path), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, + (GAsyncReadyCallback)__bt_unbond_cb, NULL); + + BT_INFO("unbonding %s is requested", addr); + + g_array_free(device_list, TRUE); + return TRUE; + } - bundle_free(b); + g_array_free(device_list, TRUE); return FALSE; } -static int __launch_system_popup(bt_agent_event_type_t event_type, +static void __bt_popup_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) +{ + BT_DBG("Sender Name[%s] Object Path[%s] Interface[%s] Signal[%s]", + sender_name, object_path, interface_name, signal_name); + + if (g_strcmp0(interface_name, "User.Bluetooth.syspopup") == 0 && + g_strcmp0(signal_name, "ResetResponse") == 0) { + int response; + + g_variant_get(parameters, "(i)", &response); + BT_DBG("response = %d", response); + } +} + +int __bt_service_subscribe_popup(GDBusConnection *conn, + gboolean subscribe) +{ + static guint subs_interface_added_id = 0; + + if (conn == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (subscribe) { + if (subs_interface_added_id == 0) { + subs_interface_added_id = g_dbus_connection_signal_subscribe(conn, + NULL, "User.Bluetooth.syspopup", "ResetResponse", NULL, NULL, 0, + __bt_popup_event_filter, NULL, NULL); + } + } else { + if (subs_interface_added_id > 0) { + g_dbus_connection_signal_unsubscribe(conn, + subs_interface_added_id); + subs_interface_added_id = 0; + } + } + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_register_popup_event_signal(void) +{ + GDBusConnection *conn; + + BT_DBG("+\n"); + + conn = _bt_get_system_gconn(); + if (conn == NULL) + return; + + __bt_service_subscribe_popup(conn, TRUE); + + BT_DBG("-\n"); + return; +} + +static gboolean __is_reset_required(const gchar *address) +{ + GArray *device_list; + uint32_t no_of_device; + uint32_t i; + bluetooth_device_info_t info; + gboolean is_required = FALSE; + + device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); + if (device_list == NULL) { + BT_ERR("g_array_new is failed"); + return FALSE; + } + + if (_bt_get_bonded_devices(&device_list) != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_get_bonded_devices is failed"); + g_array_free(device_list, TRUE); + return FALSE; + } + + no_of_device = device_list->len / sizeof(bluetooth_device_info_t); + for (i = 0; i < no_of_device; i++) { + char addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + + info = g_array_index(device_list, bluetooth_device_info_t, i); + + _bt_convert_addr_type_to_string(addr, info.device_address.addr); + if (g_strcmp0(address, addr) == 0) { + BT_DBG("This device is already in paired list"); + is_required = FALSE; + break; + } + + if (info.device_class.major_class != BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) { + is_required = TRUE; + break; + } + } + g_array_free(device_list, TRUE); + + return is_required; +} +#endif + +int _bt_launch_system_popup(bt_agent_event_type_t event_type, const char *device_name, char *passkey, const char *filename, @@ -126,11 +332,11 @@ static int __launch_system_popup(bt_agent_event_type_t event_type, bundle *b; char event_str[BT_MAX_EVENT_STR_LENGTH + 1]; - BT_DBG("_bt_agent_launch_system_popup +"); - b = bundle_create(); - if (!b) + if (!b) { + BT_ERR("Launching system popup failed"); return -1; + } bundle_add(b, "device-name", device_name); bundle_add(b, "passkey", passkey); @@ -147,6 +353,11 @@ static int __launch_system_popup(bt_agent_event_type_t event_type, sizeof(event_str)); break; + case BT_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED: + g_strlcpy(event_str, "passkey-auto-accepted", + sizeof(event_str)); + break; + case BT_AGENT_EVENT_PASSKEY_REQUEST: g_strlcpy(event_str, "passkey-request", sizeof(event_str)); break; @@ -191,7 +402,19 @@ static int __launch_system_popup(bt_agent_event_type_t event_type, g_strlcpy(event_str, "message-request", sizeof(event_str)); break; +#ifdef TIZEN_WEARABLE + case BT_AGENT_EVENT_SYSTEM_RESET_REQUEST: + __bt_register_popup_event_signal(); + g_strlcpy(event_str, "system-reset-request", sizeof(event_str)); + break; +#endif + + case BT_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE: + g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str)); + break; + default: + BT_ERR("Invalid event type"); bundle_free(b); return -1; @@ -199,66 +422,93 @@ static int __launch_system_popup(bt_agent_event_type_t event_type, bundle_add(b, "event-type", event_str); - ret = __syspopup_launch(b); +#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) + ret = syspopup_launch("bt-syspopup", b); +#endif if (0 > ret) { - BT_DBG("Popup launch failed...retry %d\n", ret); + BT_ERR("Popup launch failed...retry %d", ret); + g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS, - (GSourceFunc) __bt_agent_system_popup_timer_cb, - b); + (GSourceFunc)__bt_agent_system_popup_timer_cb, b); } else { bundle_free(b); } - BT_DBG("_bt_agent_launch_system_popup -%d", ret); + BT_INFO("_bt_agent_launch_system_popup"); return 0; } -static gboolean __pincode_request(GapAgent *agent, DBusGProxy *device) +static GVariant *__bt_service_getall(GDBusProxy *device, const char *interface) +{ + GError *error = NULL; + GVariant *reply; + + reply = g_dbus_proxy_call_sync(device, + "GetAll", g_variant_new("(s)", interface), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + if (reply == NULL) { + ERR("GetAll dBUS-RPC failed"); + if (error) { + ERR("D-Bus API failure: errCode[%x], message[%s]", + error->code, error->message); + g_clear_error(&error); + } + return NULL; + } + + return reply; +} + +static gboolean __pincode_request(GapAgentPrivate *agent, GDBusProxy *device) { uint32_t device_class; - GHashTable *hash = NULL; - GValue *value; const gchar *address; const gchar *name; - GError *error = NULL; + GVariant *reply = NULL; + GVariant *reply_temp = NULL; + GVariant *tmp_value; - BT_DBG("+\n"); + BT_DBG("+"); + + reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE); - dbus_g_proxy_call(device, "GetAll", &error, - 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); - if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); - g_error_free(error); + if (reply_temp == NULL) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", - NULL); + NULL); goto done; } - value = g_hash_table_lookup(hash, "Class"); - device_class = value ? g_value_get_uint(value) : 0; + g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/ + + tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32); + g_variant_get(tmp_value, "u", &device_class); + G_VARIANT_UNREF(tmp_value); - value = g_hash_table_lookup(hash, "Address"); - address = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &address); + G_VARIANT_UNREF(tmp_value); if (!address) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Name"); - name = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &name); + G_VARIANT_UNREF(tmp_value); if (!name) name = address; - if (__bt_agent_is_auto_response(device_class, address, name)) { - /* Use Fixed PIN "0000" for basic pairing*/ + if (_bt_is_device_creating() == TRUE && + _bt_is_bonding_device_address(address) == TRUE && + __bt_agent_is_auto_response(device_class, address, name)) { + BT_DBG("0000 Auto Pair"); + /* Use Fixed PIN "0000" for basic pairing */ _bt_set_autopair_status_in_bonding_info(TRUE); gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000", NULL); } else if (__bt_agent_is_hid_keyboard(device_class)) { + BT_DBG("HID Keyboard"); char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 }; if (__bt_agent_generate_passkey(str_passkey, @@ -271,190 +521,206 @@ static gboolean __pincode_request(GapAgent *agent, DBusGProxy *device) gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, str_passkey, NULL); - __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, + _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name, str_passkey, NULL, _gap_agent_get_path(agent)); } else { - __launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, NULL, + BT_DBG("Show Pin entry"); + _bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, NULL, NULL, _gap_agent_get_path(agent)); } done: - g_hash_table_destroy(hash); + g_variant_unref(reply); + g_variant_unref(reply_temp); __bt_agent_release_memory(); - - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } -static gboolean __passkey_request(GapAgent *agent, DBusGProxy *device) +static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device) { - uint32_t device_class; - GHashTable *hash = NULL; - GValue *value; const gchar *address; const gchar *name; - GError *error = NULL; + GVariant *reply = NULL; + GVariant *reply_temp = NULL; + GVariant *tmp_value; + BT_DBG("+"); - BT_DBG("+\n"); + reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE); - dbus_g_proxy_call(device, "GetAll", &error, - 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); - if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); - g_error_free(error); + if (reply_temp == NULL) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Class"); - device_class = value ? g_value_get_uint(value) : 0; + g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/ - value = g_hash_table_lookup(hash, "Address"); - address = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &address); + G_VARIANT_UNREF(tmp_value); if (!address) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Name"); - name = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &name); + G_VARIANT_UNREF(tmp_value); if (!name) name = address; - __launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL, + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL, _gap_agent_get_path(agent)); done: + g_variant_unref(reply); + g_variant_unref(reply_temp); __bt_agent_release_memory(); - g_hash_table_destroy(hash); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } -static gboolean __display_request(GapAgent *agent, DBusGProxy *device, +static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device, guint passkey) { - GHashTable *hash = NULL; - GValue *value; const gchar *address; const gchar *name; - GError *error = NULL; char *str_passkey; + GVariant *reply = NULL; + GVariant *reply_temp = NULL; + GVariant *tmp_value = NULL; - BT_DBG("+\n"); + BT_DBG("+"); - dbus_g_proxy_call(device, "GetAll", &error, - 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); - if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); - g_error_free(error); + reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE); + if (reply_temp == NULL) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Address"); - address = value ? g_value_get_string(value) : NULL; + g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/ + + tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &address); + G_VARIANT_UNREF(tmp_value); if (!address) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Name"); - name = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &name); + G_VARIANT_UNREF(tmp_value); if (!name) name = address; str_passkey = g_strdup_printf("%d", passkey); - __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name, + _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name, str_passkey, NULL, _gap_agent_get_path(agent)); g_free(str_passkey); done: + g_variant_unref(reply); + g_variant_unref(reply_temp); __bt_agent_release_memory(); - g_hash_table_destroy(hash); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } -static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device, +static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device, guint passkey) { - uint32_t device_class; - GHashTable *hash = NULL; - GValue *value; const gchar *address; const gchar *name; - GError *error = NULL; char str_passkey[7]; + GVariant *reply_temp = NULL; + GVariant *reply = NULL; + GVariant *tmp_value; + BT_DBG("+ passkey[%.6d]", passkey); - BT_DBG("+ passkey[%.6d]\n", passkey); + snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey); - dbus_g_proxy_call(device, "GetAll", &error, - 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); + reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE); - if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); - g_error_free(error); + if (reply_temp == NULL) { + BT_ERR("Device doesn't exist"); gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Class"); - device_class = value ? g_value_get_uint(value) : 0; + g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/ - value = g_hash_table_lookup(hash, "Address"); - address = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &address); + G_VARIANT_UNREF(tmp_value); if (!address) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Name"); - name = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value (reply, "Name", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &name); + G_VARIANT_UNREF(tmp_value); if (!name) name = address; - snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey); +#ifdef TIZEN_WEARABLE + uint32_t device_class = 0x00; + uint32_t major_class; + + tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32); + g_variant_get(tmp_value, "u", &device_class); + G_VARIANT_UNREF(tmp_value); + + major_class = (device_class & 0x1f00) >> 8; - __launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, + if (major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) { + BT_DBG("Audio device. Launch passkey pop-up"); + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, + str_passkey, NULL, _gap_agent_get_path(agent)); + goto done; + } + + if (__is_reset_required(address)) { + BT_INFO("Launch system reset pop-up"); + _bt_launch_system_popup(BT_AGENT_EVENT_SYSTEM_RESET_REQUEST, name, + NULL, NULL, _gap_agent_get_path(agent)); + } else { + BT_INFO("Launch passkey pop-up"); + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED, name, + str_passkey, NULL, _gap_agent_get_path(agent)); + + gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL); + } +#else + BT_DBG("LAUNCH SYSPOPUP"); + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, str_passkey, NULL, _gap_agent_get_path(agent)); +#endif + done: + g_variant_unref(reply); + g_variant_unref(reply_temp); __bt_agent_release_memory(); - g_hash_table_destroy(hash); - - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } -static gboolean __pairing_cancel_request(GapAgent *agent, const char *address) +static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address) { BT_DBG("On Going Pairing is cancelled by remote\n"); - - gap_agent_reply_pin_code(agent, GAP_AGENT_CANCEL, "", NULL); - #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) syspopup_destroy_all(); #endif @@ -470,23 +736,24 @@ static gboolean __a2dp_authorize_request_check(void) return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL); } -static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, +static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device, const char *uuid) { - GHashTable *hash = NULL; - GValue *value; const gchar *address; const gchar *name; - bool enabled; gboolean trust; gboolean paired; + GVariant *reply = NULL; + GVariant *reply_temp = NULL; + GVariant *tmp_value; +#ifdef TIZEN_NETWORK_TETHERING_ENABLE + bool enabled; tethering_h tethering = NULL; - GError *error = NULL; - int ret; +#endif int result = BLUETOOTH_ERROR_NONE; int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST; - BT_DBG("+\n"); + BT_DBG("+"); /* Check if already Media connection exsist */ if (!strcasecmp(uuid, A2DP_UUID)) { @@ -495,7 +762,7 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, ret = __a2dp_authorize_request_check(); if (ret) { - BT_DBG("Already one A2DP device connected \n"); + BT_ERR("Already one A2DP device connected \n"); gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL); goto done; @@ -504,9 +771,14 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, /* Check completed */ if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) || + !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) || + !strcasecmp(uuid, HFP_HS_UUID) || + !strcasecmp(uuid, HSP_HS_UUID) || !strcasecmp(uuid, A2DP_UUID) || - !strcasecmp(uuid, HID_UUID) || - !strcasecmp(uuid, AVRCP_TARGET_UUID)) { + !strcasecmp(uuid, HID_UUID) || + !strcasecmp(uuid, SAP_UUID_OLD) || + !strcasecmp(uuid, SAP_UUID_NEW) || + !strcasecmp(uuid, AVRCP_TARGET_UUID)) { BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid); gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL); @@ -519,6 +791,13 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, !strcasecmp(uuid, BNEP_UUID)) { BT_DBG("Network connection request: %s", uuid); +#ifdef TIZEN_NETWORK_TETHERING_ENABLE + if (nap_connected_device_count >= + BT_PAN_MAX_CONNECTION) { + BT_ERR("Max connection exceeded"); + goto fail; + } + int ret; ret = tethering_create(&tethering); if (ret != TETHERING_ERROR_NONE) { @@ -538,87 +817,79 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, BT_ERR("BT tethering is not enabled"); goto fail; } +#endif gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL); goto done; +#ifdef TIZEN_NETWORK_TETHERING_ENABLE fail: gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL); goto done; +#endif } - dbus_g_proxy_call(device, "GetAll", &error, - 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); - if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); - g_error_free(error); + reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE); + if (reply_temp == NULL) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Address"); - address = value ? g_value_get_string(value) : NULL; + g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/ + + tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &address); + G_VARIANT_UNREF(tmp_value); if (!address) { gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Alias"); - name = value ? g_value_get_string(value) : NULL; + tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING); + g_variant_get(tmp_value, "s", &name); + G_VARIANT_UNREF(tmp_value); if (!name) name = address; - value = g_hash_table_lookup(hash, "Trusted"); - trust = value ? g_value_get_boolean(value) : 0; + tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN); + g_variant_get(tmp_value, "b", &trust); + G_VARIANT_UNREF(tmp_value); - value = g_hash_table_lookup(hash, "Paired"); - paired = value ? g_value_get_boolean(value) : 0; + tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN); + g_variant_get(tmp_value, "b", &paired); + G_VARIANT_UNREF(tmp_value); if ((paired == FALSE) && (trust == FALSE)) { - BT_DBG("No paired & No trusted device"); + BT_ERR("No paired & No trusted device"); gap_agent_reply_authorize(agent, - GAP_AGENT_REJECT, NULL); + GAP_AGENT_REJECT, NULL); goto done; } - BT_DBG("Authorization request for device [%s] Service:[%s]\n", address, - uuid); + BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid); if (strcasecmp(uuid, OPP_UUID) == 0 && _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER, NULL) == TRUE) { _bt_send_event(BT_OPP_SERVER_EVENT, - BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); + BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE, + g_variant_new("iss", result, address, name)); goto done; } if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER, (char *)uuid) == TRUE) { - bt_rfcomm_server_info_t *server_info; - - server_info = _bt_rfcomm_get_server_info_using_uuid((char *)uuid); - retv_if(server_info == NULL, TRUE); - retv_if(server_info->server_type != BT_CUSTOM_SERVER, TRUE); + bt_agent_osp_server_t *osp_serv; + osp_serv = _gap_agent_get_osp_server(agent, + BT_RFCOMM_SERVER, (char *)uuid); _bt_send_event(BT_RFCOMM_SERVER_EVENT, BLUETOOTH_EVENT_RFCOMM_AUTHORIZE, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INT16, &server_info->control_fd, - DBUS_TYPE_INVALID); + g_variant_new("issssn", result, address, uuid, + name, osp_serv->path, osp_serv->fd)); goto done; } @@ -631,24 +902,24 @@ fail: request_type = BT_AGENT_EVENT_MAP_REQUEST; if (trust) { - BT_DBG("Trusted device, so authorize\n"); + BT_INFO("Trusted device, so authorize\n"); gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL); } else { - __launch_system_popup(request_type, name, NULL, NULL, + _bt_launch_system_popup(request_type, name, NULL, NULL, _gap_agent_get_path(agent)); } done: + g_variant_unref(reply); + g_variant_unref(reply_temp); __bt_agent_release_memory(); - g_hash_table_destroy(hash); - - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } -static gboolean __authorization_cancel_request(GapAgent *agent, +static gboolean __authorization_cancel_request(GapAgentPrivate *agent, const char *address) { BT_DBG("On Going Authorization is cancelled by remote\n"); @@ -669,15 +940,20 @@ void _bt_destroy_agent(void *agent) if (!agent) return; - _gap_agent_reset_dbus(agent); + _gap_agent_reset_dbus((GapAgentPrivate *)agent); - g_object_unref(agent); + g_free(agent); } void* _bt_create_agent(const char *path, gboolean adapter) { GAP_AGENT_FUNC_CB func_cb; - GapAgent* agent; + GDBusProxy *adapter_proxy; + GapAgentPrivate *agent; + + adapter_proxy = _bt_get_adapter_proxy(); + if (!adapter_proxy) + return NULL; func_cb.pincode_func = __pincode_request; func_cb.display_func = __display_request; @@ -687,33 +963,36 @@ void* _bt_create_agent(const char *path, gboolean adapter) func_cb.pairing_cancel_func = __pairing_cancel_request; func_cb.authorization_cancel_func = __authorization_cancel_request; - agent = _gap_agent_new(); + /* Allocate memory*/ + agent = g_new0(GapAgentPrivate, 1); - _gap_agent_setup_dbus(agent, &func_cb, path); + _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy); if (adapter) { if (!_gap_agent_register(agent)) { _bt_destroy_agent(agent); - return NULL; + agent = NULL; } } return agent; } -gboolean _bt_agent_register_osp_server(const gint type, const char *uuid) +gboolean _bt_agent_register_osp_server(const gint type, + const char *uuid, char *path, int fd) { void *agent = _bt_get_adapter_agent(); if (!agent) return FALSE; - return _gap_agent_register_osp_server(agent, type, uuid); + return _gap_agent_register_osp_server(agent, type, uuid, path, fd); } gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid) { void *agent = _bt_get_adapter_agent(); + if (!agent) return FALSE; @@ -733,11 +1012,39 @@ gboolean _bt_agent_reply_authorize(gboolean accept) return gap_agent_reply_authorize(agent, accept_val, NULL); } -gboolean _bt_agent_is_canceled(void *agent) +gboolean _bt_agent_is_canceled(void) { + void *agent = _bt_get_adapter_agent(); + if (!agent) + return FALSE; + return _gap_agent_is_canceled(agent); } +void _bt_agent_set_canceled(gboolean value) +{ + void *agent = _bt_get_adapter_agent(); + if (!agent) + return; + + return _gap_agent_set_canceled(agent, value); +} + +int _bt_agent_reply_cancellation(void) +{ + void *agent = _bt_get_adapter_agent(); + + if (!agent) + return BLUETOOTH_ERROR_INTERNAL; + + if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) { + BT_ERR("Fail to reply agent"); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class) { switch ((dev_class & 0x1f00) >> 8) { @@ -803,12 +1110,12 @@ static gboolean __bt_agent_is_device_blacklist(const char *address, long size; size_t result; - BT_DBG("+ \n"); + BT_DBG("+"); fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r"); if (fp == NULL) { - BT_DBG("fopen failed \n"); + BT_ERR("Unable to open blacklist file"); return FALSE; } @@ -823,21 +1130,27 @@ static gboolean __bt_agent_is_device_blacklist(const char *address, rewind(fp); buffer = g_malloc0(sizeof(char) * size); + /* Fix : NULL_RETURNS */ + if (buffer == NULL) { + BT_ERR("Fail to allocate memory"); + fclose(fp); + return FALSE; + } result = fread((char *)buffer, 1, size, fp); fclose(fp); if (result != size) { - BT_DBG("Read Error\n"); + BT_ERR("Read Error"); g_free(buffer); return FALSE; } - BT_DBG("Buffer = %s\n", buffer); + BT_DBG("Buffer = %s", buffer); lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0); g_free(buffer); if (lines == NULL) { - BT_DBG("No lines in the file \n"); + BT_ERR("No lines in the file"); return FALSE; } @@ -854,12 +1167,16 @@ static gboolean __bt_agent_is_device_blacklist(const char *address, if (__bt_agent_find_device_by_partial_name(lines[i], name)) goto done; + if (g_str_has_prefix(lines[i], "KeyboardAutoPair")) + if (__bt_agent_find_device_by_address_exactname( + lines[i], address)) + goto done; } g_strfreev(lines); - BT_DBG("- \n"); + BT_DBG("-"); return FALSE; done: - BT_DBG("Found the device\n"); + BT_DBG("Found the device"); g_strfreev(lines); return TRUE; } @@ -868,6 +1185,7 @@ static gboolean __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address, const gchar *name) { gboolean is_headset = FALSE; + gboolean is_mouse = FALSE; char lap_address[BT_LOWER_ADDRESS_LENGTH]; BT_DBG("bt_agent_is_headset_class, %d +", dev_class); @@ -897,9 +1215,29 @@ static gboolean __bt_agent_is_auto_response(uint32_t dev_class, break; } break; + case 0x05: + switch (dev_class & 0xff) { + case 0x80: /* 0x80: Pointing device(Mouse) */ + is_mouse = TRUE; + break; + + case 0x40: /* 0x40: input device (BT keyboard) */ + + /* Get the LAP(Lower Address part) */ + g_strlcpy(lap_address, address, sizeof(lap_address)); + + /* Need to Auto pair the blacklisted Keyboard */ + if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) { + BT_DBG("Device is not black listed\n"); + return FALSE; + } else { + BT_ERR("Device is black listed\n"); + return TRUE; + } + } } - if (!is_headset) + if ((!is_headset) && (!is_mouse)) return FALSE; /* Get the LAP(Lower Address part) */ @@ -909,7 +1247,7 @@ static gboolean __bt_agent_is_auto_response(uint32_t dev_class, BT_DBG("Address 3 byte = %s\n", lap_address); if (__bt_agent_is_device_blacklist(lap_address, name)) { - BT_DBG("Device is black listed\n"); + BT_ERR("Device is black listed\n"); return FALSE; } @@ -936,7 +1274,8 @@ static int __bt_agent_generate_passkey(char *passkey, int size) for (i = 0; i < size; i++) { len = read(random_fd, &value, sizeof(value)); - passkey[i] = '0' + (value % 10); + if (len > 0) + passkey[i] = '0' + (value % 10); } close(random_fd);