Add a libnotify/gtk popup system to bluetooth-frwk.
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-adapter.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <stdio.h>
21 #include <dbus/dbus-glib.h>
22 #include <dbus/dbus.h>
23 #include <glib.h>
24 #include <dlog.h>
25 #include <string.h>
26 #include <vconf.h>
27 #include <status.h>
28 #ifndef LIBNOTIFY_SUPPORT
29 #include <syspopup_caller.h>
30 #endif
31 #include <aul.h>
32 #include <notification.h>
33
34 #include "alarm.h"
35
36 #include "bluetooth-api.h"
37 #include "bt-internal-types.h"
38
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"
48
49 typedef struct {
50         guint event_id;
51         int timeout;
52         time_t start_time;
53         int alarm_id;
54 } bt_adapter_timer_t;
55
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;
62
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"
66
67 static gboolean __bt_timeout_handler(gpointer user_data)
68 {
69         int result = BLUETOOTH_ERROR_NONE;
70         time_t current_time;
71         int time_diff;
72
73         /* Take current time */
74         time(&current_time);
75         time_diff = difftime(current_time, visible_timer.start_time);
76
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,
82                         DBUS_TYPE_INVALID);
83
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;
88
89                 if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
90                         BT_DBG("Set vconf failed\n");
91                 return FALSE;
92         }
93
94         return TRUE;
95 }
96
97 static int __bt_visibility_alarm_cb(alarm_id_t alarm_id, void* user_param)
98 {
99         BT_DBG("__bt_visibility_alarm_cb \n");
100
101         /* Switch Off visibility in Bluez */
102         _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0);
103         visible_timer.alarm_id = 0;
104         alarmmgr_fini();
105         return 0;
106 }
107
108 static void __bt_visibility_alarm_create()
109 {
110         alarm_id_t alarm_id;
111         int result;
112
113         result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, visible_timer.timeout,
114                                                 0, NULL, &alarm_id);
115         if(result < 0) {
116                 BT_DBG("Failed to create alarm error = %d\n", result);
117                 alarmmgr_fini();
118         } else {
119                 BT_DBG("Alarm created = %d\n", alarm_id);
120                 visible_timer.alarm_id = alarm_id;
121         }
122 }
123
124 int __bt_set_visible_time(int timeout)
125 {
126         int result;
127
128         if (visible_timer.event_id > 0) {
129                 g_source_remove(visible_timer.event_id);
130                 visible_timer.event_id = 0;
131         }
132
133         if (visible_timer.alarm_id > 0) {
134                 alarmmgr_remove_alarm(visible_timer.alarm_id);
135                 visible_timer.alarm_id = 0;
136         }
137
138         visible_timer.timeout = timeout;
139
140         if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0)
141                 BT_ERR("Set vconf failed\n");
142
143         if (timeout <= 0)
144                 return BLUETOOTH_ERROR_NONE;
145
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);
150
151         /* Set Alarm timer to switch off BT */
152         result = alarmmgr_init("bt-service");
153         if (result != 0)
154                 return BLUETOOTH_ERROR_INTERNAL;
155
156         result = alarmmgr_set_cb(__bt_visibility_alarm_cb, NULL);
157         if (result != 0)
158                 return BLUETOOTH_ERROR_INTERNAL;
159
160         __bt_visibility_alarm_create();
161
162         return BLUETOOTH_ERROR_NONE;
163 }
164
165 static void __bt_get_service_list(GValue *value, bluetooth_device_info_t *dev)
166 {
167         int i;
168         char **uuids;
169         char **parts;
170
171         ret_if(value == NULL);
172         ret_if(dev == NULL);
173
174         uuids = g_value_get_boxed(value);
175         ret_if(uuids == NULL);
176
177         dev->service_index = 0;
178
179         for (i = 0; uuids[i] != NULL; i++) {
180                 g_strlcpy(dev->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX);
181
182                 parts = g_strsplit(uuids[i], "-", -1);
183
184                 if (parts == NULL || parts[0] == NULL)
185                         break;
186
187                 dev->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
188                 g_strfreev(parts);
189
190                 dev->service_index++;
191         }
192 }
193
194 static int __bt_get_bonded_device_info(gchar *device_path,
195                 bluetooth_device_info_t *dev_info)
196 {
197         GValue *value = { 0 };
198         GError *err = NULL;
199         DBusGProxy *device_proxy;
200         const gchar *address;
201         const gchar *name;
202         unsigned int cod;
203         gint rssi;
204         gboolean trust;
205         gboolean paired;
206         gboolean connected;
207         GHashTable *hash = NULL;
208         int ret;
209         DBusGConnection *conn;
210
211         BT_CHECK_PARAMETER(device_path, return);
212         BT_CHECK_PARAMETER(dev_info, return);
213
214         conn = _bt_get_system_gconn();
215         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
216
217         device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
218                                 device_path, BT_DEVICE_INTERFACE);
219
220         retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
221
222         dbus_g_proxy_call(device_proxy, "GetProperties", &err,
223                                 G_TYPE_INVALID,
224                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
225                                 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
226
227         g_object_unref(device_proxy);
228
229         if (err != NULL) {
230                 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
231                 g_error_free(err);
232                 return BLUETOOTH_ERROR_INTERNAL;
233         }
234
235         if (hash != NULL) {
236                 value = g_hash_table_lookup(hash, "Paired");
237                 paired = g_value_get_boolean(value);
238
239                 value = g_hash_table_lookup(hash, "Address");
240                 address = value ? g_value_get_string(value) : NULL;
241
242                 value = g_hash_table_lookup(hash, "Alias");
243                 name = value ? g_value_get_string(value) : NULL;
244
245                 if (name != NULL)
246                         BT_DBG("Alias Name [%s]", name);
247                 else {
248                         value = g_hash_table_lookup(hash, "Name");
249                         name = value ? g_value_get_string(value) : NULL;
250                 }
251
252                 value = g_hash_table_lookup(hash, "Class");
253                 cod = value ? g_value_get_uint(value) : 0;
254
255                 value = g_hash_table_lookup(hash, "Connected");
256                 connected = value ? g_value_get_boolean(value) : FALSE;
257
258                 value = g_hash_table_lookup(hash, "Trusted");
259                 trust = value ? g_value_get_boolean(value) : FALSE;
260
261                 if ((paired == FALSE) && (trust == FALSE)) {
262                         return BLUETOOTH_ERROR_NOT_PAIRED;
263                 }
264
265                 value = g_hash_table_lookup(hash, "RSSI");
266                 rssi = value ? g_value_get_int(value) : 0;
267
268                 value = g_hash_table_lookup(hash, "UUIDs");
269                 __bt_get_service_list(value, dev_info);
270
271                 _bt_convert_addr_string_to_type(dev_info->device_address.addr,
272                                                 address);
273
274                 _bt_divide_device_class(&dev_info->device_class, cod);
275
276                 g_strlcpy(dev_info->device_name.name, name,
277                                 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
278
279                 dev_info->rssi = rssi;
280                 dev_info->trust = trust;
281                 dev_info->paired = paired;
282                 dev_info->connected = connected;
283                 g_hash_table_destroy(hash);
284                 ret = BLUETOOTH_ERROR_NONE;
285         } else {
286                 BT_ERR("Hash is NULL\n");
287                 ret = BLUETOOTH_ERROR_INTERNAL;
288         }
289
290         return ret;
291 }
292
293 void _bt_set_discovery_status(gboolean mode)
294 {
295         is_discovering = mode;
296 }
297
298 void _bt_set_cancel_by_user(gboolean value)
299 {
300         cancel_by_user = value;
301 }
302
303 gboolean _bt_get_cancel_by_user(void)
304 {
305         return cancel_by_user;
306 }
307
308 static void __bt_flight_mode_cb(keynode_t *node, void *data)
309 {
310         gboolean flight_mode = FALSE;
311         int bt_status;
312
313         BT_DBG("key=%s\n", vconf_keynode_get_name(node));
314
315         bt_status = _bt_adapter_get_status();
316
317         if (vconf_keynode_get_type(node) == VCONF_TYPE_BOOL) {
318                 flight_mode = vconf_keynode_get_bool(node);
319
320                 BT_DBG("value=%d\n", flight_mode);
321
322                 if (flight_mode == TRUE) {
323                         BT_DBG("Deactivate Bluetooth Service\n");
324                         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
325                                 BT_DBG("Set vconf failed+\n");
326
327                         if (bt_status == BT_ACTIVATED)
328                                 _bt_disable_adapter();
329                 } else {
330
331                         int value = 0;
332
333                         if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &value))
334                                 BT_ERR("Fail get flight mode value");
335
336                         if (value == 0)
337                                 return;
338
339                         BT_DBG("Activate Bluetooth Service\n");
340                         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0))
341                                 BT_DBG("Set vconf failed\n");
342
343                         if (bt_status == BT_DEACTIVATED)
344                                 _bt_enable_adapter();
345                 }
346         }
347 }
348
349 static void __launch_bt_service(int status, int run_type)
350 {
351         bundle *kb;
352         char status_val[5] = { 0, };
353         char run_type_val[5] = { 0, };
354
355         snprintf(status_val, sizeof(status_val), "%d", status);
356         snprintf(run_type_val, sizeof(run_type_val), "%d", run_type);
357
358         BT_DBG("status: %s, run_type: %s", status_val, run_type_val);
359
360         kb = bundle_create();
361
362         bundle_add(kb, "launch-type", "setstate");
363         bundle_add(kb, "status", status_val);
364         bundle_add(kb, "run-type", run_type_val);
365
366         aul_launch_app("com.samsung.bluetooth", kb);
367
368         bundle_free(kb);
369 }
370
371 static void __bt_adapter_set_status(bt_status_t status)
372 {
373         adapter_status = status;
374 }
375
376 bt_status_t _bt_adapter_get_status(void)
377 {
378         return adapter_status;
379 }
380
381 static void __bt_phone_name_changed_cb(keynode_t *node, void *data)
382 {
383         char *phone_name = NULL;
384         char *ptr = NULL;
385
386         if (node == NULL)
387                 return;
388
389         if (vconf_keynode_get_type(node) == VCONF_TYPE_STRING) {
390                 phone_name = vconf_keynode_get_str(node);
391                 if (phone_name && strlen(phone_name) != 0) {
392                         if (!g_utf8_validate(phone_name, -1,
393                                                         (const char **)&ptr))
394                                 *ptr = '\0';
395
396                         _bt_set_local_name(phone_name);
397                 }
398         }
399 }
400
401 static void __bt_set_visible_mode(void)
402 {
403         int timeout;
404
405         if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0)
406                 BT_ERR("Fail to get the timeout value");
407
408         /* -1: Always on */
409         if (timeout == -1) {
410                 if (_bt_set_discoverable_mode(
411                         BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE,
412                         timeout) != BLUETOOTH_ERROR_NONE) {
413                         if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
414                                 BT_ERR("Set vconf failed");
415                 }
416         }
417 }
418
419 static void __bt_set_local_name(void)
420 {
421         char *phone_name = NULL;
422         char *ptr = NULL;
423
424         phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
425
426         if (!phone_name)
427                 return;
428
429         if (strlen(phone_name) != 0) {
430                 if (!g_utf8_validate(phone_name, -1, (const char **)&ptr))
431                         *ptr = '\0';
432                 _bt_set_local_name(phone_name);
433         }
434         free(phone_name);
435 }
436
437 static int __bt_set_enabled(void)
438 {
439         int enabled = FALSE;
440         int result = BLUETOOTH_ERROR_NONE;
441
442         _bt_check_adapter(&enabled);
443
444         if (enabled == FALSE) {
445                 BT_ERR("Bluetoothd is not running");
446                 return BLUETOOTH_ERROR_INTERNAL;
447         }
448
449         __bt_set_visible_mode();
450
451         __bt_set_local_name();
452
453         /* Update Bluetooth Status to notify other modules */
454         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0)
455                 BT_ERR("Set vconf failed\n");
456
457         if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
458                 BT_ERR("Set vconf failed\n");
459
460         /* Send enabled event to API */
461         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED,
462                                 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
463
464         return BLUETOOTH_ERROR_NONE;
465 }
466
467 static void __bt_set_disabled(int result)
468 {
469         /* Update Bluetooth Status to notify other modules */
470         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
471                 BT_ERR("Set vconf failed\n");
472
473         if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
474                 BT_ERR("Set vconf failed\n");
475
476         /* Send disabled event */
477         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
478                                 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
479 }
480
481 void *_bt_get_adapter_agent(void)
482 {
483         return adapter_agent;
484 }
485
486 void _bt_handle_flight_mode_noti(void)
487 {
488         BT_DBG("+");
489         vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
490                         __bt_flight_mode_cb, NULL);
491         BT_DBG("-");
492 }
493
494 void _bt_handle_adapter_added(void)
495 {
496          adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE);
497          if (!adapter_agent) {
498                 BT_ERR("Fail to register agent");
499                 return;
500          }
501
502         if (!aul_app_is_running("com.samsung.bluetooth"))
503                 __launch_bt_service(0, 0);
504
505         if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE)
506                 BT_ERR("Fail to register media player");
507
508         if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE)
509                 BT_ERR("Fail to init obex server");
510
511         /* add the vconf noti handler */
512         vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
513                                         __bt_phone_name_changed_cb, NULL);
514
515         vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
516                         __bt_flight_mode_cb, NULL);
517
518         __bt_set_enabled();
519
520         __bt_adapter_set_status(BT_ACTIVATED);
521 }
522
523 void _bt_handle_adapter_removed(void)
524 {
525         __bt_adapter_set_status(BT_DEACTIVATED);
526
527         vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
528                                 (vconf_callback_fn)__bt_phone_name_changed_cb);
529
530         _bt_destroy_agent(adapter_agent);
531         adapter_agent = NULL;
532
533         __bt_set_disabled(BLUETOOTH_ERROR_NONE);
534
535         _bt_terminate_service(NULL);
536 }
537
538 DBusGProxy *_bt_init_core_proxy(void)
539 {
540        DBusGProxy *proxy;
541         DBusGConnection *conn;
542
543         conn = _bt_get_system_gconn();
544         if (!conn)
545                 return NULL;
546
547        proxy = dbus_g_proxy_new_for_name(conn, BT_CORE_NAME,
548                        BT_CORE_PATH, BT_CORE_INTERFACE);
549         if (!proxy)
550                 return NULL;
551
552        core_proxy = proxy;
553
554        return proxy;
555 }
556
557 static DBusGProxy *__bt_get_core_proxy(void)
558 {
559        return (core_proxy) ? core_proxy : _bt_init_core_proxy();
560 }
561
562 gboolean __bt_enable_timeout_cb(gpointer user_data)
563 {
564         DBusGProxy *proxy;
565
566         retv_if(_bt_adapter_get_status() == BT_ACTIVATED, FALSE);
567
568         proxy = __bt_get_core_proxy();
569         if (!proxy)
570                 return BLUETOOTH_ERROR_INTERNAL;
571
572         /* Clean up the process */
573         if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL,
574                         G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
575                         BT_ERR("Bt core call failed");
576         }
577
578         __bt_adapter_set_status(BT_DEACTIVATED);
579
580         __bt_set_disabled(BLUETOOTH_ERROR_TIMEOUT);
581
582         /* Display notification */
583         notification_status_message_post(BT_STR_NOT_SUPPORT);
584
585         _bt_terminate_service(NULL);
586
587         return FALSE;
588 }
589
590 int _bt_enable_adapter(void)
591 {
592         DBusGProxy *proxy;
593         GError *err = NULL;
594
595         BT_DBG("");
596
597         if (_bt_adapter_get_status() == BT_ACTIVATING) {
598                         BT_DBG("Enabling in progress");
599                         return BLUETOOTH_ERROR_IN_PROGRESS;
600         }
601
602         if (_bt_adapter_get_status() == BT_ACTIVATED) {
603                         BT_DBG("Already enabled");
604                         return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED;
605         }
606
607         __bt_adapter_set_status(BT_ACTIVATING);
608
609         proxy = __bt_get_core_proxy();
610         if (!proxy)
611                 return BLUETOOTH_ERROR_INTERNAL;
612
613          if (dbus_g_proxy_call_with_timeout(proxy, "EnableAdapter",
614                                         BT_ENABLE_TIMEOUT, &err,
615                                         G_TYPE_INVALID,
616                                         G_TYPE_INVALID) == FALSE) {
617
618                 __bt_adapter_set_status(BT_DEACTIVATED);
619
620                 if (err != NULL) {
621                         BT_ERR("Bt core call failed: [%s]", err->message);
622                         g_error_free(err);
623                 }
624
625                 /* Clean up the process */
626                 if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL,
627                                 G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
628                                 BT_ERR("Bt core call failed");
629                 }
630
631                 /* Display notification */
632                 notification_status_message_post(BT_STR_NOT_SUPPORT);
633
634                 /* Terminate myself */
635                 g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
636                 return BLUETOOTH_ERROR_INTERNAL;
637         }
638
639         g_timeout_add(BT_ENABLE_TIMEOUT,
640                         (GSourceFunc)__bt_enable_timeout_cb,
641                         NULL);
642
643         return BLUETOOTH_ERROR_NONE;
644 }
645
646 int _bt_disable_adapter(void)
647 {
648         DBusGProxy *proxy;
649
650         BT_DBG("");
651
652         if (_bt_adapter_get_status() == BT_DEACTIVATING) {
653                         BT_DBG("Disabling in progress");
654                         return BLUETOOTH_ERROR_IN_PROGRESS;
655         }
656
657         if (_bt_adapter_get_status() == BT_DEACTIVATED) {
658                         BT_DBG("Already disabled");
659                         return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
660         }
661
662         __bt_adapter_set_status(BT_DEACTIVATING);
663
664         proxy = __bt_get_core_proxy();
665         if (!proxy)
666                 return BLUETOOTH_ERROR_INTERNAL;
667
668         if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL,
669                                        G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
670                 BT_ERR("Bt core call failed");
671                 __bt_adapter_set_status(BT_ACTIVATED);
672                 return BLUETOOTH_ERROR_INTERNAL;
673        }
674
675         return BLUETOOTH_ERROR_NONE;
676 }
677
678 int _bt_reset_adapter(void)
679 {
680         DBusGProxy *proxy;
681
682         BT_DBG("");
683
684         proxy = __bt_get_core_proxy();
685         if (!proxy)
686                 return BLUETOOTH_ERROR_INTERNAL;
687
688         if (dbus_g_proxy_call(proxy, "ResetAdapter", NULL,
689                                        G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
690                 BT_ERR("Bt core call failed");
691                 return BLUETOOTH_ERROR_INTERNAL;
692         }
693
694         /* Terminate myself */
695         if (_bt_adapter_get_status() == BT_DEACTIVATED) {
696                 g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
697         }
698
699         return BLUETOOTH_ERROR_NONE;
700 }
701
702 int _bt_check_adapter(int *status)
703 {
704         DBusGProxy *proxy;
705         char *adapter_path = NULL;
706
707         BT_CHECK_PARAMETER(status, return);
708
709         *status = 0; /* 0: disabled */
710
711         proxy = _bt_get_manager_proxy();
712         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
713
714         if (!dbus_g_proxy_call(proxy, "DefaultAdapter", NULL,
715                         G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
716                         &adapter_path, G_TYPE_INVALID)) {
717                 BT_ERR("Fait to get DefaultAdapter");
718                 return BLUETOOTH_ERROR_NONE;
719         }
720
721         if (adapter_path != NULL)
722                 *status = 1; /* 1: enabled */
723
724         g_free(adapter_path);
725         return BLUETOOTH_ERROR_NONE;
726 }
727
728 int _bt_get_local_address(bluetooth_device_address_t *local_address)
729 {
730         DBusGProxy *proxy;
731         GHashTable *hash = NULL;
732         GValue *value;
733         char *address = NULL;
734
735         BT_CHECK_PARAMETER(local_address, return);
736
737         proxy = _bt_get_adapter_proxy();
738         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
739
740         dbus_g_proxy_call(proxy, "GetProperties", NULL,
741                         G_TYPE_INVALID,
742                         dbus_g_type_get_map("GHashTable",
743                         G_TYPE_STRING, G_TYPE_VALUE),
744                         &hash, G_TYPE_INVALID);
745
746         if (hash != NULL) {
747                 value = g_hash_table_lookup(hash, "Address");
748                 address = (char *)(value ? g_value_dup_string(value) : NULL);
749                 g_hash_table_destroy(hash);
750         }
751
752         if (address) {
753                 _bt_convert_addr_string_to_type(local_address->addr, address);
754                 g_free(address);
755         } else {
756                 return BLUETOOTH_ERROR_INTERNAL;
757         }
758
759         return BLUETOOTH_ERROR_NONE;
760 }
761
762 int _bt_get_local_name(bluetooth_device_name_t *local_name)
763 {
764         DBusGProxy *proxy;
765         GHashTable *hash = NULL;
766         GValue *value;
767         char *name = NULL;
768         char *ptr = NULL;
769         int ret = BLUETOOTH_ERROR_NONE;
770
771         BT_CHECK_PARAMETER(local_name, return);
772
773         proxy = _bt_get_adapter_proxy();
774         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
775
776         dbus_g_proxy_call(proxy, "GetProperties", NULL,
777                         G_TYPE_INVALID,
778                         dbus_g_type_get_map("GHashTable",
779                         G_TYPE_STRING, G_TYPE_VALUE),
780                         &hash, G_TYPE_INVALID);
781
782         if (hash != NULL) {
783                 value = g_hash_table_lookup(hash, "Name");
784                 name = (char *)(value ? g_value_get_string(value) : NULL);
785         }
786
787         if (name && (strlen(name) > 0)) {
788                 /* Check the utf8 valitation & Fill the NULL in the invalid location*/
789                 if (!g_utf8_validate(name, -1, (const char **)&ptr))
790                         *ptr = '\0';
791
792                 g_strlcpy(local_name->name, name,
793                                 BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1);
794         } else {
795                 ret = BLUETOOTH_ERROR_INTERNAL;
796         }
797
798         g_hash_table_destroy(hash);
799         return ret;
800 }
801
802 int _bt_set_local_name(char *local_name)
803 {
804         GValue name = { 0 };
805         DBusGProxy *proxy;
806         GError *error = NULL;
807         char *ptr = NULL;
808
809         BT_CHECK_PARAMETER(local_name, return);
810
811         proxy = _bt_get_adapter_proxy();
812         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
813
814         if (!g_utf8_validate(local_name, -1, (const char **)&ptr))
815                 *ptr = '\0';
816
817         g_value_init(&name, G_TYPE_STRING);
818         g_value_set_string(&name, local_name);
819
820         dbus_g_proxy_call(proxy, "SetProperty",
821                         &error, G_TYPE_STRING, "Name",
822                         G_TYPE_VALUE, &name, G_TYPE_INVALID, G_TYPE_INVALID);
823
824         g_value_unset(&name);
825
826         if (error) {
827                 BT_ERR("SetProperty Fail: %s", error->message);
828                 g_error_free(error);
829                 return BLUETOOTH_ERROR_INTERNAL;
830         }
831
832         return BLUETOOTH_ERROR_NONE;
833 }
834
835 int _bt_is_service_used(char *service_uuid, gboolean *used)
836 {
837         char **uuids;
838         int i;
839         DBusGProxy *proxy;
840         GHashTable *hash = NULL;
841         GValue *value;
842         int ret = BLUETOOTH_ERROR_NONE;
843
844         BT_CHECK_PARAMETER(service_uuid, return);
845         BT_CHECK_PARAMETER(used, return);
846
847         proxy = _bt_get_adapter_proxy();
848         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
849
850         dbus_g_proxy_call(proxy, "GetProperties", NULL,
851                           G_TYPE_INVALID,
852                           dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
853                           G_TYPE_VALUE), &hash, G_TYPE_INVALID);
854
855         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
856
857         value = g_hash_table_lookup(hash, "UUIDs");
858         uuids = g_value_get_boxed(value);
859
860         if (uuids == NULL) {
861                 /* Normal case */
862                 *used = FALSE;
863                 goto done;
864         }
865
866         for (i = 0; uuids[i] != NULL; i++) {
867                 if (strcasecmp(uuids[i], service_uuid) == 0) {
868                         *used = TRUE;
869                         goto done;
870                 }
871         }
872
873         *used = FALSE;
874 done:
875         g_hash_table_destroy(hash);
876         return ret;
877 }
878
879 int _bt_get_discoverable_mode(int *mode)
880 {
881         DBusGProxy *proxy;
882         GHashTable *hash = NULL;
883         GValue *value;
884         GValue *timeout_value;
885
886         BT_CHECK_PARAMETER(mode, return);
887
888         proxy = _bt_get_adapter_proxy();
889         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
890
891         dbus_g_proxy_call(proxy, "GetProperties", NULL,
892                           G_TYPE_INVALID,
893                           dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
894                           G_TYPE_VALUE), &hash, G_TYPE_INVALID);
895
896         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
897
898         value = g_hash_table_lookup(hash, "Discoverable");
899         timeout_value = g_hash_table_lookup(hash, "DiscoverableTimeout");
900
901         retv_if(value == NULL, BLUETOOTH_ERROR_INTERNAL);
902
903         if (g_value_get_boolean(value)) {
904                 if (g_value_get_uint(timeout_value) == 0)
905                         *mode = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE;
906                 else
907                         *mode = BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE;
908         } else {
909                 *mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE;
910         }
911         g_hash_table_destroy(hash);
912         return BLUETOOTH_ERROR_NONE;
913 }
914
915 int _bt_set_discoverable_mode(int discoverable_mode, int timeout)
916 {
917         int ret = BLUETOOTH_ERROR_NONE;
918         gboolean inq_scan;
919         gboolean pg_scan;
920         GError *error = NULL;
921         GValue connectable = { 0 };
922         GValue discoverable = { 0 };
923         GValue val_timeout = { 0 };
924         DBusGProxy *proxy;
925
926         proxy = _bt_get_adapter_proxy();
927         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
928
929         g_value_init(&connectable, G_TYPE_BOOLEAN);
930         g_value_init(&discoverable, G_TYPE_BOOLEAN);
931         g_value_init(&val_timeout, G_TYPE_UINT);
932
933         switch (discoverable_mode) {
934         case BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE:
935                 pg_scan = TRUE;
936                 inq_scan = FALSE;
937                 timeout = 0;
938                 break;
939         case BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE:
940                 pg_scan = TRUE;
941                 inq_scan = TRUE;
942                 timeout = 0;
943                 break;
944         case BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE:
945                 inq_scan = TRUE;
946                 pg_scan = TRUE;
947                 break;
948         default:
949                 return BLUETOOTH_ERROR_INVALID_PARAM;
950         }
951
952         g_value_set_boolean(&connectable, pg_scan);
953         g_value_set_boolean(&discoverable, inq_scan);
954         g_value_set_uint(&val_timeout, timeout);
955
956         dbus_g_proxy_call(proxy, "SetProperty", &error,
957                                    G_TYPE_STRING, "Powered",
958                                    G_TYPE_VALUE, &connectable,
959                                    G_TYPE_INVALID, G_TYPE_INVALID);
960
961         if (error != NULL) {
962                 BT_ERR("Powered set err:[%s]", error->message);
963                 g_error_free(error);
964                 ret = BLUETOOTH_ERROR_INTERNAL;
965                 goto done;
966         }
967
968         dbus_g_proxy_call(proxy, "SetProperty", &error,
969                                    G_TYPE_STRING, "Discoverable",
970                                    G_TYPE_VALUE, &discoverable,
971                                    G_TYPE_INVALID, G_TYPE_INVALID);
972
973         if (error != NULL) {
974                 BT_ERR("Discoverable set err:[%s]", error->message);
975                 g_error_free(error);
976                 ret = BLUETOOTH_ERROR_INTERNAL;
977                 goto done;
978         }
979
980         dbus_g_proxy_call(proxy, "SetProperty", &error,
981                                    G_TYPE_STRING, "DiscoverableTimeout",
982                                    G_TYPE_VALUE, &val_timeout,
983                                    G_TYPE_INVALID, G_TYPE_INVALID);
984
985         if (error != NULL) {
986                 BT_ERR("Timeout set err:[%s]", error->message);
987                 g_error_free(error);
988                 ret = BLUETOOTH_ERROR_INTERNAL;
989                 goto done;
990         }
991
992         if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE)
993                 timeout = -1;
994
995         ret = __bt_set_visible_time(timeout);
996
997 done:
998         g_value_unset(&val_timeout);
999         g_value_unset(&connectable);
1000         g_value_unset(&discoverable);
1001
1002         return ret;
1003 }
1004
1005 int _bt_start_discovery(void)
1006 {
1007         DBusGProxy *proxy;
1008
1009         if (_bt_is_discovering() == TRUE) {
1010                 BT_ERR("BT is already in discovering");
1011                 return BLUETOOTH_ERROR_IN_PROGRESS;
1012         }
1013
1014         proxy = _bt_get_adapter_proxy();
1015         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1016
1017         if (!dbus_g_proxy_call(proxy, "StartDiscovery", NULL,
1018                                G_TYPE_INVALID, G_TYPE_INVALID)) {
1019                 BT_ERR("Discover start failed");
1020                 return BLUETOOTH_ERROR_INTERNAL;
1021         }
1022
1023         is_discovering = TRUE;
1024         cancel_by_user = FALSE;
1025         /* discovery status will be change in event */
1026
1027         return BLUETOOTH_ERROR_NONE;
1028 }
1029
1030 int _bt_cancel_discovery(void)
1031 {
1032         DBusGProxy *proxy;
1033
1034         if (_bt_is_discovering() == FALSE) {
1035                 BT_ERR("BT is not in discovering");
1036                 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
1037         }
1038
1039         proxy = _bt_get_adapter_proxy();
1040         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1041
1042         if (!dbus_g_proxy_call(proxy, "StopDiscovery", NULL,
1043                                G_TYPE_INVALID, G_TYPE_INVALID)) {
1044                 BT_ERR("Discover stop failed");
1045                 return BLUETOOTH_ERROR_INTERNAL;
1046         }
1047
1048         cancel_by_user = TRUE;
1049         /* discovery status will be change in event */
1050
1051         return BLUETOOTH_ERROR_NONE;
1052 }
1053
1054 gboolean _bt_is_discovering(void)
1055 {
1056         return is_discovering;
1057 }
1058
1059 gboolean _bt_get_discoverying_property(void)
1060 {
1061         DBusGProxy *proxy;
1062         GHashTable *hash = NULL;
1063         GValue *value;
1064         gboolean is_discover = FALSE;
1065
1066         proxy = _bt_get_adapter_proxy();
1067         retv_if(proxy == NULL, FALSE);
1068
1069         dbus_g_proxy_call(proxy, "GetProperties", NULL,
1070                           G_TYPE_INVALID,
1071                           dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
1072                           G_TYPE_VALUE), &hash, G_TYPE_INVALID);
1073
1074         retv_if(hash == NULL, FALSE);
1075
1076         value = g_hash_table_lookup(hash, "Discovering");
1077         is_discover = g_value_get_boolean(value);
1078         g_hash_table_destroy(hash);
1079         return is_discover;
1080 }
1081
1082 int _bt_get_discoverable_timeout_property(void)
1083 {
1084         DBusGProxy *proxy;
1085         GHashTable *hash = NULL;
1086         GValue *value;
1087         unsigned int disc_to;
1088
1089         proxy = _bt_get_adapter_proxy();
1090         retv_if(proxy == NULL, 0);
1091
1092         dbus_g_proxy_call(proxy, "GetProperties", NULL,
1093                           G_TYPE_INVALID,
1094                           dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
1095                           G_TYPE_VALUE), &hash, G_TYPE_INVALID);
1096
1097         retv_if(hash == NULL, 0);
1098
1099         value = g_hash_table_lookup(hash, "DiscoverableTimeout");
1100         disc_to = g_value_get_uint(value);
1101         g_hash_table_destroy(hash);
1102         return disc_to;
1103 }
1104
1105 int _bt_get_bonded_devices(GArray **dev_list)
1106 {
1107         int i;
1108         GPtrArray *gp_array = NULL;
1109         GError *error = NULL;
1110         DBusGProxy *proxy;
1111
1112         BT_CHECK_PARAMETER(dev_list, return);
1113
1114         proxy = _bt_get_adapter_proxy();
1115         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1116
1117         dbus_g_proxy_call(proxy, "ListDevices", &error,
1118                         G_TYPE_INVALID, dbus_g_type_get_collection("GPtrArray",
1119                         DBUS_TYPE_G_OBJECT_PATH), &gp_array, G_TYPE_INVALID);
1120
1121         if (error != NULL) {
1122                 BT_ERR("ListDevices error: [%s]\n", error->message);
1123                 g_error_free(error);
1124                 return BLUETOOTH_ERROR_INTERNAL;
1125         }
1126
1127         retv_if(gp_array == NULL, BLUETOOTH_ERROR_NONE);
1128         retv_if(gp_array->len == 0, BLUETOOTH_ERROR_NONE);
1129
1130         for (i = 0; i < gp_array->len; i++) {
1131                 bluetooth_device_info_t dev_info;
1132                 gchar *gp_path = g_ptr_array_index(gp_array, i);
1133
1134                 if (gp_path == NULL)
1135                         continue;
1136
1137                 memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t));
1138
1139                 if (__bt_get_bonded_device_info(gp_path,
1140                                 &dev_info) == BLUETOOTH_ERROR_NONE) {
1141
1142                         g_array_append_vals(*dev_list, &dev_info,
1143                                                 sizeof(bluetooth_device_info_t));
1144                 } else {
1145                         BT_ERR("Can't get the paired device path \n");
1146                         break;
1147                 }
1148         }
1149
1150         g_ptr_array_free(gp_array, TRUE);
1151         return BLUETOOTH_ERROR_NONE;
1152 }
1153
1154 int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address,
1155                                 bluetooth_device_info_t *dev_info)
1156 {
1157         char *object_path = NULL;
1158         DBusGProxy *adapter_proxy;
1159         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1160
1161         BT_CHECK_PARAMETER(device_address, return);
1162         BT_CHECK_PARAMETER(dev_info, return);
1163
1164         adapter_proxy = _bt_get_adapter_proxy();
1165         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1166
1167         _bt_convert_addr_type_to_string(address, device_address->addr);
1168
1169         dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
1170                           G_TYPE_STRING, address, G_TYPE_INVALID,
1171                           DBUS_TYPE_G_OBJECT_PATH, &object_path,
1172                           G_TYPE_INVALID);
1173
1174         retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND);
1175
1176         if (__bt_get_bonded_device_info(object_path,
1177                                 dev_info) != BLUETOOTH_ERROR_NONE) {
1178                 BT_ERR("Can't get the paired device path \n");
1179                 g_free(object_path);
1180                 return BLUETOOTH_ERROR_INTERNAL;
1181         }
1182         g_free(object_path);
1183         return BLUETOOTH_ERROR_NONE;
1184 }
1185
1186 int _bt_get_timeout_value(int *timeout)
1187 {
1188         time_t current_time;
1189         int time_diff;
1190
1191         /* Take current time */
1192         time(&current_time);
1193         time_diff = difftime(current_time, visible_timer.start_time);
1194
1195         BT_DBG("Time diff = %d\n", time_diff);
1196
1197         *timeout = visible_timer.timeout - time_diff;
1198
1199         return BLUETOOTH_ERROR_NONE;
1200 }
1201