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 BT_CHECK_PARAMETER(status, return);
898 *status = 0; /* 0: disabled */
900 if (_bt_get_adapter_power())
901 *status = 1; /* 1: enabled */
903 return BLUETOOTH_ERROR_NONE;
906 int _bt_get_local_address(bluetooth_device_address_t *local_address)
911 GValue address_v = { 0 };
913 BT_CHECK_PARAMETER(local_address, return);
915 proxy = _bt_get_adapter_properties_proxy();
916 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
918 if (!dbus_g_proxy_call(proxy, "Get", &err,
919 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
920 G_TYPE_STRING, "Address",
922 G_TYPE_VALUE, &address_v,
925 BT_ERR("Getting property failed: [%s]\n", err->message);
928 return BLUETOOTH_ERROR_INTERNAL;
931 address = (char *)g_value_get_string(&address_v);
934 _bt_convert_addr_string_to_type(local_address->addr, address);
936 return BLUETOOTH_ERROR_INTERNAL;
939 return BLUETOOTH_ERROR_NONE;
942 int _bt_get_local_name(bluetooth_device_name_t *local_name)
946 GValue name_v = { 0 };
949 int ret = BLUETOOTH_ERROR_NONE;
951 BT_CHECK_PARAMETER(local_name, return);
953 proxy = _bt_get_adapter_properties_proxy();
954 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
956 if (!dbus_g_proxy_call(proxy, "Get", &err,
957 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
958 G_TYPE_STRING, "Alias",
960 G_TYPE_VALUE, &name_v,
963 BT_ERR("Getting property failed: [%s]\n", err->message);
966 return BLUETOOTH_ERROR_INTERNAL;
969 name = (char *)g_value_get_string(&name_v);
971 if (name && (strlen(name) > 0)) {
972 /* Check the utf8 valitation & Fill the NULL in the invalid location*/
973 if (!g_utf8_validate(name, -1, (const char **)&ptr))
976 g_strlcpy(local_name->name, name,
977 BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1);
979 ret = BLUETOOTH_ERROR_INTERNAL;
985 int _bt_set_local_name(char *local_name)
989 GError *error = NULL;
992 BT_CHECK_PARAMETER(local_name, return);
994 proxy = _bt_get_adapter_properties_proxy();
995 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
997 if (!g_utf8_validate(local_name, -1, (const char **)&ptr))
1000 g_value_init(&name, G_TYPE_STRING);
1001 g_value_set_string(&name, local_name);
1003 dbus_g_proxy_call(proxy, "Set", &error,
1004 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1005 G_TYPE_STRING, "Alias",
1006 G_TYPE_VALUE, &name,
1007 G_TYPE_INVALID, G_TYPE_INVALID);
1009 g_value_unset(&name);
1012 BT_ERR("SetProperty Fail: %s", error->message);
1013 g_error_free(error);
1014 return BLUETOOTH_ERROR_INTERNAL;
1017 return BLUETOOTH_ERROR_NONE;
1020 int _bt_is_service_used(char *service_uuid, gboolean *used)
1025 GHashTable *hash = NULL;
1027 int ret = BLUETOOTH_ERROR_NONE;
1029 BT_CHECK_PARAMETER(service_uuid, return);
1030 BT_CHECK_PARAMETER(used, return);
1032 proxy = _bt_get_adapter_proxy();
1033 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1035 dbus_g_proxy_call(proxy, "GetProperties", NULL,
1037 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
1038 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
1040 retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
1042 value = g_hash_table_lookup(hash, "UUIDs");
1043 uuids = g_value_get_boxed(value);
1045 if (uuids == NULL) {
1051 for (i = 0; uuids[i] != NULL; i++) {
1052 if (strcasecmp(uuids[i], service_uuid) == 0) {
1060 g_hash_table_destroy(hash);
1064 static gboolean __bt_get_discoverable_property(void)
1067 GValue discoverable_v = { 0 };
1070 proxy = _bt_get_adapter_properties_proxy();
1071 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1073 if (!dbus_g_proxy_call(proxy, "Get", &err,
1074 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1075 G_TYPE_STRING, "Discoverable",
1077 G_TYPE_VALUE, &discoverable_v,
1080 BT_ERR("Getting property failed: [%s]\n", err->message);
1083 return BLUETOOTH_ERROR_INTERNAL;
1086 return g_value_get_boolean(&discoverable_v);
1089 int _bt_get_discoverable_mode(int *mode)
1091 gboolean discoverable;
1092 unsigned int timeout;
1094 BT_CHECK_PARAMETER(mode, return);
1096 discoverable = __bt_get_discoverable_property();
1097 timeout = _bt_get_discoverable_timeout_property();
1099 if (discoverable == TRUE) {
1101 *mode = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE;
1103 *mode = BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE;
1105 *mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE;
1107 return BLUETOOTH_ERROR_NONE;
1110 int _bt_set_discoverable_mode(int discoverable_mode, int timeout)
1112 int ret = BLUETOOTH_ERROR_NONE;
1115 GError *error = NULL;
1116 GValue connectable = { 0 };
1117 GValue discoverable = { 0 };
1118 GValue val_timeout = { 0 };
1121 proxy = _bt_get_adapter_properties_proxy();
1122 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1124 g_value_init(&connectable, G_TYPE_BOOLEAN);
1125 g_value_init(&discoverable, G_TYPE_BOOLEAN);
1126 g_value_init(&val_timeout, G_TYPE_UINT);
1128 switch (discoverable_mode) {
1129 case BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE:
1134 case BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE:
1139 case BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE:
1144 return BLUETOOTH_ERROR_INVALID_PARAM;
1147 g_value_set_boolean(&connectable, pg_scan);
1148 g_value_set_boolean(&discoverable, inq_scan);
1149 g_value_set_uint(&val_timeout, timeout);
1151 dbus_g_proxy_call(proxy, "Set", &error,
1152 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1153 G_TYPE_STRING, "Powered",
1154 G_TYPE_VALUE, &connectable,
1155 G_TYPE_INVALID, G_TYPE_INVALID);
1157 if (error != NULL) {
1158 BT_ERR("Powered set err:[%s]", error->message);
1159 g_error_free(error);
1160 ret = BLUETOOTH_ERROR_INTERNAL;
1164 dbus_g_proxy_call(proxy, "Set", &error,
1165 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1166 G_TYPE_STRING, "Discoverable",
1167 G_TYPE_VALUE, &discoverable,
1168 G_TYPE_INVALID, G_TYPE_INVALID);
1170 if (error != NULL) {
1171 BT_ERR("Discoverable set err:[%s]", error->message);
1172 g_error_free(error);
1173 ret = BLUETOOTH_ERROR_INTERNAL;
1177 dbus_g_proxy_call(proxy, "Set", &error,
1178 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1179 G_TYPE_STRING, "DiscoverableTimeout",
1180 G_TYPE_VALUE, &val_timeout,
1181 G_TYPE_INVALID, G_TYPE_INVALID);
1183 if (error != NULL) {
1184 BT_ERR("Timeout set err:[%s]", error->message);
1185 g_error_free(error);
1186 ret = BLUETOOTH_ERROR_INTERNAL;
1190 if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE)
1193 __bt_set_visible_time(timeout);
1196 g_value_unset(&val_timeout);
1197 g_value_unset(&connectable);
1198 g_value_unset(&discoverable);
1203 int _bt_start_discovery(void)
1207 if (_bt_is_discovering() == TRUE) {
1208 BT_ERR("BT is already in discovering");
1209 return BLUETOOTH_ERROR_IN_PROGRESS;
1212 proxy = _bt_get_adapter_proxy();
1213 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1215 if (!dbus_g_proxy_call(proxy, "StartDiscovery", NULL,
1216 G_TYPE_INVALID, G_TYPE_INVALID)) {
1217 BT_ERR("Discover start failed");
1218 return BLUETOOTH_ERROR_INTERNAL;
1221 _bt_stop_discovery_timeout();
1223 is_discovering = TRUE;
1224 cancel_by_user = FALSE;
1225 /* discovery status will be change in event */
1227 return BLUETOOTH_ERROR_NONE;
1230 int _bt_cancel_discovery(void)
1234 if (_bt_is_discovering() == FALSE) {
1235 BT_ERR("BT is not in discovering");
1236 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
1239 proxy = _bt_get_adapter_proxy();
1240 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1242 if (!dbus_g_proxy_call(proxy, "StopDiscovery", NULL,
1243 G_TYPE_INVALID, G_TYPE_INVALID)) {
1244 BT_ERR("Discover stop failed");
1245 return BLUETOOTH_ERROR_INTERNAL;
1248 cancel_by_user = TRUE;
1249 /* discovery status will be change in event */
1251 return BLUETOOTH_ERROR_NONE;
1254 gboolean _bt_is_discovering(void)
1256 return is_discovering;
1259 gboolean _bt_get_discovering_property(void)
1262 GValue discovering_v = { 0 };
1265 proxy = _bt_get_adapter_properties_proxy();
1266 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1268 if (!dbus_g_proxy_call(proxy, "Get", &err,
1269 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1270 G_TYPE_STRING, "Discovering",
1272 G_TYPE_VALUE, &discovering_v,
1275 BT_ERR("Getting property failed: [%s]\n", err->message);
1278 return BLUETOOTH_ERROR_INTERNAL;
1281 return g_value_get_boolean(&discovering_v);
1284 unsigned int _bt_get_discoverable_timeout_property(void)
1287 GValue timeout_v = { 0 };
1290 proxy = _bt_get_adapter_properties_proxy();
1291 retv_if(proxy == NULL, 0);
1293 if (!dbus_g_proxy_call(proxy, "Get", &err,
1294 G_TYPE_STRING, BT_ADAPTER_INTERFACE,
1295 G_TYPE_STRING, "DiscoverableTimeout",
1297 G_TYPE_VALUE, &timeout_v,
1300 BT_ERR("Getting property failed: [%s]\n", err->message);
1306 return g_value_get_uint(&timeout_v);
1309 static bluetooth_device_info_t *__bt_parse_device_info(DBusMessageIter *item_iter)
1311 DBusMessageIter value_iter;
1312 bluetooth_device_info_t *dev_info;
1314 dbus_message_iter_recurse(item_iter, &value_iter);
1316 if (dbus_message_iter_get_arg_type(&value_iter) != DBUS_TYPE_DICT_ENTRY) {
1321 dev_info = g_malloc0(sizeof(bluetooth_device_info_t));
1323 while (dbus_message_iter_get_arg_type(&value_iter) ==
1324 DBUS_TYPE_DICT_ENTRY) {
1327 DBusMessageIter dict_entry;
1328 DBusMessageIter iter_dict_val;
1330 dbus_message_iter_recurse(&value_iter, &dict_entry);
1332 dbus_message_iter_get_basic(&dict_entry, &key);
1335 dbus_message_iter_next(&value_iter);
1339 if (!dbus_message_iter_next(&dict_entry)) {
1340 dbus_message_iter_next(&value_iter);
1343 dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
1345 if (strcasecmp(key, "Address") == 0) {
1346 const char *address = NULL;
1347 dbus_message_iter_get_basic(&iter_dict_val, &address);
1348 _bt_convert_addr_string_to_type(dev_info->device_address.addr,
1351 } else if (strcasecmp(key, "Class") == 0) {
1353 dbus_message_iter_get_basic(&iter_dict_val, &cod);
1354 _bt_divide_device_class(&dev_info->device_class, cod);
1355 } else if (strcasecmp(key, "Name") == 0) {
1356 dbus_message_iter_get_basic(&iter_dict_val, &value);
1358 /* If there is no Alias */
1359 if (strlen(dev_info->device_name.name) == 0) {
1360 g_strlcpy(dev_info->device_name.name, value,
1361 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1363 } else if (strcasecmp(key, "Alias") == 0) {
1364 dbus_message_iter_get_basic(&iter_dict_val, &value);
1366 /* Overwrite the name */
1368 memset(dev_info->device_name.name, 0x00,
1369 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1370 g_strlcpy(dev_info->device_name.name, value,
1371 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
1373 } else if (strcasecmp(key, "Connected") == 0) {
1374 dbus_message_iter_get_basic(&iter_dict_val,
1375 &dev_info->connected);
1376 } else if (strcasecmp(key, "Paired") == 0) {
1377 dbus_message_iter_get_basic(&iter_dict_val,
1379 } else if (strcasecmp(key, "Trusted") == 0) {
1380 dbus_message_iter_get_basic(&iter_dict_val,
1382 } else if (strcasecmp(key, "RSSI") == 0) {
1383 dbus_message_iter_get_basic(&iter_dict_val,
1385 } else if (strcasecmp(key, "UUIDs") == 0) {
1386 DBusMessageIter uuid_iter;
1390 dbus_message_iter_recurse(&iter_dict_val, &uuid_iter);
1392 while (dbus_message_iter_get_arg_type(&uuid_iter) != DBUS_TYPE_INVALID) {
1393 dbus_message_iter_get_basic(&uuid_iter,
1396 g_strlcpy(dev_info->uuids[i], value,
1397 BLUETOOTH_UUID_STRING_MAX);
1399 parts = g_strsplit(value, "-", -1);
1401 if (parts == NULL || parts[0] == NULL)
1404 dev_info->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
1408 if (!dbus_message_iter_next(&uuid_iter)) {
1413 dev_info->service_index = i;
1416 dbus_message_iter_next(&value_iter);
1422 static void __bt_extract_device_info(DBusMessageIter *msg_iter,
1425 bluetooth_device_info_t *dev_info = NULL;
1426 char *object_path = NULL;
1427 DBusMessageIter value_iter;
1429 /* Parse the signature: oa{sa{sv}}} */
1430 ret_if(dbus_message_iter_get_arg_type(msg_iter) !=
1431 DBUS_TYPE_OBJECT_PATH);
1433 dbus_message_iter_get_basic(msg_iter, &object_path);
1434 ret_if(object_path == NULL);
1436 /* object array (oa) */
1437 ret_if(dbus_message_iter_next(msg_iter) == FALSE);
1438 ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY);
1440 dbus_message_iter_recurse(msg_iter, &value_iter);
1442 /* string array (sa) */
1443 while (dbus_message_iter_get_arg_type(&value_iter) ==
1444 DBUS_TYPE_DICT_ENTRY) {
1445 char *interface_name = NULL;
1446 DBusMessageIter interface_iter;
1448 dbus_message_iter_recurse(&value_iter, &interface_iter);
1450 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
1453 dbus_message_iter_get_basic(&interface_iter, &interface_name);
1455 ret_if(dbus_message_iter_next(&interface_iter) == FALSE);
1457 ret_if(dbus_message_iter_get_arg_type(&interface_iter) !=
1460 if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) {
1461 BT_DBG("Found a device: %s", object_path);
1462 dev_info = __bt_parse_device_info(&interface_iter);
1465 if (dev_info->paired == TRUE) {
1466 g_array_append_vals(*dev_list, dev_info,
1467 sizeof(bluetooth_device_info_t));
1476 dbus_message_iter_next(&value_iter);
1479 BT_DBG("There is no device interface");
1482 int _bt_get_bonded_devices(GArray **dev_list)
1486 DBusMessageIter reply_iter;
1487 DBusMessageIter value_iter;
1489 DBusConnection *conn;
1491 conn = _bt_get_system_conn();
1492 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1494 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
1495 BT_MANAGER_INTERFACE,
1496 "GetManagedObjects");
1498 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
1500 /* Synchronous call */
1501 dbus_error_init(&err);
1502 reply = dbus_connection_send_with_reply_and_block(
1505 dbus_message_unref(msg);
1508 BT_ERR("Can't get managed objects");
1510 if (dbus_error_is_set(&err)) {
1511 BT_ERR("%s", err.message);
1512 dbus_error_free(&err);
1514 return BLUETOOTH_ERROR_INTERNAL;
1517 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1518 BT_ERR("Fail to iterate the reply");
1519 return BLUETOOTH_ERROR_INTERNAL;
1522 dbus_message_iter_recurse(&reply_iter, &value_iter);
1524 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1525 while (dbus_message_iter_get_arg_type(&value_iter) ==
1526 DBUS_TYPE_DICT_ENTRY) {
1527 DBusMessageIter msg_iter;
1529 dbus_message_iter_recurse(&value_iter, &msg_iter);
1531 __bt_extract_device_info(&msg_iter, dev_list);
1533 dbus_message_iter_next(&value_iter);
1536 return BLUETOOTH_ERROR_NONE;
1539 int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address,
1540 bluetooth_device_info_t *dev_info)
1542 char *object_path = NULL;
1543 DBusGProxy *adapter_proxy;
1544 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1546 BT_CHECK_PARAMETER(device_address, return);
1547 BT_CHECK_PARAMETER(dev_info, return);
1549 adapter_proxy = _bt_get_adapter_proxy();
1550 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1552 _bt_convert_addr_type_to_string(address, device_address->addr);
1554 object_path = _bt_get_device_object_path(address);
1556 retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND);
1558 if (__bt_get_bonded_device_info(object_path,
1559 dev_info) != BLUETOOTH_ERROR_NONE) {
1560 BT_ERR("Can't get the paired device path \n");
1561 g_free(object_path);
1562 return BLUETOOTH_ERROR_INTERNAL;
1564 g_free(object_path);
1565 return BLUETOOTH_ERROR_NONE;
1568 int _bt_get_timeout_value(int *timeout)
1570 time_t current_time;
1573 /* Take current time */
1574 time(¤t_time);
1575 time_diff = difftime(current_time, visible_timer.start_time);
1577 BT_DBG("Time diff = %d\n", time_diff);
1579 *timeout = visible_timer.timeout - time_diff;
1581 return BLUETOOTH_ERROR_NONE;