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>
35 #include "bluetooth-api.h"
36 #include "bt-internal-types.h"
38 #include "bt-service-common.h"
39 #include "bt-service-event.h"
40 #include "bt-service-adapter.h"
41 #include "bt-service-util.h"
42 #include "bt-service-network.h"
43 #include "bt-service-obex-server.h"
44 #include "bt-service-agent.h"
45 #include "bt-service-main.h"
46 #include "bt-service-avrcp.h"
55 bt_adapter_timer_t visible_timer;
56 static gboolean is_discovering;
57 static gboolean cancel_by_user;
58 static bt_status_t adapter_status = BT_DEACTIVATED;
59 static void *adapter_agent = NULL;
60 static DBusGProxy *core_proxy = NULL;
62 #define BT_CORE_NAME "org.projectx.bt_core"
63 #define BT_CORE_PATH "/org/projectx/bt_core"
64 #define BT_CORE_INTERFACE "org.projectx.btcore"
66 static gboolean __bt_timeout_handler(gpointer user_data)
68 int result = BLUETOOTH_ERROR_NONE;
72 /* Take current time */
74 time_diff = difftime(current_time, visible_timer.start_time);
76 /* Send event to application */
77 _bt_send_event(BT_ADAPTER_EVENT,
78 BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED,
79 DBUS_TYPE_INT32, &result,
80 DBUS_TYPE_INT16, &time_diff,
83 if (visible_timer.timeout <= time_diff) {
84 g_source_remove(visible_timer.event_id);
85 visible_timer.event_id = 0;
86 visible_timer.timeout = 0;
88 if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
89 BT_DBG("Set vconf failed\n");
96 static int __bt_visibility_alarm_cb(alarm_id_t alarm_id, void* user_param)
98 BT_DBG("__bt_visibility_alarm_cb \n");
100 /* Switch Off visibility in Bluez */
101 _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0);
102 visible_timer.alarm_id = 0;
107 static void __bt_visibility_alarm_create()
112 result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, visible_timer.timeout,
115 BT_DBG("Failed to create alarm error = %d\n", result);
118 BT_DBG("Alarm created = %d\n", alarm_id);
119 visible_timer.alarm_id = alarm_id;
123 int __bt_set_visible_time(int timeout)
127 if (visible_timer.event_id > 0) {
128 g_source_remove(visible_timer.event_id);
129 visible_timer.event_id = 0;
132 if (visible_timer.alarm_id > 0) {
133 alarmmgr_remove_alarm(visible_timer.alarm_id);
134 visible_timer.alarm_id = 0;
137 visible_timer.timeout = timeout;
139 if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0)
140 BT_ERR("Set vconf failed\n");
143 return BLUETOOTH_ERROR_NONE;
145 /* Take start time */
146 time(&(visible_timer.start_time));
147 visible_timer.event_id = g_timeout_add_seconds(1,
148 __bt_timeout_handler, NULL);
150 /* Set Alarm timer to switch off BT */
151 result = alarmmgr_init("bt-service");
153 return BLUETOOTH_ERROR_INTERNAL;
155 result = alarmmgr_set_cb(__bt_visibility_alarm_cb, NULL);
157 return BLUETOOTH_ERROR_INTERNAL;
159 __bt_visibility_alarm_create();
161 return BLUETOOTH_ERROR_NONE;
164 static void __bt_get_service_list(GValue *value, bluetooth_device_info_t *dev)
170 ret_if(value == NULL);
173 uuids = g_value_get_boxed(value);
174 ret_if(uuids == NULL);
176 dev->service_index = 0;
178 for (i = 0; uuids[i] != NULL; i++) {
179 g_strlcpy(dev->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX);
181 parts = g_strsplit(uuids[i], "-", -1);
183 if (parts == NULL || parts[0] == NULL)
186 dev->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
189 dev->service_index++;
193 static bt_remote_dev_info_t *__bt_parse_remote_device_info(
194 DBusMessageIter *item_iter)
196 DBusMessageIter value_iter;
197 bt_remote_dev_info_t *dev_info;
199 dbus_message_iter_recurse(item_iter, &value_iter);
201 if (dbus_message_iter_get_arg_type(&value_iter) !=
202 DBUS_TYPE_DICT_ENTRY) {
207 dev_info = g_malloc0(sizeof(bt_remote_dev_info_t));
209 while (dbus_message_iter_get_arg_type(&value_iter) ==
210 DBUS_TYPE_DICT_ENTRY) {
213 DBusMessageIter dict_entry;
214 DBusMessageIter iter_dict_val;
216 dbus_message_iter_recurse(&value_iter, &dict_entry);
218 dbus_message_iter_get_basic(&dict_entry, &key);
221 dbus_message_iter_next(&value_iter);
225 if (!dbus_message_iter_next(&dict_entry)) {
226 dbus_message_iter_next(&value_iter);
229 dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
231 if (strcasecmp(key, "Address") == 0) {
232 const char *address = NULL;
233 dbus_message_iter_get_basic(&iter_dict_val,
235 dev_info->address = g_strdup(address);
236 } else if (strcasecmp(key, "Class") == 0) {
237 dbus_message_iter_get_basic(&iter_dict_val,
239 } else if (strcasecmp(key, "Name") == 0) {
240 dbus_message_iter_get_basic(&iter_dict_val,
242 if (dev_info->name == NULL)
243 dev_info->name = g_strdup(value);
244 } else if (strcasecmp(key, "Connected") == 0) {
245 dbus_message_iter_get_basic(&iter_dict_val,
246 &dev_info->connected);
247 } else if (strcasecmp(key, "Paired") == 0) {
248 dbus_message_iter_get_basic(&iter_dict_val,
250 } else if (strcasecmp(key, "Trusted") == 0) {
251 dbus_message_iter_get_basic(&iter_dict_val,
253 } else if (strcasecmp(key, "RSSI") == 0) {
254 dbus_message_iter_get_basic(&iter_dict_val,
256 } else if (strcasecmp(key, "UUIDs") == 0) {
257 DBusMessageIter uuid_iter;
258 DBusMessageIter tmp_iter;
261 dbus_message_iter_recurse(&iter_dict_val,
263 tmp_iter = uuid_iter;
265 /* Store the uuid count */
266 while (dbus_message_iter_get_arg_type(&tmp_iter) !=
269 dbus_message_iter_get_basic(&tmp_iter,
272 dev_info->uuid_count++;
273 if (!dbus_message_iter_next(&tmp_iter))
277 /* Store the uuids */
278 if (dev_info->uuid_count > 0) {
279 dev_info->uuids = g_new0(char *,
280 dev_info->uuid_count + 1);
282 dbus_message_iter_next(&value_iter);
286 while (dbus_message_iter_get_arg_type(&uuid_iter) !=
288 dbus_message_iter_get_basic(&uuid_iter,
290 dev_info->uuids[i] = g_strdup(value);
292 if (!dbus_message_iter_next(&uuid_iter)) {
298 dbus_message_iter_next(&value_iter);
304 static void __bt_extract_remote_devinfo(DBusMessageIter *msg_iter,
307 bt_remote_dev_info_t *dev_info = NULL;
308 char *object_path = NULL;
309 DBusMessageIter value_iter;
311 /* Parse the signature: oa{sa{sv}}} */
312 ret_if(dbus_message_iter_get_arg_type(msg_iter) !=
313 DBUS_TYPE_OBJECT_PATH);
315 dbus_message_iter_get_basic(msg_iter, &object_path);
316 ret_if(object_path == NULL);
318 /* object array (oa) */
319 ret_if(dbus_message_iter_next(msg_iter) == FALSE);
320 ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY);
322 dbus_message_iter_recurse(msg_iter, &value_iter);
324 /* string array (sa) */
325 while (dbus_message_iter_get_arg_type(&value_iter) ==
326 DBUS_TYPE_DICT_ENTRY) {
327 char *interface_name = NULL;
328 DBusMessageIter interface_iter;
330 dbus_message_iter_recurse(&value_iter, &interface_iter);
332 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
335 dbus_message_iter_get_basic(&interface_iter, &interface_name);
337 ret_if(dbus_message_iter_next(&interface_iter) == FALSE);
339 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
342 if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) {
343 BT_DBG("Found a device: %s", object_path);
344 dev_info = __bt_parse_remote_device_info(
348 g_array_append_vals(*dev_list, dev_info,
349 sizeof(bt_remote_dev_info_t));
353 dbus_message_iter_next(&value_iter);
357 int _bt_get_remote_found_devices(GArray **dev_list)
361 DBusMessageIter reply_iter;
362 DBusMessageIter value_iter;
364 DBusConnection *conn;
366 conn = _bt_get_system_conn();
367 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
369 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
370 BT_MANAGER_INTERFACE,
371 "GetManagedObjects");
373 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
375 /* Synchronous call */
376 dbus_error_init(&err);
377 reply = dbus_connection_send_with_reply_and_block(
380 dbus_message_unref(msg);
383 BT_ERR("Can't get managed objects");
385 if (dbus_error_is_set(&err)) {
386 BT_ERR("%s", err.message);
387 dbus_error_free(&err);
389 return BLUETOOTH_ERROR_INTERNAL;
392 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
393 BT_ERR("Fail to iterate the reply");
394 return BLUETOOTH_ERROR_INTERNAL;
397 dbus_message_iter_recurse(&reply_iter, &value_iter);
399 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
400 while (dbus_message_iter_get_arg_type(&value_iter) ==
401 DBUS_TYPE_DICT_ENTRY) {
402 DBusMessageIter msg_iter;
404 dbus_message_iter_recurse(&value_iter, &msg_iter);
406 __bt_extract_remote_devinfo(&msg_iter, dev_list);
408 dbus_message_iter_next(&value_iter);
411 return BLUETOOTH_ERROR_NONE;
414 static int __bt_get_bonded_device_info(gchar *device_path,
415 bluetooth_device_info_t *dev_info)
417 GValue *value = { 0 };
419 DBusGProxy *device_proxy;
420 const gchar *address;
427 GHashTable *hash = NULL;
429 DBusGConnection *conn;
431 BT_CHECK_PARAMETER(device_path, return);
432 BT_CHECK_PARAMETER(dev_info, return);
434 conn = _bt_get_system_gconn();
435 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
437 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
438 device_path, BT_PROPERTIES_INTERFACE);
440 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
442 dbus_g_proxy_call(device_proxy, "GetAll", &err,
443 G_TYPE_STRING, BT_DEVICE_INTERFACE,
445 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
446 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
448 g_object_unref(device_proxy);
451 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
453 return BLUETOOTH_ERROR_INTERNAL;
457 value = g_hash_table_lookup(hash, "Paired");
458 paired = g_value_get_boolean(value);
460 value = g_hash_table_lookup(hash, "Address");
461 address = value ? g_value_get_string(value) : NULL;
463 value = g_hash_table_lookup(hash, "Alias");
464 name = value ? g_value_get_string(value) : NULL;
467 BT_DBG("Alias Name [%s]", name);
469 value = g_hash_table_lookup(hash, "Name");
470 name = value ? g_value_get_string(value) : NULL;
473 value = g_hash_table_lookup(hash, "Class");
474 cod = value ? g_value_get_uint(value) : 0;
476 value = g_hash_table_lookup(hash, "Connected");
477 connected = value ? g_value_get_boolean(value) : FALSE;
479 value = g_hash_table_lookup(hash, "Trusted");
480 trust = value ? g_value_get_boolean(value) : FALSE;
482 if ((paired == FALSE) && (trust == FALSE)) {
483 return BLUETOOTH_ERROR_NOT_PAIRED;
486 value = g_hash_table_lookup(hash, "RSSI");
487 rssi = value ? g_value_get_int(value) : 0;
489 value = g_hash_table_lookup(hash, "UUIDs");
490 __bt_get_service_list(value, dev_info);
492 _bt_convert_addr_string_to_type(dev_info->device_address.addr,
495 _bt_divide_device_class(&dev_info->device_class, cod);
497 g_strlcpy(dev_info->device_name.name, name,
498 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
500 dev_info->rssi = rssi;
501 dev_info->trust = trust;
502 dev_info->paired = paired;
503 dev_info->connected = connected;
504 g_hash_table_destroy(hash);
505 ret = BLUETOOTH_ERROR_NONE;
507 BT_ERR("Hash is NULL\n");
508 ret = BLUETOOTH_ERROR_INTERNAL;
514 void _bt_set_discovery_status(gboolean mode)
516 is_discovering = mode;
519 void _bt_set_cancel_by_user(gboolean value)
521 cancel_by_user = value;
524 gboolean _bt_get_cancel_by_user(void)
526 return cancel_by_user;
529 static void __bt_flight_mode_cb(keynode_t *node, void *data)
531 gboolean flight_mode = FALSE;
534 BT_DBG("key=%s\n", vconf_keynode_get_name(node));
536 bt_status = _bt_adapter_get_status();
538 if (vconf_keynode_get_type(node) == VCONF_TYPE_BOOL) {
539 flight_mode = vconf_keynode_get_bool(node);
541 BT_DBG("value=%d\n", flight_mode);
543 if (flight_mode == TRUE) {
544 BT_DBG("Deactivate Bluetooth Service\n");
545 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
546 BT_DBG("Set vconf failed+\n");
548 if (bt_status == BT_ACTIVATED)
549 _bt_disable_adapter();
554 if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &value))
555 BT_ERR("Fail get flight mode value");
560 BT_DBG("Activate Bluetooth Service\n");
561 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0))
562 BT_DBG("Set vconf failed\n");
564 if (bt_status == BT_DEACTIVATED)
565 _bt_enable_adapter();
570 static void __launch_bt_service(int status, int run_type)
573 char status_val[5] = { 0, };
574 char run_type_val[5] = { 0, };
576 snprintf(status_val, sizeof(status_val), "%d", status);
577 snprintf(run_type_val, sizeof(run_type_val), "%d", run_type);
579 BT_DBG("status: %s, run_type: %s", status_val, run_type_val);
581 kb = bundle_create();
583 bundle_add(kb, "launch-type", "setstate");
584 bundle_add(kb, "status", status_val);
585 bundle_add(kb, "run-type", run_type_val);
587 aul_launch_app("com.samsung.bluetooth", kb);
592 void _bt_adapter_set_status(bt_status_t status)
594 adapter_status = status;
597 bt_status_t _bt_adapter_get_status(void)
599 return adapter_status;
602 static void __bt_phone_name_changed_cb(keynode_t *node, void *data)
604 char *phone_name = NULL;
610 if (vconf_keynode_get_type(node) == VCONF_TYPE_STRING) {
611 phone_name = vconf_keynode_get_str(node);
612 if (phone_name && strlen(phone_name) != 0) {
613 if (!g_utf8_validate(phone_name, -1,
614 (const char **)&ptr))
617 _bt_set_local_name(phone_name);
622 static void __bt_set_visible_mode(void)
626 if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0)
627 BT_ERR("Fail to get the timeout value");
631 if (_bt_set_discoverable_mode(
632 BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE,
633 timeout) != BLUETOOTH_ERROR_NONE) {
634 if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
635 BT_ERR("Set vconf failed");
640 static void __bt_set_local_name(void)
642 char *phone_name = NULL;
645 phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
650 if (strlen(phone_name) != 0) {
651 if (!g_utf8_validate(phone_name, -1, (const char **)&ptr))
653 _bt_set_local_name(phone_name);
658 static int __bt_set_enabled(void)
661 int result = BLUETOOTH_ERROR_NONE;
663 _bt_check_adapter(&enabled);
665 if (enabled == FALSE) {
666 BT_ERR("Bluetoothd is not running");
667 return BLUETOOTH_ERROR_INTERNAL;
670 __bt_set_visible_mode();
672 __bt_set_local_name();
674 /* Update Bluetooth Status to notify other modules */
675 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0)
676 BT_ERR("Set vconf failed\n");
678 if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
679 BT_ERR("Set vconf failed\n");
681 /* Send enabled event to API */
682 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED,
683 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
685 return BLUETOOTH_ERROR_NONE;
688 static void __bt_set_disabled(int result)
690 /* Update Bluetooth Status to notify other modules */
691 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
692 BT_ERR("Set vconf failed\n");
694 if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
695 BT_ERR("Set vconf failed\n");
697 /* Send disabled event */
698 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
699 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
702 void *_bt_get_adapter_agent(void)
704 return adapter_agent;
707 void _bt_handle_flight_mode_noti(void)
710 vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
711 __bt_flight_mode_cb, NULL);
715 void _bt_handle_adapter_added(void)
717 adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE);
718 if (!adapter_agent) {
719 BT_ERR("Fail to register agent");
723 #ifdef __TIZEN_MOBILE__
724 if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE)
725 BT_ERR("Fail to register media player");
728 if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE)
729 BT_ERR("Fail to init obex server");
731 if (_bt_network_activate() != BLUETOOTH_ERROR_NONE)
732 BT_ERR("Fail to activate network");
735 /* add the vconf noti handler */
736 vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
737 __bt_phone_name_changed_cb, NULL);
739 vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
740 __bt_flight_mode_cb, NULL);
744 _bt_adapter_set_status(BT_ACTIVATED);
747 void _bt_handle_adapter_removed(void)
749 _bt_adapter_set_status(BT_DEACTIVATED);
751 vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
752 (vconf_callback_fn)__bt_phone_name_changed_cb);
754 _bt_destroy_agent(adapter_agent);
755 adapter_agent = NULL;
757 __bt_set_disabled(BLUETOOTH_ERROR_NONE);
759 _bt_terminate_service(NULL);
762 DBusGProxy *_bt_init_core_proxy(void)
765 DBusGConnection *conn;
767 conn = _bt_get_system_gconn();
771 proxy = dbus_g_proxy_new_for_name(conn, BT_CORE_NAME,
772 BT_CORE_PATH, BT_CORE_INTERFACE);
781 static DBusGProxy *__bt_get_core_proxy(void)
783 return (core_proxy) ? core_proxy : _bt_init_core_proxy();
786 int _bt_enable_adapter(void)
793 if (_bt_adapter_get_status() == BT_ACTIVATING) {
794 BT_DBG("Enabling in progress");
795 return BLUETOOTH_ERROR_IN_PROGRESS;
798 if (_bt_adapter_get_status() == BT_ACTIVATED) {
799 BT_DBG("Already enabled");
800 return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED;
803 _bt_adapter_set_status(BT_ACTIVATING);
805 proxy = __bt_get_core_proxy();
807 return BLUETOOTH_ERROR_INTERNAL;
809 if (dbus_g_proxy_call_with_timeout(proxy, "EnableAdapter",
810 BT_ENABLE_TIMEOUT, &err,
812 G_TYPE_INVALID) == FALSE) {
814 _bt_adapter_set_status(BT_DEACTIVATED);
817 BT_ERR("Bt core call failed: [%s]", err->message);
821 /* Clean up the process */
822 if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL,
823 G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
824 BT_ERR("Bt core call failed");
827 /* Display notification */
828 status_message_post(BT_STR_NOT_SUPPORT);
830 /* Terminate myself */
831 g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
832 return BLUETOOTH_ERROR_INTERNAL;
835 return BLUETOOTH_ERROR_NONE;
838 int _bt_disable_adapter(void)
844 if (_bt_adapter_get_status() == BT_DEACTIVATING) {
845 BT_DBG("Disabling in progress");
846 return BLUETOOTH_ERROR_IN_PROGRESS;
849 if (_bt_adapter_get_status() == BT_DEACTIVATED) {
850 BT_DBG("Already disabled");
851 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
854 _bt_adapter_set_status(BT_DEACTIVATING);
856 proxy = __bt_get_core_proxy();
858 return BLUETOOTH_ERROR_INTERNAL;
860 if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL,
861 G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
862 BT_ERR("Bt core call failed");
863 _bt_adapter_set_status(BT_ACTIVATED);
864 return BLUETOOTH_ERROR_INTERNAL;
867 return BLUETOOTH_ERROR_NONE;
870 int _bt_reset_adapter(void)
876 proxy = __bt_get_core_proxy();
878 return BLUETOOTH_ERROR_INTERNAL;
880 if (dbus_g_proxy_call(proxy, "ResetAdapter", NULL,
881 G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
882 BT_ERR("Bt core call failed");
883 return BLUETOOTH_ERROR_INTERNAL;
886 /* Terminate myself */
887 if (_bt_adapter_get_status() == BT_DEACTIVATED) {
888 g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
891 return BLUETOOTH_ERROR_NONE;
894 int _bt_check_adapter(int *status)
896 char *adapter_path = NULL;
898 BT_CHECK_PARAMETER(status, return);
900 *status = 0; /* 0: disabled */
902 adapter_path = _bt_get_adapter_path();
904 if (adapter_path != NULL)
905 *status = 1; /* 1: enabled */
907 g_free(adapter_path);
908 return BLUETOOTH_ERROR_NONE;
911 int _bt_get_local_address(bluetooth_device_address_t *local_address)
916 GValue address_v = { 0 };
918 BT_CHECK_PARAMETER(local_address, return);
920 proxy = _bt_get_adapter_properties_proxy();
921 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
923 if (!dbus_g_proxy_call(proxy, "Get", &err,
924 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
925 G_TYPE_STRING, "Address",
927 G_TYPE_VALUE, &address_v,
930 BT_ERR("Getting property failed: [%s]\n", err->message);
933 return BLUETOOTH_ERROR_INTERNAL;
936 address = (char *)g_value_get_string(&address_v);
939 _bt_convert_addr_string_to_type(local_address->addr, address);
941 return BLUETOOTH_ERROR_INTERNAL;
944 return BLUETOOTH_ERROR_NONE;
947 int _bt_get_local_name(bluetooth_device_name_t *local_name)
951 GValue name_v = { 0 };
954 int ret = BLUETOOTH_ERROR_NONE;
956 BT_CHECK_PARAMETER(local_name, return);
958 proxy = _bt_get_adapter_properties_proxy();
959 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
961 if (!dbus_g_proxy_call(proxy, "Get", &err,
962 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
963 G_TYPE_STRING, "Alias",
965 G_TYPE_VALUE, &name_v,
968 BT_ERR("Getting property failed: [%s]\n", err->message);
971 return BLUETOOTH_ERROR_INTERNAL;
974 name = (char *)g_value_get_string(&name_v);
976 if (name && (strlen(name) > 0)) {
977 /* Check the utf8 valitation & Fill the NULL in the invalid location*/
978 if (!g_utf8_validate(name, -1, (const char **)&ptr))
981 g_strlcpy(local_name->name, name,
982 BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1);
984 ret = BLUETOOTH_ERROR_INTERNAL;
990 int _bt_set_local_name(char *local_name)
994 GError *error = NULL;
997 BT_CHECK_PARAMETER(local_name, return);
999 proxy = _bt_get_adapter_properties_proxy();
1000 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1002 if (!g_utf8_validate(local_name, -1, (const char **)&ptr))
1005 g_value_init(&name, G_TYPE_STRING);
1006 g_value_set_string(&name, local_name);
1008 dbus_g_proxy_call(proxy, "Set", &error,
1009 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1010 G_TYPE_STRING, "Alias",
1011 G_TYPE_VALUE, &name,
1012 G_TYPE_INVALID, G_TYPE_INVALID);
1014 g_value_unset(&name);
1017 BT_ERR("SetProperty Fail: %s", error->message);
1018 g_error_free(error);
1019 return BLUETOOTH_ERROR_INTERNAL;
1022 return BLUETOOTH_ERROR_NONE;
1025 int _bt_is_service_used(char *service_uuid, gboolean *used)
1030 GHashTable *hash = NULL;
1032 int ret = BLUETOOTH_ERROR_NONE;
1034 BT_CHECK_PARAMETER(service_uuid, return);
1035 BT_CHECK_PARAMETER(used, return);
1037 proxy = _bt_get_adapter_proxy();
1038 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1040 dbus_g_proxy_call(proxy, "GetProperties", NULL,
1042 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
1043 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
1045 retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
1047 value = g_hash_table_lookup(hash, "UUIDs");
1048 uuids = g_value_get_boxed(value);
1050 if (uuids == NULL) {
1056 for (i = 0; uuids[i] != NULL; i++) {
1057 if (strcasecmp(uuids[i], service_uuid) == 0) {
1065 g_hash_table_destroy(hash);
1069 static gboolean __bt_get_discoverable_property(void)
1072 GValue discoverable_v = { 0 };
1075 proxy = _bt_get_adapter_properties_proxy();
1076 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1078 if (!dbus_g_proxy_call(proxy, "Get", &err,
1079 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1080 G_TYPE_STRING, "Discoverable",
1082 G_TYPE_VALUE, &discoverable_v,
1085 BT_ERR("Getting property failed: [%s]\n", err->message);
1088 return BLUETOOTH_ERROR_INTERNAL;
1091 return g_value_get_boolean(&discoverable_v);
1094 int _bt_get_discoverable_mode(int *mode)
1096 gboolean discoverable;
1097 unsigned int timeout;
1099 BT_CHECK_PARAMETER(mode, return);
1101 discoverable = __bt_get_discoverable_property();
1102 timeout = _bt_get_discoverable_timeout_property();
1104 if (discoverable == TRUE) {
1106 *mode = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE;
1108 *mode = BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE;
1110 *mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE;
1112 return BLUETOOTH_ERROR_NONE;
1115 int _bt_set_discoverable_mode(int discoverable_mode, int timeout)
1117 int ret = BLUETOOTH_ERROR_NONE;
1120 GError *error = NULL;
1121 GValue connectable = { 0 };
1122 GValue discoverable = { 0 };
1123 GValue val_timeout = { 0 };
1126 proxy = _bt_get_adapter_properties_proxy();
1127 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1129 g_value_init(&connectable, G_TYPE_BOOLEAN);
1130 g_value_init(&discoverable, G_TYPE_BOOLEAN);
1131 g_value_init(&val_timeout, G_TYPE_UINT);
1133 switch (discoverable_mode) {
1134 case BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE:
1139 case BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE:
1144 case BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE:
1149 return BLUETOOTH_ERROR_INVALID_PARAM;
1152 g_value_set_boolean(&connectable, pg_scan);
1153 g_value_set_boolean(&discoverable, inq_scan);
1154 g_value_set_uint(&val_timeout, timeout);
1156 dbus_g_proxy_call(proxy, "Set", &error,
1157 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1158 G_TYPE_STRING, "Powered",
1159 G_TYPE_VALUE, &connectable,
1160 G_TYPE_INVALID, G_TYPE_INVALID);
1162 if (error != NULL) {
1163 BT_ERR("Powered set err:[%s]", error->message);
1164 g_error_free(error);
1165 ret = BLUETOOTH_ERROR_INTERNAL;
1169 dbus_g_proxy_call(proxy, "Set", &error,
1170 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1171 G_TYPE_STRING, "Discoverable",
1172 G_TYPE_VALUE, &discoverable,
1173 G_TYPE_INVALID, G_TYPE_INVALID);
1175 if (error != NULL) {
1176 BT_ERR("Discoverable set err:[%s]", error->message);
1177 g_error_free(error);
1178 ret = BLUETOOTH_ERROR_INTERNAL;
1182 dbus_g_proxy_call(proxy, "Set", &error,
1183 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1184 G_TYPE_STRING, "DiscoverableTimeout",
1185 G_TYPE_VALUE, &val_timeout,
1186 G_TYPE_INVALID, G_TYPE_INVALID);
1188 if (error != NULL) {
1189 BT_ERR("Timeout set err:[%s]", error->message);
1190 g_error_free(error);
1191 ret = BLUETOOTH_ERROR_INTERNAL;
1195 if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE)
1198 __bt_set_visible_time(timeout);
1201 g_value_unset(&val_timeout);
1202 g_value_unset(&connectable);
1203 g_value_unset(&discoverable);
1208 int _bt_start_discovery(void)
1212 if (_bt_is_discovering() == TRUE) {
1213 BT_ERR("BT is already in discovering");
1214 return BLUETOOTH_ERROR_IN_PROGRESS;
1217 proxy = _bt_get_adapter_proxy();
1218 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1220 if (!dbus_g_proxy_call(proxy, "StartDiscovery", NULL,
1221 G_TYPE_INVALID, G_TYPE_INVALID)) {
1222 BT_ERR("Discover start failed");
1223 return BLUETOOTH_ERROR_INTERNAL;
1226 _bt_stop_discovery_timeout();
1228 is_discovering = TRUE;
1229 cancel_by_user = FALSE;
1230 /* discovery status will be change in event */
1232 return BLUETOOTH_ERROR_NONE;
1235 int _bt_cancel_discovery(void)
1239 if (_bt_is_discovering() == FALSE) {
1240 BT_ERR("BT is not in discovering");
1241 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
1244 proxy = _bt_get_adapter_proxy();
1245 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1247 if (!dbus_g_proxy_call(proxy, "StopDiscovery", NULL,
1248 G_TYPE_INVALID, G_TYPE_INVALID)) {
1249 BT_ERR("Discover stop failed");
1250 return BLUETOOTH_ERROR_INTERNAL;
1253 cancel_by_user = TRUE;
1254 /* discovery status will be change in event */
1256 return BLUETOOTH_ERROR_NONE;
1259 gboolean _bt_is_discovering(void)
1261 return is_discovering;
1264 gboolean _bt_get_discovering_property(void)
1267 GValue discovering_v = { 0 };
1270 proxy = _bt_get_adapter_properties_proxy();
1271 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1273 if (!dbus_g_proxy_call(proxy, "Get", &err,
1274 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1275 G_TYPE_STRING, "Discovering",
1277 G_TYPE_VALUE, &discovering_v,
1280 BT_ERR("Getting property failed: [%s]\n", err->message);
1283 return BLUETOOTH_ERROR_INTERNAL;
1286 return g_value_get_boolean(&discovering_v);
1289 unsigned int _bt_get_discoverable_timeout_property(void)
1292 GValue timeout_v = { 0 };
1295 proxy = _bt_get_adapter_properties_proxy();
1296 retv_if(proxy == NULL, 0);
1298 if (!dbus_g_proxy_call(proxy, "Get", &err,
1299 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1300 G_TYPE_STRING, "DiscoverableTimeout",
1302 G_TYPE_VALUE, &timeout_v,
1305 BT_ERR("Getting property failed: [%s]\n", err->message);
1311 return g_value_get_uint(&timeout_v);
1314 static bluetooth_device_info_t *__bt_parse_device_info(DBusMessageIter *item_iter)
1316 DBusMessageIter value_iter;
1317 bluetooth_device_info_t *dev_info;
1319 dbus_message_iter_recurse(item_iter, &value_iter);
1321 if (dbus_message_iter_get_arg_type(&value_iter) != DBUS_TYPE_DICT_ENTRY) {
1326 dev_info = g_malloc0(sizeof(bluetooth_device_info_t));
1328 while (dbus_message_iter_get_arg_type(&value_iter) ==
1329 DBUS_TYPE_DICT_ENTRY) {
1332 DBusMessageIter dict_entry;
1333 DBusMessageIter iter_dict_val;
1335 dbus_message_iter_recurse(&value_iter, &dict_entry);
1337 dbus_message_iter_get_basic(&dict_entry, &key);
1340 dbus_message_iter_next(&value_iter);
1344 if (!dbus_message_iter_next(&dict_entry)) {
1345 dbus_message_iter_next(&value_iter);
1348 dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
1350 if (strcasecmp(key, "Address") == 0) {
1351 const char *address = NULL;
1352 dbus_message_iter_get_basic(&iter_dict_val, &address);
1353 _bt_convert_addr_string_to_type(dev_info->device_address.addr,
1356 } else if (strcasecmp(key, "Class") == 0) {
1358 dbus_message_iter_get_basic(&iter_dict_val, &cod);
1359 _bt_divide_device_class(&dev_info->device_class, cod);
1360 } else if (strcasecmp(key, "Name") == 0) {
1361 dbus_message_iter_get_basic(&iter_dict_val, &value);
1363 /* If there is no Alias */
1364 if (strlen(dev_info->device_name.name) == 0) {
1365 g_strlcpy(dev_info->device_name.name, value,
1366 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1368 } else if (strcasecmp(key, "Alias") == 0) {
1369 dbus_message_iter_get_basic(&iter_dict_val, &value);
1371 /* Overwrite the name */
1373 memset(dev_info->device_name.name, 0x00,
1374 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1375 g_strlcpy(dev_info->device_name.name, value,
1376 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1378 } else if (strcasecmp(key, "Connected") == 0) {
1379 dbus_message_iter_get_basic(&iter_dict_val,
1380 &dev_info->connected);
1381 } else if (strcasecmp(key, "Paired") == 0) {
1382 dbus_message_iter_get_basic(&iter_dict_val,
1384 } else if (strcasecmp(key, "Trusted") == 0) {
1385 dbus_message_iter_get_basic(&iter_dict_val,
1387 } else if (strcasecmp(key, "RSSI") == 0) {
1388 dbus_message_iter_get_basic(&iter_dict_val,
1390 } else if (strcasecmp(key, "UUIDs") == 0) {
1391 DBusMessageIter uuid_iter;
1395 dbus_message_iter_recurse(&iter_dict_val, &uuid_iter);
1397 while (dbus_message_iter_get_arg_type(&uuid_iter) != DBUS_TYPE_INVALID) {
1398 dbus_message_iter_get_basic(&uuid_iter,
1401 g_strlcpy(dev_info->uuids[i], value,
1402 BLUETOOTH_UUID_STRING_MAX);
1404 parts = g_strsplit(value, "-", -1);
1406 if (parts == NULL || parts[0] == NULL)
1409 dev_info->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
1413 if (!dbus_message_iter_next(&uuid_iter)) {
1418 dev_info->service_index = i;
1421 dbus_message_iter_next(&value_iter);
1427 static void __bt_extract_device_info(DBusMessageIter *msg_iter,
1430 bluetooth_device_info_t *dev_info = NULL;
1431 char *object_path = NULL;
1432 DBusMessageIter value_iter;
1434 /* Parse the signature: oa{sa{sv}}} */
1435 ret_if(dbus_message_iter_get_arg_type(msg_iter) !=
1436 DBUS_TYPE_OBJECT_PATH);
1438 dbus_message_iter_get_basic(msg_iter, &object_path);
1439 ret_if(object_path == NULL);
1441 /* object array (oa) */
1442 ret_if(dbus_message_iter_next(msg_iter) == FALSE);
1443 ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY);
1445 dbus_message_iter_recurse(msg_iter, &value_iter);
1447 /* string array (sa) */
1448 while (dbus_message_iter_get_arg_type(&value_iter) ==
1449 DBUS_TYPE_DICT_ENTRY) {
1450 char *interface_name = NULL;
1451 DBusMessageIter interface_iter;
1453 dbus_message_iter_recurse(&value_iter, &interface_iter);
1455 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
1458 dbus_message_iter_get_basic(&interface_iter, &interface_name);
1460 ret_if(dbus_message_iter_next(&interface_iter) == FALSE);
1462 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
1465 if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) {
1466 BT_DBG("Found a device: %s", object_path);
1467 dev_info = __bt_parse_device_info(&interface_iter);
1470 if (dev_info->paired == TRUE) {
1471 g_array_append_vals(*dev_list, dev_info,
1472 sizeof(bluetooth_device_info_t));
1481 dbus_message_iter_next(&value_iter);
1484 BT_DBG("There is no device interface");
1487 int _bt_get_bonded_devices(GArray **dev_list)
1491 DBusMessageIter reply_iter;
1492 DBusMessageIter value_iter;
1494 DBusConnection *conn;
1496 conn = _bt_get_system_conn();
1497 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1499 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
1500 BT_MANAGER_INTERFACE,
1501 "GetManagedObjects");
1503 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
1505 /* Synchronous call */
1506 dbus_error_init(&err);
1507 reply = dbus_connection_send_with_reply_and_block(
1510 dbus_message_unref(msg);
1513 BT_ERR("Can't get managed objects");
1515 if (dbus_error_is_set(&err)) {
1516 BT_ERR("%s", err.message);
1517 dbus_error_free(&err);
1519 return BLUETOOTH_ERROR_INTERNAL;
1522 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1523 BT_ERR("Fail to iterate the reply");
1524 return BLUETOOTH_ERROR_INTERNAL;
1527 dbus_message_iter_recurse(&reply_iter, &value_iter);
1529 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1530 while (dbus_message_iter_get_arg_type(&value_iter) ==
1531 DBUS_TYPE_DICT_ENTRY) {
1532 DBusMessageIter msg_iter;
1534 dbus_message_iter_recurse(&value_iter, &msg_iter);
1536 __bt_extract_device_info(&msg_iter, dev_list);
1538 dbus_message_iter_next(&value_iter);
1541 return BLUETOOTH_ERROR_NONE;
1544 int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address,
1545 bluetooth_device_info_t *dev_info)
1547 char *object_path = NULL;
1548 DBusGProxy *adapter_proxy;
1549 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1551 BT_CHECK_PARAMETER(device_address, return);
1552 BT_CHECK_PARAMETER(dev_info, return);
1554 adapter_proxy = _bt_get_adapter_proxy();
1555 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1557 _bt_convert_addr_type_to_string(address, device_address->addr);
1559 object_path = _bt_get_device_object_path(address);
1561 retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND);
1563 if (__bt_get_bonded_device_info(object_path,
1564 dev_info) != BLUETOOTH_ERROR_NONE) {
1565 BT_ERR("Can't get the paired device path \n");
1566 g_free(object_path);
1567 return BLUETOOTH_ERROR_INTERNAL;
1569 g_free(object_path);
1570 return BLUETOOTH_ERROR_NONE;
1573 int _bt_get_timeout_value(int *timeout)
1575 time_t current_time;
1578 /* Take current time */
1579 time(¤t_time);
1580 time_diff = difftime(current_time, visible_timer.start_time);
1582 BT_DBG("Time diff = %d\n", time_diff);
1584 *timeout = visible_timer.timeout - time_diff;
1586 return BLUETOOTH_ERROR_NONE;