4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <dbus/dbus-glib.h>
22 #include <dbus/dbus.h>
28 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
29 #include <syspopup_caller.h>
31 #ifdef __TIZEN_MOBILE__
36 #include "bluetooth-api.h"
37 #include "bt-internal-types.h"
39 #include "bt-service-common.h"
40 #include "bt-service-event.h"
41 #include "bt-service-adapter.h"
42 #include "bt-service-util.h"
43 #include "bt-service-network.h"
44 #include "bt-service-obex-server.h"
45 #include "bt-service-agent.h"
46 #include "bt-service-main.h"
47 #include "bt-service-avrcp.h"
56 bt_adapter_timer_t visible_timer;
57 static gboolean is_discovering;
58 static gboolean cancel_by_user;
59 static bt_status_t adapter_status = BT_DEACTIVATED;
60 static void *adapter_agent = NULL;
61 static DBusGProxy *core_proxy = NULL;
63 #define BT_CORE_NAME "org.projectx.bt_core"
64 #define BT_CORE_PATH "/org/projectx/bt_core"
65 #define BT_CORE_INTERFACE "org.projectx.btcore"
67 static gboolean __bt_timeout_handler(gpointer user_data)
69 int result = BLUETOOTH_ERROR_NONE;
73 /* Take current time */
75 time_diff = difftime(current_time, visible_timer.start_time);
77 /* Send event to application */
78 _bt_send_event(BT_ADAPTER_EVENT,
79 BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED,
80 DBUS_TYPE_INT32, &result,
81 DBUS_TYPE_INT16, &time_diff,
84 if (visible_timer.timeout <= time_diff) {
85 g_source_remove(visible_timer.event_id);
86 visible_timer.event_id = 0;
87 visible_timer.timeout = 0;
89 if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
90 BT_DBG("Set vconf failed\n");
97 static int __bt_visibility_alarm_cb(alarm_id_t alarm_id, void* user_param)
99 BT_DBG("__bt_visibility_alarm_cb \n");
101 /* Switch Off visibility in Bluez */
102 _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0);
103 visible_timer.alarm_id = 0;
108 static void __bt_visibility_alarm_create()
113 result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, visible_timer.timeout,
116 BT_DBG("Failed to create alarm error = %d\n", result);
119 BT_DBG("Alarm created = %d\n", alarm_id);
120 visible_timer.alarm_id = alarm_id;
124 int __bt_set_visible_time(int timeout)
128 if (visible_timer.event_id > 0) {
129 g_source_remove(visible_timer.event_id);
130 visible_timer.event_id = 0;
133 if (visible_timer.alarm_id > 0) {
134 alarmmgr_remove_alarm(visible_timer.alarm_id);
135 visible_timer.alarm_id = 0;
138 visible_timer.timeout = timeout;
140 if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0)
141 BT_ERR("Set vconf failed\n");
144 return BLUETOOTH_ERROR_NONE;
146 /* Take start time */
147 time(&(visible_timer.start_time));
148 visible_timer.event_id = g_timeout_add_seconds(1,
149 __bt_timeout_handler, NULL);
151 /* Set Alarm timer to switch off BT */
152 result = alarmmgr_init("bt-service");
154 return BLUETOOTH_ERROR_INTERNAL;
156 result = alarmmgr_set_cb(__bt_visibility_alarm_cb, NULL);
158 return BLUETOOTH_ERROR_INTERNAL;
160 __bt_visibility_alarm_create();
162 return BLUETOOTH_ERROR_NONE;
165 static void __bt_get_service_list(GValue *value, bluetooth_device_info_t *dev)
171 ret_if(value == NULL);
174 uuids = g_value_get_boxed(value);
175 ret_if(uuids == NULL);
177 dev->service_index = 0;
179 for (i = 0; uuids[i] != NULL; i++) {
180 g_strlcpy(dev->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX);
182 parts = g_strsplit(uuids[i], "-", -1);
184 if (parts == NULL || parts[0] == NULL)
187 dev->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
190 dev->service_index++;
194 static bt_remote_dev_info_t *__bt_parse_remote_device_info(
195 DBusMessageIter *item_iter)
197 DBusMessageIter value_iter;
198 bt_remote_dev_info_t *dev_info;
200 dbus_message_iter_recurse(item_iter, &value_iter);
202 if (dbus_message_iter_get_arg_type(&value_iter) !=
203 DBUS_TYPE_DICT_ENTRY) {
208 dev_info = g_malloc0(sizeof(bt_remote_dev_info_t));
210 while (dbus_message_iter_get_arg_type(&value_iter) ==
211 DBUS_TYPE_DICT_ENTRY) {
214 DBusMessageIter dict_entry;
215 DBusMessageIter iter_dict_val;
217 dbus_message_iter_recurse(&value_iter, &dict_entry);
219 dbus_message_iter_get_basic(&dict_entry, &key);
222 dbus_message_iter_next(&value_iter);
226 if (!dbus_message_iter_next(&dict_entry)) {
227 dbus_message_iter_next(&value_iter);
230 dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
232 if (strcasecmp(key, "Address") == 0) {
233 const char *address = NULL;
234 dbus_message_iter_get_basic(&iter_dict_val,
236 dev_info->address = g_strdup(address);
237 } else if (strcasecmp(key, "Class") == 0) {
238 dbus_message_iter_get_basic(&iter_dict_val,
240 } else if (strcasecmp(key, "Name") == 0) {
241 dbus_message_iter_get_basic(&iter_dict_val,
243 if (dev_info->name == NULL)
244 dev_info->name = g_strdup(value);
245 } else if (strcasecmp(key, "Connected") == 0) {
246 dbus_message_iter_get_basic(&iter_dict_val,
247 &dev_info->connected);
248 } else if (strcasecmp(key, "Paired") == 0) {
249 dbus_message_iter_get_basic(&iter_dict_val,
251 } else if (strcasecmp(key, "Trusted") == 0) {
252 dbus_message_iter_get_basic(&iter_dict_val,
254 } else if (strcasecmp(key, "RSSI") == 0) {
255 dbus_message_iter_get_basic(&iter_dict_val,
257 } else if (strcasecmp(key, "UUIDs") == 0) {
258 DBusMessageIter uuid_iter;
259 DBusMessageIter tmp_iter;
262 dbus_message_iter_recurse(&iter_dict_val,
264 tmp_iter = uuid_iter;
266 /* Store the uuid count */
267 while (dbus_message_iter_get_arg_type(&tmp_iter) !=
270 dbus_message_iter_get_basic(&tmp_iter,
273 dev_info->uuid_count++;
274 if (!dbus_message_iter_next(&tmp_iter))
278 /* Store the uuids */
279 if (dev_info->uuid_count > 0) {
280 dev_info->uuids = g_new0(char *,
281 dev_info->uuid_count + 1);
283 dbus_message_iter_next(&value_iter);
287 while (dbus_message_iter_get_arg_type(&uuid_iter) !=
289 dbus_message_iter_get_basic(&uuid_iter,
291 dev_info->uuids[i] = g_strdup(value);
293 if (!dbus_message_iter_next(&uuid_iter)) {
299 dbus_message_iter_next(&value_iter);
305 static void __bt_extract_remote_devinfo(DBusMessageIter *msg_iter,
308 bt_remote_dev_info_t *dev_info = NULL;
309 char *object_path = NULL;
310 DBusMessageIter value_iter;
312 /* Parse the signature: oa{sa{sv}}} */
313 ret_if(dbus_message_iter_get_arg_type(msg_iter) !=
314 DBUS_TYPE_OBJECT_PATH);
316 dbus_message_iter_get_basic(msg_iter, &object_path);
317 ret_if(object_path == NULL);
319 /* object array (oa) */
320 ret_if(dbus_message_iter_next(msg_iter) == FALSE);
321 ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY);
323 dbus_message_iter_recurse(msg_iter, &value_iter);
325 /* string array (sa) */
326 while (dbus_message_iter_get_arg_type(&value_iter) ==
327 DBUS_TYPE_DICT_ENTRY) {
328 char *interface_name = NULL;
329 DBusMessageIter interface_iter;
331 dbus_message_iter_recurse(&value_iter, &interface_iter);
333 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
336 dbus_message_iter_get_basic(&interface_iter, &interface_name);
338 ret_if(dbus_message_iter_next(&interface_iter) == FALSE);
340 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
343 if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) {
344 BT_DBG("Found a device: %s", object_path);
345 dev_info = __bt_parse_remote_device_info(
349 g_array_append_vals(*dev_list, dev_info,
350 sizeof(bt_remote_dev_info_t));
354 dbus_message_iter_next(&value_iter);
358 int _bt_get_remote_found_devices(GArray **dev_list)
362 DBusMessageIter reply_iter;
363 DBusMessageIter value_iter;
365 DBusConnection *conn;
367 conn = _bt_get_system_conn();
368 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
370 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
371 BT_MANAGER_INTERFACE,
372 "GetManagedObjects");
374 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
376 /* Synchronous call */
377 dbus_error_init(&err);
378 reply = dbus_connection_send_with_reply_and_block(
381 dbus_message_unref(msg);
384 BT_ERR("Can't get managed objects");
386 if (dbus_error_is_set(&err)) {
387 BT_ERR("%s", err.message);
388 dbus_error_free(&err);
390 return BLUETOOTH_ERROR_INTERNAL;
393 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
394 BT_ERR("Fail to iterate the reply");
395 return BLUETOOTH_ERROR_INTERNAL;
398 dbus_message_iter_recurse(&reply_iter, &value_iter);
400 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
401 while (dbus_message_iter_get_arg_type(&value_iter) ==
402 DBUS_TYPE_DICT_ENTRY) {
403 DBusMessageIter msg_iter;
405 dbus_message_iter_recurse(&value_iter, &msg_iter);
407 __bt_extract_remote_devinfo(&msg_iter, dev_list);
409 dbus_message_iter_next(&value_iter);
412 return BLUETOOTH_ERROR_NONE;
415 static int __bt_get_bonded_device_info(gchar *device_path,
416 bluetooth_device_info_t *dev_info)
418 GValue *value = { 0 };
420 DBusGProxy *device_proxy;
421 const gchar *address;
428 GHashTable *hash = NULL;
430 DBusGConnection *conn;
432 BT_CHECK_PARAMETER(device_path, return);
433 BT_CHECK_PARAMETER(dev_info, return);
435 conn = _bt_get_system_gconn();
436 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
438 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
439 device_path, BT_PROPERTIES_INTERFACE);
441 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
443 dbus_g_proxy_call(device_proxy, "GetAll", &err,
444 G_TYPE_STRING, BT_DEVICE_INTERFACE,
446 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
447 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
449 g_object_unref(device_proxy);
452 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
454 return BLUETOOTH_ERROR_INTERNAL;
458 value = g_hash_table_lookup(hash, "Paired");
459 paired = g_value_get_boolean(value);
461 value = g_hash_table_lookup(hash, "Address");
462 address = value ? g_value_get_string(value) : NULL;
464 value = g_hash_table_lookup(hash, "Alias");
465 name = value ? g_value_get_string(value) : NULL;
468 BT_DBG("Alias Name [%s]", name);
470 value = g_hash_table_lookup(hash, "Name");
471 name = value ? g_value_get_string(value) : NULL;
474 value = g_hash_table_lookup(hash, "Class");
475 cod = value ? g_value_get_uint(value) : 0;
477 value = g_hash_table_lookup(hash, "Connected");
478 connected = value ? g_value_get_boolean(value) : FALSE;
480 value = g_hash_table_lookup(hash, "Trusted");
481 trust = value ? g_value_get_boolean(value) : FALSE;
483 if ((paired == FALSE) && (trust == FALSE)) {
484 return BLUETOOTH_ERROR_NOT_PAIRED;
487 value = g_hash_table_lookup(hash, "RSSI");
488 rssi = value ? g_value_get_int(value) : 0;
490 value = g_hash_table_lookup(hash, "UUIDs");
491 __bt_get_service_list(value, dev_info);
493 _bt_convert_addr_string_to_type(dev_info->device_address.addr,
496 _bt_divide_device_class(&dev_info->device_class, cod);
498 g_strlcpy(dev_info->device_name.name, name,
499 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
501 dev_info->rssi = rssi;
502 dev_info->trust = trust;
503 dev_info->paired = paired;
504 dev_info->connected = connected;
505 g_hash_table_destroy(hash);
506 ret = BLUETOOTH_ERROR_NONE;
508 BT_ERR("Hash is NULL\n");
509 ret = BLUETOOTH_ERROR_INTERNAL;
515 void _bt_set_discovery_status(gboolean mode)
517 is_discovering = mode;
520 void _bt_set_cancel_by_user(gboolean value)
522 cancel_by_user = value;
525 gboolean _bt_get_cancel_by_user(void)
527 return cancel_by_user;
530 static void __bt_flight_mode_cb(keynode_t *node, void *data)
532 gboolean flight_mode = FALSE;
535 BT_DBG("key=%s\n", vconf_keynode_get_name(node));
537 bt_status = _bt_adapter_get_status();
539 if (vconf_keynode_get_type(node) == VCONF_TYPE_BOOL) {
540 flight_mode = vconf_keynode_get_bool(node);
542 BT_DBG("value=%d\n", flight_mode);
544 if (flight_mode == TRUE) {
545 BT_DBG("Deactivate Bluetooth Service\n");
546 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
547 BT_DBG("Set vconf failed+\n");
549 if (bt_status == BT_ACTIVATED)
550 _bt_disable_adapter();
555 if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &value))
556 BT_ERR("Fail get flight mode value");
561 BT_DBG("Activate Bluetooth Service\n");
562 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0))
563 BT_DBG("Set vconf failed\n");
565 if (bt_status == BT_DEACTIVATED)
566 _bt_enable_adapter();
571 #ifdef __TIZEN_MOBILE__
572 static void __launch_bt_service(int status, int run_type)
575 char status_val[5] = { 0, };
576 char run_type_val[5] = { 0, };
578 snprintf(status_val, sizeof(status_val), "%d", status);
579 snprintf(run_type_val, sizeof(run_type_val), "%d", run_type);
581 BT_DBG("status: %s, run_type: %s", status_val, run_type_val);
583 kb = bundle_create();
585 bundle_add(kb, "launch-type", "setstate");
586 bundle_add(kb, "status", status_val);
587 bundle_add(kb, "run-type", run_type_val);
589 aul_launch_app("com.samsung.bluetooth", kb);
595 void _bt_adapter_set_status(bt_status_t status)
597 adapter_status = status;
600 bt_status_t _bt_adapter_get_status(void)
602 return adapter_status;
605 static void __bt_phone_name_changed_cb(keynode_t *node, void *data)
607 char *phone_name = NULL;
613 if (vconf_keynode_get_type(node) == VCONF_TYPE_STRING) {
614 phone_name = vconf_keynode_get_str(node);
615 if (phone_name && strlen(phone_name) != 0) {
616 if (!g_utf8_validate(phone_name, -1,
617 (const char **)&ptr))
620 _bt_set_local_name(phone_name);
625 static void __bt_set_visible_mode(void)
629 if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0)
630 BT_ERR("Fail to get the timeout value");
634 if (_bt_set_discoverable_mode(
635 BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE,
636 timeout) != BLUETOOTH_ERROR_NONE) {
637 if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
638 BT_ERR("Set vconf failed");
643 static void __bt_set_local_name(void)
645 char *phone_name = NULL;
648 phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
653 if (strlen(phone_name) != 0) {
654 if (!g_utf8_validate(phone_name, -1, (const char **)&ptr))
656 _bt_set_local_name(phone_name);
661 void _bt_set_enabled(void)
663 int result = BLUETOOTH_ERROR_NONE;
665 _bt_adapter_set_status(BT_ACTIVATED);
667 // register agent if it was not previously done.
668 if (!adapter_agent) {
670 _bt_handle_adapter_added();
673 __bt_set_visible_mode();
675 __bt_set_local_name();
677 /* Update Bluetooth Status to notify other modules */
678 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0)
679 BT_ERR("Set vconf failed\n");
681 if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
682 BT_ERR("Set vconf failed\n");
684 /* Send enabled event to API */
685 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED,
686 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
689 void _bt_set_disabled(void)
691 int result = BLUETOOTH_ERROR_NONE;
693 _bt_adapter_set_status(BT_DEACTIVATED);
695 /* Update Bluetooth Status to notify other modules */
696 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
697 BT_ERR("Set vconf failed\n");
699 if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
700 BT_ERR("Set vconf failed\n");
702 /* Send disabled event */
703 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
704 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
707 void *_bt_get_adapter_agent(void)
709 return adapter_agent;
712 void _bt_handle_flight_mode_noti(void)
715 vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
716 __bt_flight_mode_cb, NULL);
720 void _bt_handle_adapter_added(void)
724 adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE);
725 if (!adapter_agent) {
726 BT_ERR("Fail to register agent");
730 #ifdef __TIZEN_MOBILE__
731 if (!aul_app_is_running("com.samsung.bluetooth"))
732 __launch_bt_service(0, 0);
734 if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE)
735 BT_ERR("Fail to register media player");
738 if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE)
739 BT_ERR("Fail to init obex server");
741 if (_bt_network_activate() != BLUETOOTH_ERROR_NONE)
742 BT_ERR("Fail to activate network");
745 /* add the vconf noti handler */
746 vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
747 __bt_phone_name_changed_cb, NULL);
749 vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
750 __bt_flight_mode_cb, NULL);
753 void _bt_handle_adapter_removed(void)
757 vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
758 (vconf_callback_fn)__bt_phone_name_changed_cb);
760 _bt_destroy_agent(adapter_agent);
761 adapter_agent = NULL;
763 _bt_terminate_service(NULL);
766 DBusGProxy *_bt_init_core_proxy(void)
769 DBusGConnection *conn;
771 conn = _bt_get_system_gconn();
775 proxy = dbus_g_proxy_new_for_name(conn, BT_CORE_NAME,
776 BT_CORE_PATH, BT_CORE_INTERFACE);
785 static DBusGProxy *__bt_get_core_proxy(void)
787 return (core_proxy) ? core_proxy : _bt_init_core_proxy();
790 int _bt_enable_adapter(void)
797 if (_bt_adapter_get_status() == BT_ACTIVATING) {
798 BT_DBG("Enabling in progress");
799 return BLUETOOTH_ERROR_IN_PROGRESS;
802 if (_bt_adapter_get_status() == BT_ACTIVATED) {
803 BT_DBG("Already enabled");
804 return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED;
807 _bt_adapter_set_status(BT_ACTIVATING);
809 proxy = __bt_get_core_proxy();
811 return BLUETOOTH_ERROR_INTERNAL;
813 if (dbus_g_proxy_call_with_timeout(proxy, "EnableAdapter",
814 BT_ENABLE_TIMEOUT, &err,
816 G_TYPE_INVALID) == FALSE) {
818 _bt_adapter_set_status(BT_DEACTIVATED);
821 BT_ERR("Bt core call failed: [%s]", err->message);
825 /* Clean up the process */
826 if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL,
827 G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
828 BT_ERR("Bt core call failed");
831 /* Display notification */
832 notification_status_message_post(BT_STR_NOT_SUPPORT);
834 /* Terminate myself */
835 g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
836 return BLUETOOTH_ERROR_INTERNAL;
839 return BLUETOOTH_ERROR_NONE;
842 int _bt_disable_adapter(void)
848 if (_bt_adapter_get_status() == BT_DEACTIVATING) {
849 BT_DBG("Disabling in progress");
850 return BLUETOOTH_ERROR_IN_PROGRESS;
853 if (_bt_adapter_get_status() == BT_DEACTIVATED) {
854 BT_DBG("Already disabled");
855 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
858 _bt_adapter_set_status(BT_DEACTIVATING);
860 proxy = __bt_get_core_proxy();
862 return BLUETOOTH_ERROR_INTERNAL;
864 if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL,
865 G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
866 BT_ERR("Bt core call failed");
867 _bt_adapter_set_status(BT_ACTIVATED);
868 return BLUETOOTH_ERROR_INTERNAL;
871 return BLUETOOTH_ERROR_NONE;
874 int _bt_reset_adapter(void)
880 proxy = __bt_get_core_proxy();
882 return BLUETOOTH_ERROR_INTERNAL;
884 if (dbus_g_proxy_call(proxy, "ResetAdapter", NULL,
885 G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
886 BT_ERR("Bt core call failed");
887 return BLUETOOTH_ERROR_INTERNAL;
890 /* Terminate myself */
891 if (_bt_adapter_get_status() == BT_DEACTIVATED) {
892 g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
895 return BLUETOOTH_ERROR_NONE;
898 int _bt_check_adapter(int *status)
900 BT_CHECK_PARAMETER(status, return);
902 *status = 0; /* 0: disabled */
904 if (_bt_get_adapter_power())
905 *status = 1; /* 1: enabled */
907 return BLUETOOTH_ERROR_NONE;
910 int _bt_get_local_address(bluetooth_device_address_t *local_address)
915 GValue address_v = { 0 };
917 BT_CHECK_PARAMETER(local_address, return);
919 proxy = _bt_get_adapter_properties_proxy();
920 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
922 if (!dbus_g_proxy_call(proxy, "Get", &err,
923 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
924 G_TYPE_STRING, "Address",
926 G_TYPE_VALUE, &address_v,
929 BT_ERR("Getting property failed: [%s]\n", err->message);
932 return BLUETOOTH_ERROR_INTERNAL;
935 address = (char *)g_value_get_string(&address_v);
938 _bt_convert_addr_string_to_type(local_address->addr, address);
940 return BLUETOOTH_ERROR_INTERNAL;
943 return BLUETOOTH_ERROR_NONE;
946 int _bt_get_local_name(bluetooth_device_name_t *local_name)
950 GValue name_v = { 0 };
953 int ret = BLUETOOTH_ERROR_NONE;
955 BT_CHECK_PARAMETER(local_name, return);
957 proxy = _bt_get_adapter_properties_proxy();
958 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
960 if (!dbus_g_proxy_call(proxy, "Get", &err,
961 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
962 G_TYPE_STRING, "Alias",
964 G_TYPE_VALUE, &name_v,
967 BT_ERR("Getting property failed: [%s]\n", err->message);
970 return BLUETOOTH_ERROR_INTERNAL;
973 name = (char *)g_value_get_string(&name_v);
975 if (name && (strlen(name) > 0)) {
976 /* Check the utf8 valitation & Fill the NULL in the invalid location*/
977 if (!g_utf8_validate(name, -1, (const char **)&ptr))
980 g_strlcpy(local_name->name, name,
981 BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1);
983 ret = BLUETOOTH_ERROR_INTERNAL;
989 int _bt_set_local_name(char *local_name)
993 GError *error = NULL;
996 BT_CHECK_PARAMETER(local_name, return);
998 proxy = _bt_get_adapter_properties_proxy();
999 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1001 if (!g_utf8_validate(local_name, -1, (const char **)&ptr))
1004 g_value_init(&name, G_TYPE_STRING);
1005 g_value_set_string(&name, local_name);
1007 dbus_g_proxy_call(proxy, "Set", &error,
1008 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1009 G_TYPE_STRING, "Alias",
1010 G_TYPE_VALUE, &name,
1011 G_TYPE_INVALID, G_TYPE_INVALID);
1013 g_value_unset(&name);
1016 BT_ERR("SetProperty Fail: %s", error->message);
1017 g_error_free(error);
1018 return BLUETOOTH_ERROR_INTERNAL;
1021 return BLUETOOTH_ERROR_NONE;
1024 int _bt_is_service_used(char *service_uuid, gboolean *used)
1029 GHashTable *hash = NULL;
1031 int ret = BLUETOOTH_ERROR_NONE;
1033 BT_CHECK_PARAMETER(service_uuid, return);
1034 BT_CHECK_PARAMETER(used, return);
1036 proxy = _bt_get_adapter_proxy();
1037 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1039 dbus_g_proxy_call(proxy, "GetProperties", NULL,
1041 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
1042 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
1044 retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
1046 value = g_hash_table_lookup(hash, "UUIDs");
1047 uuids = g_value_get_boxed(value);
1049 if (uuids == NULL) {
1055 for (i = 0; uuids[i] != NULL; i++) {
1056 if (strcasecmp(uuids[i], service_uuid) == 0) {
1064 g_hash_table_destroy(hash);
1068 static gboolean __bt_get_discoverable_property(void)
1071 GValue discoverable_v = { 0 };
1074 proxy = _bt_get_adapter_properties_proxy();
1075 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1077 if (!dbus_g_proxy_call(proxy, "Get", &err,
1078 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1079 G_TYPE_STRING, "Discoverable",
1081 G_TYPE_VALUE, &discoverable_v,
1084 BT_ERR("Getting property failed: [%s]\n", err->message);
1087 return BLUETOOTH_ERROR_INTERNAL;
1090 return g_value_get_boolean(&discoverable_v);
1093 int _bt_get_discoverable_mode(int *mode)
1095 gboolean discoverable;
1096 unsigned int timeout;
1098 BT_CHECK_PARAMETER(mode, return);
1100 discoverable = __bt_get_discoverable_property();
1101 timeout = _bt_get_discoverable_timeout_property();
1103 if (discoverable == TRUE) {
1105 *mode = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE;
1107 *mode = BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE;
1109 *mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE;
1111 return BLUETOOTH_ERROR_NONE;
1114 int _bt_set_discoverable_mode(int discoverable_mode, int timeout)
1116 int ret = BLUETOOTH_ERROR_NONE;
1119 GError *error = NULL;
1120 GValue connectable = { 0 };
1121 GValue discoverable = { 0 };
1122 GValue val_timeout = { 0 };
1125 proxy = _bt_get_adapter_properties_proxy();
1126 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1128 g_value_init(&connectable, G_TYPE_BOOLEAN);
1129 g_value_init(&discoverable, G_TYPE_BOOLEAN);
1130 g_value_init(&val_timeout, G_TYPE_UINT);
1132 switch (discoverable_mode) {
1133 case BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE:
1138 case BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE:
1143 case BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE:
1148 return BLUETOOTH_ERROR_INVALID_PARAM;
1151 g_value_set_boolean(&connectable, pg_scan);
1152 g_value_set_boolean(&discoverable, inq_scan);
1153 g_value_set_uint(&val_timeout, timeout);
1155 dbus_g_proxy_call(proxy, "Set", &error,
1156 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1157 G_TYPE_STRING, "Powered",
1158 G_TYPE_VALUE, &connectable,
1159 G_TYPE_INVALID, G_TYPE_INVALID);
1161 if (error != NULL) {
1162 BT_ERR("Powered set err:[%s]", error->message);
1163 g_error_free(error);
1164 ret = BLUETOOTH_ERROR_INTERNAL;
1168 dbus_g_proxy_call(proxy, "Set", &error,
1169 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1170 G_TYPE_STRING, "Discoverable",
1171 G_TYPE_VALUE, &discoverable,
1172 G_TYPE_INVALID, G_TYPE_INVALID);
1174 if (error != NULL) {
1175 BT_ERR("Discoverable set err:[%s]", error->message);
1176 g_error_free(error);
1177 ret = BLUETOOTH_ERROR_INTERNAL;
1181 dbus_g_proxy_call(proxy, "Set", &error,
1182 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1183 G_TYPE_STRING, "DiscoverableTimeout",
1184 G_TYPE_VALUE, &val_timeout,
1185 G_TYPE_INVALID, G_TYPE_INVALID);
1187 if (error != NULL) {
1188 BT_ERR("Timeout set err:[%s]", error->message);
1189 g_error_free(error);
1190 ret = BLUETOOTH_ERROR_INTERNAL;
1194 if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE)
1197 __bt_set_visible_time(timeout);
1200 g_value_unset(&val_timeout);
1201 g_value_unset(&connectable);
1202 g_value_unset(&discoverable);
1207 int _bt_start_discovery(void)
1211 if (_bt_is_discovering() == TRUE) {
1212 BT_ERR("BT is already in discovering");
1213 return BLUETOOTH_ERROR_IN_PROGRESS;
1216 proxy = _bt_get_adapter_proxy();
1217 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1219 if (!dbus_g_proxy_call(proxy, "StartDiscovery", NULL,
1220 G_TYPE_INVALID, G_TYPE_INVALID)) {
1221 BT_ERR("Discover start failed");
1222 return BLUETOOTH_ERROR_INTERNAL;
1225 _bt_stop_discovery_timeout();
1227 is_discovering = TRUE;
1228 cancel_by_user = FALSE;
1229 /* discovery status will be change in event */
1231 return BLUETOOTH_ERROR_NONE;
1234 int _bt_cancel_discovery(void)
1238 if (_bt_is_discovering() == FALSE) {
1239 BT_ERR("BT is not in discovering");
1240 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
1243 proxy = _bt_get_adapter_proxy();
1244 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1246 if (!dbus_g_proxy_call(proxy, "StopDiscovery", NULL,
1247 G_TYPE_INVALID, G_TYPE_INVALID)) {
1248 BT_ERR("Discover stop failed");
1249 return BLUETOOTH_ERROR_INTERNAL;
1252 cancel_by_user = TRUE;
1253 /* discovery status will be change in event */
1255 return BLUETOOTH_ERROR_NONE;
1258 gboolean _bt_is_discovering(void)
1260 return is_discovering;
1263 gboolean _bt_get_discovering_property(void)
1266 GValue discovering_v = { 0 };
1269 proxy = _bt_get_adapter_properties_proxy();
1270 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1272 if (!dbus_g_proxy_call(proxy, "Get", &err,
1273 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1274 G_TYPE_STRING, "Discovering",
1276 G_TYPE_VALUE, &discovering_v,
1279 BT_ERR("Getting property failed: [%s]\n", err->message);
1282 return BLUETOOTH_ERROR_INTERNAL;
1285 return g_value_get_boolean(&discovering_v);
1288 unsigned int _bt_get_discoverable_timeout_property(void)
1291 GValue timeout_v = { 0 };
1294 proxy = _bt_get_adapter_properties_proxy();
1295 retv_if(proxy == NULL, 0);
1297 if (!dbus_g_proxy_call(proxy, "Get", &err,
1298 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1299 G_TYPE_STRING, "DiscoverableTimeout",
1301 G_TYPE_VALUE, &timeout_v,
1304 BT_ERR("Getting property failed: [%s]\n", err->message);
1310 return g_value_get_uint(&timeout_v);
1313 static bluetooth_device_info_t *__bt_parse_device_info(DBusMessageIter *item_iter)
1315 DBusMessageIter value_iter;
1316 bluetooth_device_info_t *dev_info;
1318 dbus_message_iter_recurse(item_iter, &value_iter);
1320 if (dbus_message_iter_get_arg_type(&value_iter) != DBUS_TYPE_DICT_ENTRY) {
1325 dev_info = g_malloc0(sizeof(bluetooth_device_info_t));
1327 while (dbus_message_iter_get_arg_type(&value_iter) ==
1328 DBUS_TYPE_DICT_ENTRY) {
1331 DBusMessageIter dict_entry;
1332 DBusMessageIter iter_dict_val;
1334 dbus_message_iter_recurse(&value_iter, &dict_entry);
1336 dbus_message_iter_get_basic(&dict_entry, &key);
1339 dbus_message_iter_next(&value_iter);
1343 if (!dbus_message_iter_next(&dict_entry)) {
1344 dbus_message_iter_next(&value_iter);
1347 dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
1349 if (strcasecmp(key, "Address") == 0) {
1350 const char *address = NULL;
1351 dbus_message_iter_get_basic(&iter_dict_val, &address);
1352 _bt_convert_addr_string_to_type(dev_info->device_address.addr,
1355 } else if (strcasecmp(key, "Class") == 0) {
1357 dbus_message_iter_get_basic(&iter_dict_val, &cod);
1358 _bt_divide_device_class(&dev_info->device_class, cod);
1359 } else if (strcasecmp(key, "Name") == 0) {
1360 dbus_message_iter_get_basic(&iter_dict_val, &value);
1362 /* If there is no Alias */
1363 if (strlen(dev_info->device_name.name) == 0) {
1364 g_strlcpy(dev_info->device_name.name, value,
1365 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1367 } else if (strcasecmp(key, "Alias") == 0) {
1368 dbus_message_iter_get_basic(&iter_dict_val, &value);
1370 /* Overwrite the name */
1372 memset(dev_info->device_name.name, 0x00,
1373 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1374 g_strlcpy(dev_info->device_name.name, value,
1375 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1377 } else if (strcasecmp(key, "Connected") == 0) {
1378 dbus_message_iter_get_basic(&iter_dict_val,
1379 &dev_info->connected);
1380 } else if (strcasecmp(key, "Paired") == 0) {
1381 dbus_message_iter_get_basic(&iter_dict_val,
1383 } else if (strcasecmp(key, "Trusted") == 0) {
1384 dbus_message_iter_get_basic(&iter_dict_val,
1386 } else if (strcasecmp(key, "RSSI") == 0) {
1387 dbus_message_iter_get_basic(&iter_dict_val,
1389 } else if (strcasecmp(key, "UUIDs") == 0) {
1390 DBusMessageIter uuid_iter;
1394 dbus_message_iter_recurse(&iter_dict_val, &uuid_iter);
1396 while (dbus_message_iter_get_arg_type(&uuid_iter) != DBUS_TYPE_INVALID) {
1397 dbus_message_iter_get_basic(&uuid_iter,
1400 g_strlcpy(dev_info->uuids[i], value,
1401 BLUETOOTH_UUID_STRING_MAX);
1403 parts = g_strsplit(value, "-", -1);
1405 if (parts == NULL || parts[0] == NULL)
1408 dev_info->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
1412 if (!dbus_message_iter_next(&uuid_iter)) {
1417 dev_info->service_index = i;
1420 dbus_message_iter_next(&value_iter);
1426 static void __bt_extract_device_info(DBusMessageIter *msg_iter,
1429 bluetooth_device_info_t *dev_info = NULL;
1430 char *object_path = NULL;
1431 DBusMessageIter value_iter;
1433 /* Parse the signature: oa{sa{sv}}} */
1434 ret_if(dbus_message_iter_get_arg_type(msg_iter) !=
1435 DBUS_TYPE_OBJECT_PATH);
1437 dbus_message_iter_get_basic(msg_iter, &object_path);
1438 ret_if(object_path == NULL);
1440 /* object array (oa) */
1441 ret_if(dbus_message_iter_next(msg_iter) == FALSE);
1442 ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY);
1444 dbus_message_iter_recurse(msg_iter, &value_iter);
1446 /* string array (sa) */
1447 while (dbus_message_iter_get_arg_type(&value_iter) ==
1448 DBUS_TYPE_DICT_ENTRY) {
1449 char *interface_name = NULL;
1450 DBusMessageIter interface_iter;
1452 dbus_message_iter_recurse(&value_iter, &interface_iter);
1454 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
1457 dbus_message_iter_get_basic(&interface_iter, &interface_name);
1459 ret_if(dbus_message_iter_next(&interface_iter) == FALSE);
1461 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
1464 if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) {
1465 BT_DBG("Found a device: %s", object_path);
1466 dev_info = __bt_parse_device_info(&interface_iter);
1469 if (dev_info->paired == TRUE) {
1470 g_array_append_vals(*dev_list, dev_info,
1471 sizeof(bluetooth_device_info_t));
1480 dbus_message_iter_next(&value_iter);
1483 BT_DBG("There is no device interface");
1486 int _bt_get_bonded_devices(GArray **dev_list)
1490 DBusMessageIter reply_iter;
1491 DBusMessageIter value_iter;
1493 DBusConnection *conn;
1495 conn = _bt_get_system_conn();
1496 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1498 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
1499 BT_MANAGER_INTERFACE,
1500 "GetManagedObjects");
1502 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
1504 /* Synchronous call */
1505 dbus_error_init(&err);
1506 reply = dbus_connection_send_with_reply_and_block(
1509 dbus_message_unref(msg);
1512 BT_ERR("Can't get managed objects");
1514 if (dbus_error_is_set(&err)) {
1515 BT_ERR("%s", err.message);
1516 dbus_error_free(&err);
1518 return BLUETOOTH_ERROR_INTERNAL;
1521 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1522 BT_ERR("Fail to iterate the reply");
1523 return BLUETOOTH_ERROR_INTERNAL;
1526 dbus_message_iter_recurse(&reply_iter, &value_iter);
1528 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1529 while (dbus_message_iter_get_arg_type(&value_iter) ==
1530 DBUS_TYPE_DICT_ENTRY) {
1531 DBusMessageIter msg_iter;
1533 dbus_message_iter_recurse(&value_iter, &msg_iter);
1535 __bt_extract_device_info(&msg_iter, dev_list);
1537 dbus_message_iter_next(&value_iter);
1540 return BLUETOOTH_ERROR_NONE;
1543 int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address,
1544 bluetooth_device_info_t *dev_info)
1546 char *object_path = NULL;
1547 DBusGProxy *adapter_proxy;
1548 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1550 BT_CHECK_PARAMETER(device_address, return);
1551 BT_CHECK_PARAMETER(dev_info, return);
1553 adapter_proxy = _bt_get_adapter_proxy();
1554 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1556 _bt_convert_addr_type_to_string(address, device_address->addr);
1558 object_path = _bt_get_device_object_path(address);
1560 retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND);
1562 if (__bt_get_bonded_device_info(object_path,
1563 dev_info) != BLUETOOTH_ERROR_NONE) {
1564 BT_ERR("Can't get the paired device path \n");
1565 g_free(object_path);
1566 return BLUETOOTH_ERROR_INTERNAL;
1568 g_free(object_path);
1569 return BLUETOOTH_ERROR_NONE;
1572 int _bt_get_timeout_value(int *timeout)
1574 time_t current_time;
1577 /* Take current time */
1578 time(¤t_time);
1579 time_diff = difftime(current_time, visible_timer.start_time);
1581 BT_DBG("Time diff = %d\n", time_diff);
1583 *timeout = visible_timer.timeout - time_diff;
1585 return BLUETOOTH_ERROR_NONE;