Merge branch 'master' into tizen_2.1
[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 #include <syspopup_caller.h>
29 #include <aul.h>
30
31 #include "alarm.h"
32
33 #include "bluetooth-api.h"
34 #include "bt-internal-types.h"
35
36 #include "bt-service-common.h"
37 #include "bt-service-event.h"
38 #include "bt-service-adapter.h"
39 #include "bt-service-util.h"
40 #include "bt-service-network.h"
41 #include "bt-service-obex-server.h"
42 #include "bt-service-agent.h"
43 #include "bt-service-main.h"
44 #include "bt-service-avrcp.h"
45
46 typedef struct {
47         guint event_id;
48         int timeout;
49         time_t start_time;
50         int alarm_id;
51 } bt_adapter_timer_t;
52
53 bt_adapter_timer_t visible_timer;
54 static gboolean is_discovering;
55 static gboolean cancel_by_user;
56 static bt_status_t adapter_status = BT_DEACTIVATED;
57 static void *adapter_agent = NULL;
58 static DBusGProxy *core_proxy = NULL;
59
60 #define BT_CORE_NAME "org.projectx.bt_core"
61 #define BT_CORE_PATH "/org/projectx/bt_core"
62 #define BT_CORE_INTERFACE "org.projectx.btcore"
63
64 static gboolean __bt_timeout_handler(gpointer user_data)
65 {
66         int result = BLUETOOTH_ERROR_NONE;
67         time_t current_time;
68         int time_diff;
69
70         /* Take current time */
71         time(&current_time);
72         time_diff = difftime(current_time, visible_timer.start_time);
73
74         /* Send event to application */
75         _bt_send_event(BT_ADAPTER_EVENT,
76                         BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED,
77                         DBUS_TYPE_INT32, &result,
78                         DBUS_TYPE_INT16, &time_diff,
79                         DBUS_TYPE_INVALID);
80
81         if (visible_timer.timeout <= time_diff) {
82                 g_source_remove(visible_timer.event_id);
83                 visible_timer.event_id = 0;
84                 visible_timer.timeout = 0;
85
86                 if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
87                         BT_DBG("Set vconf failed\n");
88                 return FALSE;
89         }
90
91         return TRUE;
92 }
93
94 static int __bt_visibility_alarm_cb(alarm_id_t alarm_id, void* user_param)
95 {
96         BT_DBG("__bt_visibility_alarm_cb \n");
97
98         /* Switch Off visibility in Bluez */
99         _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0);
100         visible_timer.alarm_id = 0;
101         alarmmgr_fini();
102         return 0;
103 }
104
105 static void __bt_visibility_alarm_create()
106 {
107         alarm_id_t alarm_id;
108         int result;
109
110         result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, visible_timer.timeout,
111                                                 0, NULL, &alarm_id);
112         if(result < 0) {
113                 BT_DBG("Failed to create alarm error = %d\n", result);
114                 alarmmgr_fini();
115         } else {
116                 BT_DBG("Alarm created = %d\n", alarm_id);
117                 visible_timer.alarm_id = alarm_id;
118         }
119 }
120
121 int __bt_set_visible_time(int timeout)
122 {
123         int result;
124
125         if (visible_timer.event_id > 0) {
126                 g_source_remove(visible_timer.event_id);
127                 visible_timer.event_id = 0;
128         }
129
130         if (visible_timer.alarm_id > 0) {
131                 alarmmgr_remove_alarm(visible_timer.alarm_id);
132                 visible_timer.alarm_id = 0;
133         }
134
135         visible_timer.timeout = timeout;
136
137         if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0)
138                 BT_ERR("Set vconf failed\n");
139
140         if (timeout <= 0)
141                 return BLUETOOTH_ERROR_NONE;
142
143         /* Take start time */
144         time(&(visible_timer.start_time));
145         visible_timer.event_id = g_timeout_add_seconds(1,
146                                 __bt_timeout_handler, NULL);
147
148         /* Set Alarm timer to switch off BT */
149         result = alarmmgr_init("bt-service");
150         if (result != 0)
151                 return BLUETOOTH_ERROR_INTERNAL;
152
153         result = alarmmgr_set_cb(__bt_visibility_alarm_cb, NULL);
154         if (result != 0)
155                 return BLUETOOTH_ERROR_INTERNAL;
156
157         __bt_visibility_alarm_create();
158
159         return BLUETOOTH_ERROR_NONE;
160 }
161
162 static void __bt_get_service_list(GValue *value, bluetooth_device_info_t *dev)
163 {
164         int i;
165         char **uuids;
166         char **parts;
167
168         ret_if(value == NULL);
169         ret_if(dev == NULL);
170
171         uuids = g_value_get_boxed(value);
172         ret_if(uuids == NULL);
173
174         dev->service_index = 0;
175
176         for (i = 0; uuids[i] != NULL; i++) {
177                 g_strlcpy(dev->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX);
178
179                 parts = g_strsplit(uuids[i], "-", -1);
180
181                 if (parts == NULL || parts[0] == NULL)
182                         break;
183
184                 dev->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
185                 g_strfreev(parts);
186
187                 dev->service_index++;
188         }
189 }
190
191 static int __bt_get_bonded_device_info(gchar *device_path,
192                 bluetooth_device_info_t *dev_info)
193 {
194         GValue *value = { 0 };
195         GError *err = NULL;
196         DBusGProxy *device_proxy;
197         const gchar *address;
198         const gchar *name;
199         unsigned int cod;
200         gint rssi;
201         gboolean trust;
202         gboolean paired;
203         gboolean connected;
204         GHashTable *hash = NULL;
205         int ret;
206         DBusGConnection *conn;
207
208         BT_CHECK_PARAMETER(device_path, return);
209         BT_CHECK_PARAMETER(dev_info, return);
210
211         conn = _bt_get_system_gconn();
212         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
213
214         device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
215                                 device_path, BT_DEVICE_INTERFACE);
216
217         retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
218
219         dbus_g_proxy_call(device_proxy, "GetProperties", &err,
220                                 G_TYPE_INVALID,
221                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
222                                 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
223
224         g_object_unref(device_proxy);
225
226         if (err != NULL) {
227                 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
228                 g_error_free(err);
229                 return BLUETOOTH_ERROR_INTERNAL;
230         }
231
232         if (hash != NULL) {
233                 value = g_hash_table_lookup(hash, "Paired");
234                 paired = g_value_get_boolean(value);
235
236                 value = g_hash_table_lookup(hash, "Address");
237                 address = value ? g_value_get_string(value) : NULL;
238
239                 value = g_hash_table_lookup(hash, "Alias");
240                 name = value ? g_value_get_string(value) : NULL;
241
242                 if (name != NULL)
243                         BT_DBG("Alias Name [%s]", name);
244                 else {
245                         value = g_hash_table_lookup(hash, "Name");
246                         name = value ? g_value_get_string(value) : NULL;
247                 }
248
249                 value = g_hash_table_lookup(hash, "Class");
250                 cod = value ? g_value_get_uint(value) : 0;
251
252                 value = g_hash_table_lookup(hash, "Connected");
253                 connected = value ? g_value_get_boolean(value) : FALSE;
254
255                 value = g_hash_table_lookup(hash, "Trusted");
256                 trust = value ? g_value_get_boolean(value) : FALSE;
257
258                 if ((paired == FALSE) && (trust == FALSE)) {
259                         return BLUETOOTH_ERROR_NOT_PAIRED;
260                 }
261
262                 value = g_hash_table_lookup(hash, "RSSI");
263                 rssi = value ? g_value_get_int(value) : 0;
264
265                 value = g_hash_table_lookup(hash, "UUIDs");
266                 __bt_get_service_list(value, dev_info);
267
268                 _bt_convert_addr_string_to_type(dev_info->device_address.addr,
269                                                 address);
270
271                 _bt_divide_device_class(&dev_info->device_class, cod);
272
273                 g_strlcpy(dev_info->device_name.name, name,
274                                 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
275
276                 dev_info->rssi = rssi;
277                 dev_info->trust = trust;
278                 dev_info->paired = paired;
279                 dev_info->connected = connected;
280                 g_hash_table_destroy(hash);
281                 ret = BLUETOOTH_ERROR_NONE;
282         } else {
283                 BT_ERR("Hash is NULL\n");
284                 ret = BLUETOOTH_ERROR_INTERNAL;
285         }
286
287         return ret;
288 }
289
290 void _bt_set_discovery_status(gboolean mode)
291 {
292         is_discovering = mode;
293 }
294
295 void _bt_set_cancel_by_user(gboolean value)
296 {
297         cancel_by_user = value;
298 }
299
300 gboolean _bt_get_cancel_by_user(void)
301 {
302         return cancel_by_user;
303 }
304
305 static void __bt_flight_mode_cb(keynode_t *node, void *data)
306 {
307         gboolean flight_mode = FALSE;
308         int bt_status;
309
310         BT_DBG("key=%s\n", vconf_keynode_get_name(node));
311
312         bt_status = _bt_adapter_get_status();
313
314         if (vconf_keynode_get_type(node) == VCONF_TYPE_BOOL) {
315                 flight_mode = vconf_keynode_get_bool(node);
316
317                 BT_DBG("value=%d\n", flight_mode);
318
319                 if (flight_mode == TRUE) {
320                         BT_DBG("Deactivate Bluetooth Service\n");
321                         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
322                                 BT_DBG("Set vconf failed+\n");
323
324                         if (bt_status == BT_ACTIVATED)
325                                 _bt_disable_adapter();
326                 } else {
327
328                         int value = 0;
329
330                         if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &value))
331                                 BT_ERR("Fail get flight mode value");
332
333                         if (value == 0)
334                                 return;
335
336                         BT_DBG("Activate Bluetooth Service\n");
337                         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0))
338                                 BT_DBG("Set vconf failed\n");
339
340                         if (bt_status == BT_DEACTIVATED)
341                                 _bt_enable_adapter();
342                 }
343         }
344 }
345
346 static void __launch_bt_service(int status, int run_type)
347 {
348         bundle *kb;
349         char status_val[5] = { 0, };
350         char run_type_val[5] = { 0, };
351
352         snprintf(status_val, sizeof(status_val), "%d", status);
353         snprintf(run_type_val, sizeof(run_type_val), "%d", run_type);
354
355         BT_DBG("status: %s, run_type: %s", status_val, run_type_val);
356
357         kb = bundle_create();
358
359         bundle_add(kb, "launch-type", "setstate");
360         bundle_add(kb, "status", status_val);
361         bundle_add(kb, "run-type", run_type_val);
362
363         aul_launch_app("com.samsung.bluetooth", kb);
364
365         bundle_free(kb);
366 }
367
368 static void __bt_adapter_set_status(bt_status_t status)
369 {
370         adapter_status = status;
371 }
372
373 bt_status_t _bt_adapter_get_status(void)
374 {
375         return adapter_status;
376 }
377
378 static void __bt_phone_name_changed_cb(keynode_t *node, void *data)
379 {
380         char *phone_name = NULL;
381         char *ptr = NULL;
382
383         if (node == NULL)
384                 return;
385
386         if (vconf_keynode_get_type(node) == VCONF_TYPE_STRING) {
387                 phone_name = vconf_keynode_get_str(node);
388                 if (phone_name && strlen(phone_name) != 0) {
389                         if (!g_utf8_validate(phone_name, -1,
390                                                         (const char **)&ptr))
391                                 *ptr = '\0';
392
393                         _bt_set_local_name(phone_name);
394                 }
395         }
396 }
397
398 static void __bt_set_visible_mode(void)
399 {
400         int timeout;
401
402         if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0)
403                 BT_ERR("Fail to get the timeout value");
404
405         /* -1: Always on */
406         if (timeout == -1) {
407                 if (_bt_set_discoverable_mode(
408                         BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE,
409                         timeout) != BLUETOOTH_ERROR_NONE) {
410                         if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
411                                 BT_ERR("Set vconf failed");
412                 }
413         }
414 }
415
416 static void __bt_set_local_name(void)
417 {
418         char *phone_name = NULL;
419         char *ptr = NULL;
420
421         phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
422
423         if (!phone_name)
424                 return;
425
426         if (strlen(phone_name) != 0) {
427                 if (!g_utf8_validate(phone_name, -1, (const char **)&ptr))
428                         *ptr = '\0';
429                 _bt_set_local_name(phone_name);
430         }
431         free(phone_name);
432 }
433
434 static int __bt_set_enabled(void)
435 {
436         int enabled = FALSE;
437         int result = BLUETOOTH_ERROR_NONE;
438
439         _bt_check_adapter(&enabled);
440
441         if (enabled == FALSE) {
442                 BT_ERR("Bluetoothd is not running");
443                 return BLUETOOTH_ERROR_INTERNAL;
444         }
445
446         __bt_set_visible_mode();
447
448         __bt_set_local_name();
449
450         /* Update Bluetooth Status to notify other modules */
451         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0)
452                 BT_ERR("Set vconf failed\n");
453
454         if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
455                 BT_ERR("Set vconf failed\n");
456
457         /* Send enabled event to API */
458         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED,
459                                 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
460
461         return BLUETOOTH_ERROR_NONE;
462 }
463
464 static void __bt_set_disabled(int result)
465 {
466         /* Update Bluetooth Status to notify other modules */
467         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
468                 BT_ERR("Set vconf failed\n");
469
470         if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
471                 BT_ERR("Set vconf failed\n");
472
473         /* Send disabled event */
474         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
475                                 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
476 }
477
478 void *_bt_get_adapter_agent(void)
479 {
480         return adapter_agent;
481 }
482
483 void _bt_handle_flight_mode_noti(void)
484 {
485         BT_DBG("+");
486         vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
487                         __bt_flight_mode_cb, NULL);
488         BT_DBG("-");
489 }
490
491 void _bt_handle_adapter_added(void)
492 {
493          adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE);
494          if (!adapter_agent) {
495                 BT_ERR("Fail to register agent");
496                 return;
497          }
498
499         if (!aul_app_is_running("com.samsung.bluetooth"))
500                 __launch_bt_service(0, 0);
501
502         if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE)
503                 BT_ERR("Fail to register media player");
504
505         if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE)
506                 BT_ERR("Fail to init obex server");
507
508         if (_bt_network_activate() != BLUETOOTH_ERROR_NONE)
509                 BT_ERR("Fail to activate network");
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         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                 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