Add the interface to start / stop visibility timer
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-adapter.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdio.h>
19 #include <gio/gio.h>
20 #include <glib.h>
21 #include <dlog.h>
22 #include <string.h>
23 #include <vconf.h>
24 #include <syspopup_caller.h>
25 #include <bundle.h>
26 #include <eventsystem.h>
27 #include <bundle_internal.h>
28
29 #include "alarm.h"
30 #include "bluetooth-api.h"
31 #include "bt-internal-types.h"
32 #include "bt-service-common.h"
33 #include "bt-service-event.h"
34 #include "bt-service-adapter.h"
35 #include "bt-service-util.h"
36 #include "bt-service-network.h"
37 #include "bt-service-obex-server.h"
38 #include "bt-service-opp-client.h"
39 #include "bt-service-map-client.h"
40 #include "bt-service-agent.h"
41 #include "bt-service-main.h"
42 #include "bt-service-avrcp.h"
43 #include "bt-service-device.h"
44 #ifdef TIZEN_FEATURE_BT_DPM
45 #include "bt-service-dpm.h"
46 #endif
47
48 typedef struct {
49         guint event_id;
50         int timeout;
51         time_t start_time;
52         int alarm_id;
53 } bt_adapter_timer_t;
54
55 bt_adapter_timer_t visible_timer = {0, };
56
57 typedef struct {
58         alarm_id_t alarm_id;
59         bt_set_alarm_cb callback;
60         void *user_data;
61 } bt_service_alarm_t;
62
63 typedef struct {
64         gboolean is_alarm_initialized;
65         GList *g_alarm_list;
66 } bt_service_alarm_mgr_t;
67
68 #define BT_RECOVERY_MAX_COUNT 3
69
70 static bt_service_alarm_mgr_t alarm_mgr = {0, };
71
72 static gboolean is_discovering;
73 static gboolean discovery_req;
74 static gboolean cancel_by_user;
75 static bt_status_t adapter_status = BT_DEACTIVATED;
76 static bt_le_status_t adapter_le_status = BT_LE_DEACTIVATED;
77 static gboolean is_le_intended = FALSE;
78 static void *adapter_agent = NULL;
79 static GDBusProxy *core_proxy = NULL;
80 static guint timer_id = 0;
81 static guint le_timer_id = 0;
82 static int recovery_cnt = BT_RECOVERY_MAX_COUNT;
83 static guint recovery_timer = 0;
84
85 static uint status_reg_id;
86
87 #define BT_CORE_NAME "org.projectx.bt_core"
88 #define BT_CORE_PATH "/org/projectx/bt_core"
89 #define BT_CORE_INTERFACE "org.projectx.btcore"
90
91 #define BT_DISABLE_TIME 500 /* 500 ms */
92
93 #define BT_RECOVERY_TIME_W 2000 /*2 sec*/
94 #define BT_RECOVERY_TIME 5000 /*5 sec*/
95
96 static int alarm_cb(alarm_id_t alarm_id, void* user_param);
97 static void alarm_data_free(void *data);
98
99 GDBusProxy *_bt_init_core_proxy(void)
100 {
101         GDBusProxy *proxy;
102         GDBusConnection *conn;
103
104         conn = _bt_gdbus_get_system_gconn();
105         if (!conn)
106                 return NULL;
107
108         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
109                                         NULL,
110                                         BT_CORE_NAME,
111                                         BT_CORE_PATH,
112                                         BT_CORE_INTERFACE,
113                                         NULL, NULL);
114
115         if (!proxy)
116                 return NULL;
117
118         core_proxy = proxy;
119
120         return proxy;
121 }
122
123 static GDBusProxy *__bt_get_core_proxy(void)
124 {
125         return (core_proxy) ? core_proxy : _bt_init_core_proxy();
126 }
127
128 static gboolean __bt_is_factory_test_mode(void)
129 {
130         int mode = 0;
131
132         if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) {
133                 BT_ERR("Get the DUT Mode fail");
134                 return TRUE;
135         }
136
137         if (mode != FALSE) {
138                 BT_INFO("DUT Test Mode !!");
139                 return TRUE;
140         }
141
142         return FALSE;
143 }
144
145 static gboolean __bt_timeout_handler(gpointer user_data)
146 {
147         int result = BLUETOOTH_ERROR_NONE;
148         time_t current_time;
149         int time_diff;
150
151         /* Take current time */
152         time(&current_time);
153         time_diff = difftime(current_time, visible_timer.start_time);
154
155         /* Send event to application */
156         _bt_send_event(BT_ADAPTER_EVENT,
157                         BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED,
158                         g_variant_new("(in)", result, time_diff));
159
160         if (visible_timer.timeout <= time_diff) {
161                 g_source_remove(visible_timer.event_id);
162                 visible_timer.event_id = 0;
163                 visible_timer.timeout = 0;
164
165                 if (!TIZEN_PROFILE_WEARABLE) {
166                         if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
167                                 BT_ERR("Set vconf failed\n");
168                 }
169                 return FALSE;
170         }
171
172         return TRUE;
173 }
174
175 static int __bt_visibility_alarm_cb(alarm_id_t alarm_id, void* user_param)
176 {
177
178         int result = BLUETOOTH_ERROR_NONE;
179         int timeout = 0;
180
181         if (alarm_id != visible_timer.alarm_id)
182                 return 0;
183
184         if (visible_timer.event_id) {
185                 _bt_send_event(BT_ADAPTER_EVENT,
186                                 BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED,
187                                 g_variant_new("(in)", result, timeout));
188                 g_source_remove(visible_timer.event_id);
189                 visible_timer.event_id = 0;
190                 visible_timer.timeout = 0;
191
192                 if (!TIZEN_PROFILE_WEARABLE) {
193                         if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
194                                 BT_ERR("Set vconf failed\n");
195                 }
196         }
197
198         /* Switch Off visibility in Bluez */
199         _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0);
200         visible_timer.alarm_id = 0;
201
202         return 0;
203 }
204
205 static void __bt_visibility_alarm_remove()
206 {
207         if (visible_timer.event_id > 0) {
208                 g_source_remove(visible_timer.event_id);
209                 visible_timer.event_id = 0;
210         }
211
212         if (visible_timer.alarm_id > 0) {
213                 _bt_service_remove_alarm(visible_timer.alarm_id);
214                 visible_timer.alarm_id = 0;
215         }
216 }
217
218 int _bt_start_visibility_timer(int timeout)
219 {
220         int result;
221         alarm_id_t alarm_id = 0;
222 #ifdef TIZEN_FEATURE_BT_DPM
223         int discoverable_state = DPM_BT_ERROR;
224 #endif
225
226         if (timeout <= 0) {
227                 BT_ERR("Invalid timeout : %d", timeout);
228                 return BLUETOOTH_ERROR_INVALID_PARAM;
229         }
230
231 #ifdef TIZEN_FEATURE_BT_DPM
232         _bt_dpm_get_bluetooth_limited_discoverable_state(&discoverable_state);
233         if (discoverable_state != DPM_RESTRICTED) {
234                 BT_ERR("Limited discoverable mode is not allowed");
235                 return BLUETOOTH_ERROR_ACCESS_DENIED;
236         }
237 #endif
238
239         __bt_visibility_alarm_remove();
240
241         result = _bt_service_set_alarm(timeout, __bt_visibility_alarm_cb, NULL,
242                                        &alarm_id);
243         if (result != BLUETOOTH_ERROR_NONE) {
244                 BT_ERR("_bt_service_set_alarm is failed : 0x%X", result);
245                 return BLUETOOTH_ERROR_INTERNAL;
246         }
247
248         if (!TIZEN_PROFILE_WEARABLE) {
249                 if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0)
250                         BT_ERR("Set vconf failed");
251         }
252
253         visible_timer.timeout = timeout;
254         visible_timer.alarm_id = alarm_id;
255         /* Take start time */
256         time(&(visible_timer.start_time));
257         visible_timer.event_id = g_timeout_add_seconds(1, __bt_timeout_handler, NULL);
258
259         return BLUETOOTH_ERROR_NONE;
260 }
261
262 int _bt_stop_visibility_timer(void)
263 {
264         __bt_visibility_alarm_remove();
265
266         visible_timer.timeout = 0;
267
268         if (!TIZEN_PROFILE_WEARABLE) {
269                 if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0)
270                         BT_ERR("Set vconf failed");
271         }
272
273         return BLUETOOTH_ERROR_NONE;
274 }
275
276 static void __bt_get_service_list(GVariant *value, bluetooth_device_info_t *dev)
277 {
278         int i = 0;
279         char **parts;
280         GVariantIter *iter;
281         gchar *uuid = NULL;
282
283         ret_if(value == NULL);
284         ret_if(dev == NULL);
285
286         dev->service_index = 0;
287
288         g_variant_get(value, "as", &iter);
289         while (g_variant_iter_loop(iter, "s", &uuid)) {
290                 g_strlcpy(dev->uuids[i], uuid, BLUETOOTH_UUID_STRING_MAX);
291                 parts = g_strsplit(uuid, "-", -1);
292
293                 if (parts == NULL || parts[0] == NULL) {
294                         g_free(uuid);
295                         break;
296                 }
297
298                 dev->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
299                 g_strfreev(parts);
300
301                 dev->service_index++;
302                 i++;
303         }
304         g_variant_iter_free(iter);
305 }
306
307 static int __bt_get_bonded_device_info(gchar *device_path,
308                 bluetooth_device_info_t *dev_info)
309 {
310         GError *error = NULL;
311         GDBusProxy *device_proxy;
312         gchar *address = NULL;
313         gchar *name = NULL;
314         gchar *alias = NULL;
315         unsigned int cod = 0;
316         gint rssi = 0;
317         gboolean trust = FALSE;
318         gboolean paired = FALSE;
319         guchar connected = 0;
320         GByteArray *manufacturer_data = NULL;
321         int ret;
322         GDBusConnection *conn;
323         GVariant *result;
324         GVariantIter *property_iter;
325         const gchar *key;
326         GVariant *value;
327         guint8 char_value;
328         GVariantIter *char_value_iter;
329
330         BT_CHECK_PARAMETER(device_path, return);
331         BT_CHECK_PARAMETER(dev_info, return);
332
333         conn = _bt_gdbus_get_system_gconn();
334         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
335
336         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
337                                         NULL,
338                                         BT_BLUEZ_NAME,
339                                         device_path,
340                                         BT_PROPERTIES_INTERFACE,
341                                         NULL, NULL);
342
343         retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
344
345         result = g_dbus_proxy_call_sync(device_proxy,
346                                 "GetAll",
347                                 g_variant_new("(s)", BT_DEVICE_INTERFACE),
348                                 G_DBUS_CALL_FLAGS_NONE,
349                                 -1,
350                                 NULL,
351                                 &error);
352
353         if (!result) {
354                 BT_ERR("Error occured in Proxy call");
355                 if (error != NULL) {
356                         BT_ERR("Error occured in Proxy call (Error: %s)", error->message);
357                         g_clear_error(&error);
358                 }
359                 g_object_unref(device_proxy);
360                 return BLUETOOTH_ERROR_INTERNAL;
361         }
362
363         g_object_unref(device_proxy);
364
365         g_variant_get(result, "(a{sv})", &property_iter);
366
367         while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
368                 if (!g_strcmp0(key, "Paired")) {
369                         paired = g_variant_get_boolean(value);
370                 } else if (!g_strcmp0(key, "Address")) {
371                         g_variant_get(value, "s", &address);
372                 } else if (!g_strcmp0(key, "Alias")) {
373                         g_variant_get(value, "s", &alias);
374                 } else if (!g_strcmp0(key, "Name")) {
375                         g_variant_get(value, "s", &name);
376                 } else if (!g_strcmp0(key, "Class")) {
377                         cod = g_variant_get_uint32(value);
378                 } else if (!g_strcmp0(key, "Connected")) {
379                         connected = g_variant_get_byte(value);
380                 } else if (!g_strcmp0(key, "Trusted")) {
381                         trust = g_variant_get_boolean(value);
382                 } else if (!g_strcmp0(key, "RSSI")) {
383                         rssi = g_variant_get_int16(value);
384                 } else if (!g_strcmp0(key, "UUIDs")) {
385                         __bt_get_service_list(value, dev_info);
386                 } else if (!g_strcmp0(key, "ManufacturerDataLen")) {
387                         dev_info->manufacturer_data.data_len = g_variant_get_uint16(value);
388                 } else if (!g_strcmp0(key, "ManufacturerData")) {
389                         manufacturer_data = g_byte_array_new();
390                         g_variant_get(value, "ay", &char_value_iter);
391                         while (g_variant_iter_loop(char_value_iter, "y",  &char_value))
392                                 g_byte_array_append(manufacturer_data, &char_value, 1);
393
394                         g_variant_iter_free(char_value_iter);
395
396                         if (manufacturer_data) {
397                                 if (manufacturer_data->len > 0) {
398                                         memcpy(dev_info->manufacturer_data.data, manufacturer_data->data,
399                                                 manufacturer_data->len);
400                                 }
401                         }
402                         g_byte_array_free(manufacturer_data, TRUE);
403                 }
404         }
405         g_variant_iter_free(property_iter);
406
407         BT_DBG("trust: %d, paired: %d", trust, paired);
408
409         g_variant_unref(result);
410
411         if ((paired == FALSE) && (trust == FALSE)) {
412                 g_free(address);
413                 g_free(alias);
414                 g_free(name);
415                 return BLUETOOTH_ERROR_NOT_PAIRED;
416         }
417
418         _bt_convert_addr_string_to_type(dev_info->device_address.addr,
419                                         address);
420
421         _bt_divide_device_class(&dev_info->device_class, cod);
422
423         g_strlcpy(dev_info->device_name.name, alias ? alias : name,
424                         BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
425
426         dev_info->rssi = rssi;
427         dev_info->trust = trust;
428         dev_info->paired = paired;
429         dev_info->connected = connected;
430         ret = BLUETOOTH_ERROR_NONE;
431         g_free(address);
432         g_free(alias);
433         g_free(name);
434
435         return ret;
436 }
437
438 void _bt_set_discovery_status(gboolean mode)
439 {
440         is_discovering = mode;
441         discovery_req = FALSE;
442 }
443
444 void _bt_set_cancel_by_user(gboolean value)
445 {
446         cancel_by_user = value;
447 }
448
449 gboolean _bt_get_cancel_by_user(void)
450 {
451         return cancel_by_user;
452 }
453
454 void _bt_adapter_set_status(bt_status_t status)
455 {
456         BT_INFO("adapter_status changed [%d] -> [%d]", adapter_status, status);
457         adapter_status = status;
458 }
459
460 bt_status_t _bt_adapter_get_status(void)
461 {
462         return adapter_status;
463 }
464
465 void _bt_adapter_set_le_status(bt_le_status_t status)
466 {
467         BT_INFO("adapter_le_status changed [%d] -> [%d]", adapter_le_status, status);
468         adapter_le_status = status;
469 }
470
471 bt_le_status_t _bt_adapter_get_le_status(void)
472 {
473         return adapter_le_status;
474 }
475
476
477 void _bt_set_le_intended_status(gboolean value)
478 {
479         is_le_intended = value;
480 }
481
482 static void __bt_phone_name_changed_cb(keynode_t *node, void *data)
483 {
484         char *phone_name = NULL;
485         char *ptr = NULL;
486
487         ret_if(node == NULL);
488
489         if (vconf_keynode_get_type(node) == VCONF_TYPE_STRING) {
490                 phone_name = vconf_keynode_get_str(node);
491
492                 if (phone_name && strlen(phone_name) != 0) {
493                         if (!g_utf8_validate(phone_name, -1,
494                                                         (const char **)&ptr))
495                                         *ptr = '\0';
496
497                         BT_INFO("device_name is changed to %s", phone_name);
498                         _bt_set_local_name(phone_name);
499                 } else {
500                         BT_ERR("phone_name is NOT valid");
501                 }
502         } else {
503                 BT_ERR("vconf type is NOT string");
504         }
505 }
506
507 static void __bt_set_local_name(void)
508 {
509         bluetooth_device_name_t local_name;
510         char *phone_name = NULL;
511         char *ptr = NULL;
512         char *temp = NULL;
513
514         if (_bt_get_local_name(&local_name) != BLUETOOTH_ERROR_NONE ||
515                 (temp = strstr(local_name.name, "BlueZ")) != NULL) {
516                 phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
517
518                 if (!phone_name)
519                         return;
520
521                 if (strlen(phone_name) != 0) {
522                         if (!g_utf8_validate(phone_name, -1, (const char **)&ptr))
523                                 *ptr = '\0';
524
525                         _bt_set_local_name(phone_name);
526                 }
527                 free(phone_name);
528         }
529 }
530
531 static int __bt_set_enabled(void)
532 {
533         int adapter_status = BT_ADAPTER_DISABLED;
534         int result = BLUETOOTH_ERROR_NONE;
535
536         if (timer_id > 0) {
537                 BT_DBG("g_source is removed");
538                 g_source_remove(timer_id);
539                 timer_id = 0;
540         }
541
542         _bt_check_adapter(&adapter_status);
543
544         if (adapter_status == BT_ADAPTER_DISABLED) {
545                 BT_ERR("Bluetoothd is not running");
546                 return BLUETOOTH_ERROR_INTERNAL;
547         }
548
549         if (TIZEN_PROFILE_MOBILE || TIZEN_PROFILE_IVI) {
550                 /* BT setting UI will control Mobile's visible mode. So in the FRWK...set the visible mode as off: */
551                 if (_bt_set_discoverable_mode(
552                         BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0) != BLUETOOTH_ERROR_NONE)
553                                 BT_ERR("Set connectable mode failed");
554         } else if (TIZEN_PROFILE_TV) {
555                 if (_bt_set_discoverable_mode(
556                         BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE, 0) != BLUETOOTH_ERROR_NONE)
557                                 BT_ERR("Fail to set discoverable mode");
558         }
559
560         /* Update Bluetooth Status to notify other modules */
561         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0)
562                 BT_ERR("Set vconf failed\n");
563
564         if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
565                 BT_ERR("Set vconf failed\n");
566
567         if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
568                                                 EVT_VAL_BT_ON) != ES_R_OK)
569                 BT_ERR("Fail to set value");
570
571         /* Send enabled event to API */
572         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED,
573                                 g_variant_new("(i)", result));
574
575 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
576         _bt_audio_start_auto_connect(FALSE);
577 #endif
578
579         __bt_set_local_name();
580         _bt_set_discovery_status(FALSE);
581
582         return BLUETOOTH_ERROR_NONE;
583 }
584
585 void _bt_set_disabled(int result)
586 {
587         int power_off_status = 0;
588         int ret;
589         int ret_pm_ignore;
590         int pm_ignore_mode = 0;
591
592         ret = vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &power_off_status);
593         BT_DBG("ret : %d, power_off_status : %d", ret, power_off_status);
594
595         ret_pm_ignore = vconf_get_int(VCONFKEY_PM_KEY_IGNORE, &pm_ignore_mode);
596
597         /* Update the vconf BT status in normal Deactivation case only */
598         if (ret == 0 && power_off_status == VCONFKEY_SYSMAN_POWER_OFF_NONE &&
599                 ret_pm_ignore == 0 && pm_ignore_mode != VCONFKEY_PM_KEY_LOCK) {
600
601                 BT_DBG("Update vconf for BT normal Deactivation");
602
603                 if (result == BLUETOOTH_ERROR_TIMEOUT)
604                         if (vconf_set_int(BT_OFF_DUE_TO_TIMEOUT, 1) != 0)
605                                 BT_ERR("Set vconf failed");
606
607                 /* Update Bluetooth Status to notify other modules */
608                 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
609                         BT_ERR("Set vconf failed");
610
611                 if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
612                                                         EVT_VAL_BT_OFF) != ES_R_OK)
613                         BT_ERR("Fail to set value");
614         }
615
616         if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0)
617                 BT_ERR("Set vconf failed\n");
618
619         _bt_cancel_queued_transfers();
620         _bt_adapter_set_status(BT_DEACTIVATED);
621         _bt_set_discovery_status(FALSE);
622
623         BT_INFO("Adapter disabled");
624 }
625
626 static int __bt_set_le_enabled(void)
627 {
628         BT_DBG("+");
629         int result = BLUETOOTH_ERROR_NONE;
630         bt_status_t status;
631
632         /* Update Bluetooth Status to notify other modules */
633         if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_ON) != 0)
634                 BT_ERR("Set vconf failed\n");
635
636         if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
637                                                 EVT_VAL_BT_LE_ON) != ES_R_OK)
638                 BT_ERR("Fail to set value");
639
640         /* Send enabled event to API */
641         /*
642         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED,
643                                 DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
644         */
645         status = _bt_adapter_get_status();
646         if (status == BT_DEACTIVATED) {
647                 BT_INFO("BREDR is off, turn off PSCAN");
648                 _bt_set_connectable(FALSE);
649         }
650         if (le_timer_id > 0) {
651                 g_source_remove(le_timer_id);
652                 le_timer_id = 0;
653         }
654
655         /* Send enabled event to API */
656         _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_LE_ENABLED,
657                                 g_variant_new("(i)", result));
658
659         __bt_set_local_name();
660
661         BT_DBG("-");
662         return BLUETOOTH_ERROR_NONE;
663 }
664
665 void _bt_set_le_disabled(int result)
666 {
667         int power_off_status;
668         int ret;
669
670         ret = vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &power_off_status);
671         BT_DBG("ret : %d", ret);
672         BT_DBG("power_off_status : %d", power_off_status);
673
674         /* Update Bluetooth Status to notify other modules */
675         BT_DBG("Update vconf for BT LE normal Deactivation");
676         if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
677                 BT_ERR("Set vconf failed\n");
678         _bt_adapter_set_le_status(BT_LE_DEACTIVATED);
679
680         if (_bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
681                                                 EVT_VAL_BT_LE_OFF) != ES_R_OK)
682                 BT_ERR("Fail to set value");
683
684         /* Send disabled event */
685         _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_LE_DISABLED,
686                                                 g_variant_new("(i)", result));
687 }
688
689 void *_bt_get_adapter_agent(void)
690 {
691         return adapter_agent;
692 }
693
694 int _bt_enable_core(void)
695 {
696         GDBusProxy *proxy;
697         GVariant *result;
698         GError *error = NULL;
699
700         proxy = __bt_get_core_proxy();
701         retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL);
702
703         /* Clean up the process */
704         result = g_dbus_proxy_call_sync(proxy,
705                                 "EnableCore",
706                                 NULL,
707                                 G_DBUS_CALL_FLAGS_NONE,
708                                 -1,
709                                 NULL,
710                                 &error);
711
712         if (!result) {
713                 if (error != NULL) {
714                         BT_ERR("Bt core call failed(Error: %s)", error->message);
715                         g_clear_error(&error);
716                 } else
717                         BT_ERR("Bt core call failed");
718                 return BLUETOOTH_ERROR_INTERNAL;
719         }
720
721         g_variant_unref(result);
722         return BLUETOOTH_ERROR_NONE;
723 }
724
725 static void __bt_service_flight_ps_mode_cb(keynode_t *node, void *data)
726 {
727         gboolean flight_mode = FALSE;
728         int power_saving_mode = 0;
729         int type;
730
731         DBG_SECURE("key=%s", vconf_keynode_get_name(node));
732         type = vconf_keynode_get_type(node);
733         if (type == VCONF_TYPE_BOOL) {
734                 flight_mode = vconf_keynode_get_bool(node);
735                 if (flight_mode != TRUE) {
736                         BT_ERR("Ignore the event");
737                         return;
738                 }
739         } else if (type == VCONF_TYPE_INT) {
740                 power_saving_mode = vconf_keynode_get_int(node);
741                 if (power_saving_mode != 2) {
742                         BT_ERR("Ignore the event");
743                         return;
744                 }
745         } else {
746                 BT_ERR("Invaild vconf key type : %d", type);
747                 return;
748         }
749
750         _bt_enable_core();
751 }
752
753 void _bt_service_register_vconf_handler(void)
754 {
755         BT_DBG("+");
756
757         if (TIZEN_FEATURE_FLIGHTMODE_ENABLED) {
758                 if (vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
759                                 (vconf_callback_fn)__bt_service_flight_ps_mode_cb, NULL) < 0)
760                         BT_ERR("Unable to register key handler");
761         } else {
762                 BT_DBG("Telephony is disabled");
763         }
764
765         if (!TIZEN_PROFILE_WEARABLE) {
766                 if (vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE,
767                                 (vconf_callback_fn)__bt_service_flight_ps_mode_cb, NULL) < 0)
768                         BT_ERR("Unable to register key handler");
769         }
770 }
771
772 void _bt_service_unregister_vconf_handler(void)
773 {
774         BT_DBG("+");
775
776         if (TIZEN_FEATURE_FLIGHTMODE_ENABLED) {
777                 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
778                                 (vconf_callback_fn)__bt_service_flight_ps_mode_cb);
779         }
780
781         if (!TIZEN_PROFILE_WEARABLE) {
782                 vconf_ignore_key_changed(VCONFKEY_SETAPPL_PSMODE,
783                                 (vconf_callback_fn)__bt_service_flight_ps_mode_cb);
784         }
785 }
786
787 static void __bt_state_event_handler(const char *event_name, bundle *data, void *user_data)
788 {
789         const char *bt_status = NULL;
790         const char *bt_le_status = NULL;
791         BT_DBG("bt state set event(%s) received", event_name);
792
793         bt_status = bundle_get_val(data, EVT_KEY_BT_STATE);
794         BT_DBG("bt_state: (%s)", bt_status);
795
796         bt_le_status = bundle_get_val(data, EVT_KEY_BT_LE_STATE);
797         BT_DBG("bt_state: (%s)", bt_le_status);
798 }
799
800 static gboolean __bt_adapter_recovery_cb(gpointer data)
801 {
802         int ret = 0;
803
804         BT_DBG("+");
805
806         recovery_timer = 0;
807
808         _bt_service_initialize();
809
810         ret = _bt_enable_adapter_check_status();
811         if (ret == BLUETOOTH_ERROR_NONE) {
812                 ret = _bt_enable_adapter();
813                 if (ret < 0)
814                         BT_ERR("_bt_enable_adapter() failed");
815
816                 ret = _bt_enable_adapter_le();
817                 if (ret < 0)
818                         BT_ERR("_bt_enable_adapter_le() failed");
819         }
820
821         recovery_cnt--;
822
823         BT_DBG("-");
824
825         return FALSE;
826 }
827
828 void _bt_handle_adapter_added(void)
829 {
830         BT_DBG("+");
831         bt_status_t status;
832         bt_le_status_t le_status;
833         int ret;
834 /*
835         if (timer_id > 0) {
836                 BT_DBG("g_source is removed");
837                 g_source_remove(timer_id);
838                 timer_id = 0;
839         }
840 */
841
842         recovery_cnt = -1;
843
844         status = _bt_adapter_get_status();
845         le_status = _bt_adapter_get_le_status();
846         BT_INFO("status : %d", status);
847         BT_INFO("le_status : %d", le_status);
848         if (!TIZEN_FEATURE_BT_USB_DONGLE) {
849                 adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE);
850                 if (!adapter_agent) {
851                         BT_ERR("Fail to register agent");
852                         return;
853                 }
854         } else {
855                 if (adapter_agent == NULL) {
856                         adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE);
857                         if (!adapter_agent) {
858                                 BT_ERR("Fail to register agent");
859                                 return;
860                         }
861                 }
862         }
863
864         if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE)
865                 BT_ERR("Fail to register media player");
866
867         if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE)
868                 BT_ERR("Fail to init obex server");
869
870 #ifdef TIZEN_BT_PAN_NAP_ENABLED
871         if (_bt_network_activate() != BLUETOOTH_ERROR_NONE)
872                 BT_ERR("Fail to activate network");
873 #endif
874
875         /* add the vconf noti handler */
876         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
877                                         __bt_phone_name_changed_cb, NULL);
878         if (ret < 0)
879                 BT_ERR("Unable to register key handler");
880
881         if (le_status == BT_LE_ACTIVATING ||
882                  status == BT_ACTIVATING) {
883                 __bt_set_le_enabled();
884                 _bt_adapter_set_le_status(BT_LE_ACTIVATED);
885         }
886
887         if (status == BT_ACTIVATING) {
888                 __bt_set_enabled();
889                 _bt_adapter_set_status(BT_ACTIVATED);
890         }
891
892         /* eventsystem */
893         if (eventsystem_register_event(SYS_EVENT_BT_STATE, &status_reg_id,
894                         (eventsystem_handler)__bt_state_event_handler, NULL) != ES_R_OK) {
895                 BT_ERR("Fail to register system event");
896         }
897 }
898
899 void _bt_handle_adapter_removed(void)
900 {
901         int ret;
902
903         _bt_adapter_set_status(BT_DEACTIVATED);
904
905         __bt_visibility_alarm_remove();
906
907         if (alarm_mgr.is_alarm_initialized == TRUE) {
908                 alarmmgr_fini();
909                 alarm_mgr.is_alarm_initialized = FALSE;
910                 g_list_free_full(alarm_mgr.g_alarm_list, alarm_data_free);
911                 alarm_mgr.g_alarm_list = NULL;
912         }
913
914 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
915         _bt_audio_stop_auto_connect();
916 #endif
917
918         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR,
919                                 (vconf_callback_fn)__bt_phone_name_changed_cb);
920         if (0 != ret)
921                 ERR("vconf_ignore_key_changed failed\n");
922
923         /* unregister all the services/servers/profiles registered on bluez-adapter
924         once adapter is removed, reinitializing of the state-varaibles becomes
925         a problem */
926         if (_bt_unregister_obex_server() != BLUETOOTH_ERROR_NONE)
927                 BT_ERR("Fail to unregister obex server");
928
929         if (_bt_unregister_media_player() != BLUETOOTH_ERROR_NONE)
930                 BT_ERR("Fail to unregister media player");
931
932         /* Other unregister APIs should be placed here */
933
934         if (!TIZEN_FEATURE_BT_USB_DONGLE) {
935                 _bt_destroy_agent(adapter_agent);
936                 adapter_agent = NULL;
937
938                 if (recovery_cnt > 0) {
939                         /* Send disabled event */
940                         _bt_set_disabled(BLUETOOTH_ERROR_NONE);
941                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
942                                 g_variant_new("(i)", BLUETOOTH_ERROR_NONE));
943
944                         if (recovery_timer > 0)
945                                 g_source_remove(recovery_timer);
946
947                         if (TIZEN_PROFILE_WEARABLE) {
948                                 recovery_timer = g_timeout_add(BT_RECOVERY_TIME_W,
949                                                 (GSourceFunc)__bt_adapter_recovery_cb, NULL);
950                         } else {
951                                 recovery_timer = g_timeout_add(BT_RECOVERY_TIME,
952                                                 (GSourceFunc)__bt_adapter_recovery_cb, NULL);
953                         }
954
955                         if (eventsystem_unregister_event(status_reg_id) != ES_R_OK)
956                                 BT_ERR("Fail to unregister system event");
957                         return;
958                 }
959
960                 if (recovery_timer == 0)
961                         _bt_reliable_terminate_service(NULL);
962         } else {
963                 _bt_set_disabled(BLUETOOTH_ERROR_NONE);
964                 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
965                                 g_variant_new("(i)", BLUETOOTH_ERROR_NONE));
966         }
967
968         if (eventsystem_unregister_event(status_reg_id) != ES_R_OK)
969                 BT_ERR("Fail to unregister system event");
970 }
971
972 static gboolean __bt_enable_timeout_cb(gpointer user_data)
973 {
974         GDBusProxy *proxy;
975         GVariant *result;
976         GError *error = NULL;
977
978         timer_id = 0;
979
980         retv_if(_bt_adapter_get_status() == BT_ACTIVATED, FALSE);
981
982         BT_ERR("EnableAdapter is failed");
983
984         proxy = __bt_get_core_proxy();
985         if (!proxy)
986                 return FALSE;
987
988         /* Clean up the process */
989         result = g_dbus_proxy_call_sync(proxy,
990                                 "DisableAdapter",
991                                 NULL,
992                                 G_DBUS_CALL_FLAGS_NONE,
993                                 -1,
994                                 NULL,
995                                 &error);
996
997         if (!result) {
998                 if (error != NULL) {
999                         BT_ERR("Bt core call failed(Error: %s)", error->message);
1000                         g_clear_error(&error);
1001                 } else {
1002                         BT_ERR("Bt core call failed");
1003                 }
1004                 return FALSE;
1005         }
1006
1007         g_variant_unref(result);
1008         _bt_set_disabled(BLUETOOTH_ERROR_TIMEOUT);
1009
1010         if (recovery_cnt > 0) {
1011                 BT_ERR("Try recovery again(remain:%d)", recovery_cnt);
1012                 if (recovery_timer > 0)
1013                         g_source_remove(recovery_timer);
1014
1015                 if (TIZEN_PROFILE_WEARABLE) {
1016                         recovery_timer = g_timeout_add(BT_RECOVERY_TIME_W,
1017                                 (GSourceFunc)__bt_adapter_recovery_cb, NULL);
1018                 } else {
1019                         recovery_timer = g_timeout_add(BT_RECOVERY_TIME,
1020                                 (GSourceFunc)__bt_adapter_recovery_cb, NULL);
1021                 }
1022
1023                 return FALSE;
1024         }
1025
1026         if (!TIZEN_FEATURE_BT_USB_DONGLE)
1027                 _bt_terminate_service(NULL);
1028
1029         return FALSE;
1030 }
1031
1032 static gboolean __bt_enable_le_timeout_cb(gpointer user_data)
1033 {
1034         GDBusProxy *proxy;
1035         GVariant *result;
1036         GError *error = NULL;
1037
1038         le_timer_id = 0;
1039
1040         retv_if(_bt_adapter_get_le_status() == BT_LE_ACTIVATED, FALSE);
1041
1042         BT_ERR("EnableAdapterLE is failed");
1043
1044         proxy = __bt_get_core_proxy();
1045         if (!proxy)
1046                 return FALSE;
1047
1048         /* Clean up the process */
1049         result = g_dbus_proxy_call_sync(proxy,
1050                                 "DisableAdapterLe",
1051                                 NULL,
1052                                 G_DBUS_CALL_FLAGS_NONE,
1053                                 -1,
1054                                 NULL,
1055                                 &error);
1056
1057         if (!result) {
1058                 if (error != NULL) {
1059                         BT_ERR("Bt core call failed(Error: %s)", error->message);
1060                         g_clear_error(&error);
1061                 } else
1062                         BT_ERR("Bt core call failed");
1063                 return FALSE;
1064         }
1065
1066         g_variant_unref(result);
1067
1068         if (_bt_adapter_get_le_status() != BT_LE_DEACTIVATED)
1069                 _bt_set_le_disabled(BLUETOOTH_ERROR_TIMEOUT);
1070
1071         if (_bt_adapter_get_status() == BT_DEACTIVATED)
1072                 _bt_terminate_service(NULL);
1073
1074         return FALSE;
1075 }
1076
1077 void _bt_adapter_start_le_enable_timer(void)
1078 {
1079         if (le_timer_id > 0) {
1080                 g_source_remove(le_timer_id);
1081                 le_timer_id = 0;
1082         }
1083
1084         le_timer_id = g_timeout_add(BT_ENABLE_TIMEOUT,
1085                         __bt_enable_le_timeout_cb, NULL);
1086
1087         return;
1088 }
1089
1090 void _bt_adapter_start_enable_timer(void)
1091 {
1092         if (timer_id > 0) {
1093                 g_source_remove(timer_id);
1094                 timer_id = 0;
1095         }
1096
1097         timer_id = g_timeout_add(BT_ENABLE_TIMEOUT,
1098                         __bt_enable_timeout_cb, NULL);
1099
1100         return;
1101 }
1102
1103 static gboolean __bt_adapter_enabled_cb(gpointer user_data)
1104 {
1105         BT_DBG("+");
1106
1107         __bt_set_enabled();
1108         _bt_adapter_set_status(BT_ACTIVATED);
1109
1110         return FALSE;
1111 }
1112
1113 int _bt_enable_adapter_check_status(void)
1114 {
1115         bt_status_t status = _bt_adapter_get_status();
1116         bt_le_status_t le_status = _bt_adapter_get_le_status();
1117
1118         BT_DBG("");
1119
1120         if (status == BT_ACTIVATING) {
1121                 BT_ERR("Enabling in progress");
1122                 return BLUETOOTH_ERROR_IN_PROGRESS;
1123         }
1124
1125         if (status == BT_ACTIVATED) {
1126                 BT_ERR("Already enabled");
1127                 return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED;
1128         }
1129
1130         if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) {
1131                 BT_ERR("Disabling in progress");
1132                 return BLUETOOTH_ERROR_DEVICE_BUSY;
1133         }
1134
1135         return BLUETOOTH_ERROR_NONE;
1136 }
1137
1138 int _bt_enable_adapter(void)
1139 {
1140         GDBusProxy *proxy;
1141         GError *error = NULL;
1142         int ret;
1143         GVariant *result = NULL;
1144         bt_status_t status = _bt_adapter_get_status();
1145         bt_le_status_t le_status = _bt_adapter_get_le_status();
1146
1147         BT_DBG("");
1148
1149         if (status == BT_ACTIVATING) {
1150                 BT_ERR("Enabling in progress");
1151                 return BLUETOOTH_ERROR_IN_PROGRESS;
1152         }
1153
1154         if (status == BT_ACTIVATED) {
1155                 BT_ERR("Already enabled");
1156                 return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED;
1157         }
1158
1159         if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) {
1160                 BT_ERR("Disabling in progress");
1161                 return BLUETOOTH_ERROR_DEVICE_BUSY;
1162         }
1163
1164         _bt_adapter_set_status(BT_ACTIVATING);
1165
1166 if (TIZEN_PROFILE_TV) {
1167         int adapter_status = BT_ADAPTER_DISABLED;
1168
1169         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
1170                 BT_ERR("Set vconf failed");
1171
1172         _bt_check_adapter(&adapter_status);
1173         if (adapter_status == BT_ADAPTER_ENABLED) {
1174                 g_idle_add(__bt_adapter_enabled_cb, NULL);
1175                 _bt_adapter_start_enable_timer();
1176                 return BLUETOOTH_ERROR_NONE;
1177         }
1178 }
1179
1180         proxy = __bt_get_core_proxy();
1181         if (!proxy)
1182                 return BLUETOOTH_ERROR_INTERNAL;
1183
1184         if (le_status == BT_LE_ACTIVATED) {
1185                 BT_INFO("LE Already enabled. Just turn on PSCAN");
1186                 ret = _bt_set_connectable(TRUE);
1187                 if (ret == BLUETOOTH_ERROR_NONE)
1188                         _bt_adapter_set_status(BT_ACTIVATED);
1189                 else
1190                         return BLUETOOTH_ERROR_INTERNAL;
1191         }
1192
1193         result = g_dbus_proxy_call_sync(proxy, "EnableAdapter",
1194                                          NULL,
1195                                          G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
1196                                          NULL, &error);
1197          if (error) {
1198                 BT_ERR("EnableAdapterLe failed: %s", error->message);
1199                 _bt_adapter_set_status(BT_DEACTIVATED);
1200                 g_clear_error(&error);
1201                 error = NULL;
1202                 result = g_dbus_proxy_call_sync(proxy,
1203                                 "DisableAdapter",
1204                                 NULL,
1205                                 G_DBUS_CALL_FLAGS_NONE,
1206                                 -1,
1207                                 NULL,
1208                                 &error);
1209
1210                 if (error != NULL) {
1211                                 BT_ERR("Bt core call failed(Error: %s)", error->message);
1212                                 g_clear_error(&error);
1213                 }
1214                 g_variant_unref(result);
1215                 /* Terminate myself */
1216                 if (!TIZEN_FEATURE_BT_USB_DONGLE)
1217                         g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
1218                 return BLUETOOTH_ERROR_INTERNAL;
1219         }
1220         g_variant_unref(result);
1221         if (le_status == BT_LE_ACTIVATED)
1222                 __bt_set_enabled();
1223         else
1224                 _bt_adapter_start_enable_timer();
1225
1226         return BLUETOOTH_ERROR_NONE;
1227 }
1228
1229 static gboolean __bt_set_powered(gboolean powered)
1230 {
1231         GDBusProxy *proxy;
1232         GError *error = NULL;
1233         GVariant *result;
1234
1235         BT_DBG("");
1236
1237         proxy = _bt_get_adapter_properties_proxy();
1238         retv_if(proxy == NULL, FALSE);
1239
1240         result = g_dbus_proxy_call_sync(proxy, "Set",
1241                 g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, "Powered",
1242                 g_variant_new("b", powered)),
1243                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1244         if (!result) {
1245                 if (error != NULL) {
1246                         BT_ERR("Failed to set powered property (Error: %s)",
1247                         error->message);
1248                         g_clear_error(&error);
1249                 } else {
1250                         BT_ERR("Failed to set powered property");
1251                 }
1252                 return FALSE;
1253         }
1254
1255         BT_INFO("Set powered [%d]", powered);
1256         g_variant_unref(result);
1257         return TRUE;
1258 }
1259
1260 static gboolean __bt_disconnect_all(void)
1261 {
1262         int i;
1263         GDBusConnection *conn;
1264         GDBusProxy *dev_proxy;
1265         gboolean ret = FALSE;
1266         GVariant *result;
1267         GError *error = NULL;
1268         GArray *device_list;
1269         bluetooth_device_info_t info;
1270         guint size;
1271         char *device_path = NULL;
1272         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1273
1274
1275         BT_DBG("");
1276
1277         conn = _bt_gdbus_get_system_gconn();
1278
1279         device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
1280
1281         if (_bt_get_bonded_devices(&device_list)
1282                                         != BLUETOOTH_ERROR_NONE) {
1283                 g_array_free(device_list, TRUE);
1284                 return FALSE;
1285         }
1286
1287         size = (device_list->len) / sizeof(bluetooth_device_info_t);
1288
1289         for (i = 0; i < size; i++) {
1290
1291                 info = g_array_index(device_list,
1292                                 bluetooth_device_info_t, i);
1293
1294                 if (info.connected != BLUETOOTH_CONNECTED_LINK_NONE) {
1295                         BT_DBG("Found Connected device");
1296                         _bt_convert_addr_type_to_string(address, info.device_address.addr);
1297                         device_path = _bt_get_device_object_path(address);
1298                         if (device_path == NULL)
1299                                 continue;
1300
1301                         BT_DBG("Disconnecting : %s", device_path);
1302
1303                         dev_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1304                                                         NULL,
1305                                                         BT_BLUEZ_NAME,
1306                                                         device_path,
1307                                                         BT_DEVICE_INTERFACE,
1308                                                         NULL, NULL);
1309
1310                         if (dev_proxy == NULL)
1311                                 continue;
1312
1313                         result = g_dbus_proxy_call_sync(dev_proxy,
1314                                                 "Disconnect",
1315                                                 NULL,
1316                                                 G_DBUS_CALL_FLAGS_NONE,
1317                                                 -1,
1318                                                 NULL,
1319                                                 &error);
1320
1321                         if (!result) {
1322                                 if (error != NULL) {
1323                                         BT_ERR("Disconnect call failed(Error: %s)", error->message);
1324                                         g_clear_error(&error);
1325                                 } else
1326                                         BT_ERR("Disconnect call failed");
1327                                 g_object_unref(dev_proxy);
1328                                 return FALSE;
1329                         }
1330
1331                         g_variant_unref(result);
1332                         g_object_unref(dev_proxy);
1333                 }
1334         }
1335         ret = TRUE;
1336         g_array_free(device_list, TRUE);
1337
1338         return ret;
1339 }
1340
1341 #if 0
1342 static gboolean __bt_set_disabled_timeout_cb(gpointer user_data)
1343 {
1344         BT_DBG("");
1345         _bt_set_disabled(BLUETOOTH_ERROR_NONE);
1346         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
1347                 g_variant_new("(i)", BLUETOOTH_ERROR_NONE));
1348
1349         return FALSE;
1350 }
1351 #endif
1352
1353 int _bt_disable_cb(void)
1354 {
1355         FN_START;
1356         GDBusProxy *proxy;
1357 #if 0
1358         int ret;
1359 #endif
1360         GVariant *result;
1361         GError *error = NULL;
1362
1363         _bt_adapter_set_status(BT_DEACTIVATING);
1364 #if 0
1365         bt_le_status_t le_status;
1366         le_status = _bt_adapter_get_le_status();
1367         BT_DBG("le_status : %d", le_status);
1368         if (le_status == BT_LE_ACTIVATED) {
1369                 BT_INFO("LE is enabled. Just turn off PSCAN");
1370
1371                 if (_bt_is_discovering())
1372                         _bt_cancel_discovery();
1373
1374                 if (_bt_is_connectable() == FALSE) {
1375                         g_timeout_add(100, (GSourceFunc)__bt_set_disabled_timeout_cb, NULL);
1376                 } else {
1377                         ret = _bt_set_connectable(FALSE);
1378                         if (ret != BLUETOOTH_ERROR_NONE) {
1379                                 BT_ERR("_bt_set_connectable fail!");
1380                                 _bt_adapter_set_status(BT_ACTIVATED);
1381                                 return BLUETOOTH_ERROR_INTERNAL;
1382                         }
1383                 }
1384         }
1385 #endif
1386         proxy = __bt_get_core_proxy();
1387         retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL);
1388
1389         result = g_dbus_proxy_call_sync(proxy,
1390                                 "DisableAdapter",
1391                                 NULL,
1392                                 G_DBUS_CALL_FLAGS_NONE,
1393                                 -1,
1394                                 NULL,
1395                                 &error);
1396
1397         if (!result) {
1398                 if (error != NULL) {
1399                         BT_ERR("Failed to DisableAdapter (Error: %s)", error->message);
1400                         g_clear_error(&error);
1401                 } else
1402                         BT_ERR("Failed to DisableAdapter");
1403                 _bt_adapter_set_status(BT_ACTIVATED);
1404                 return BLUETOOTH_ERROR_INTERNAL;
1405         }
1406
1407         g_variant_unref(result);
1408         return BLUETOOTH_ERROR_NONE;
1409 }
1410
1411 int _bt_disable_adapter_check_status(void)
1412 {
1413         bt_status_t status = _bt_adapter_get_status();
1414
1415         BT_DBG("");
1416
1417         if (status == BT_DEACTIVATING) {
1418                 BT_DBG("Disabling in progress");
1419                 return BLUETOOTH_ERROR_IN_PROGRESS;
1420         }
1421
1422         if (status == BT_DEACTIVATED) {
1423                 BT_DBG("Already disabled");
1424                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1425         }
1426
1427         return BLUETOOTH_ERROR_NONE;
1428 }
1429
1430 int _bt_disable_adapter(void)
1431 {
1432         BT_DBG("+");
1433         int ret;
1434         bt_le_status_t le_status;
1435
1436         if (_bt_adapter_get_status() == BT_DEACTIVATING) {
1437                 BT_DBG("Disabling in progress");
1438                 return BLUETOOTH_ERROR_IN_PROGRESS;
1439         }
1440
1441         if (_bt_adapter_get_status() == BT_DEACTIVATED) {
1442                 BT_DBG("Already disabled");
1443                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1444         }
1445
1446         if (timer_id > 0) {
1447                 g_source_remove(timer_id);
1448                 timer_id = 0;
1449         }
1450
1451         /* unregister all the services/servers/profiles registered on bluez-adapter
1452         once adapter is removed, reinitializing of the state-varaibles becomes
1453         a problem */
1454         if (_bt_unregister_obex_server() != BLUETOOTH_ERROR_NONE)
1455                 BT_ERR("Fail to unregister obex server");
1456
1457         if (_bt_unregister_media_player() != BLUETOOTH_ERROR_NONE)
1458                 BT_ERR("Fail to unregister media player");
1459         /* Other unregister APIs should be placed here */
1460
1461         le_status = _bt_adapter_get_le_status();
1462         if (le_status == BT_LE_ACTIVATED && is_le_intended == TRUE) {
1463                 __bt_disconnect_all();
1464         } else {
1465                 if (le_status == BT_LE_ACTIVATED)
1466                         _bt_set_le_disabled(BLUETOOTH_ERROR_NONE);
1467
1468                 __bt_set_powered(FALSE);
1469         }
1470
1471         ret = _bt_disable_cb();
1472
1473         BT_DBG("-");
1474         return ret;
1475 }
1476
1477 int _bt_recover_adapter(void)
1478 {
1479         BT_DBG("+");
1480
1481         if (_bt_adapter_get_status() == BT_DEACTIVATING) {
1482                 BT_ERR("Disabling in progress");
1483                 return BLUETOOTH_ERROR_IN_PROGRESS;
1484         }
1485
1486         if (_bt_adapter_get_status() == BT_DEACTIVATED) {
1487                 BT_ERR("Already disabled");
1488                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1489         }
1490
1491         recovery_cnt = BT_RECOVERY_MAX_COUNT;
1492
1493         _bt_disable_adapter();
1494         _bt_disable_adapter_le();
1495
1496         BT_DBG("-");
1497         return BLUETOOTH_ERROR_NONE;
1498 }
1499
1500 int _bt_reset_adapter(void)
1501 {
1502         GDBusProxy *proxy;
1503         GVariant *result;
1504         GError *error = NULL;
1505
1506         BT_DBG("");
1507
1508         proxy = __bt_get_core_proxy();
1509         if (!proxy)
1510                 return BLUETOOTH_ERROR_INTERNAL;
1511
1512         result = g_dbus_proxy_call_sync(proxy,
1513                                 "ResetAdapter",
1514                                 NULL,
1515                                 G_DBUS_CALL_FLAGS_NONE,
1516                                 -1,
1517                                 NULL,
1518                                 &error);
1519
1520         if (!result) {
1521                 if (error != NULL) {
1522                         BT_ERR("Failed to ResetAdapter (Error: %s)", error->message);
1523                         g_clear_error(&error);
1524                 } else
1525                         BT_ERR("Failed to ResetAdapter");
1526                 return BLUETOOTH_ERROR_INTERNAL;
1527         }
1528
1529         g_variant_unref(result);
1530         /* Terminate myself */
1531         if (_bt_adapter_get_status() == BT_DEACTIVATED)
1532                 g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
1533
1534         return BLUETOOTH_ERROR_NONE;
1535 }
1536
1537 int _bt_check_adapter(int *status)
1538 {
1539 if (!TIZEN_PROFILE_TV) {
1540         char *adapter_path = NULL;
1541
1542         BT_CHECK_PARAMETER(status, return);
1543
1544         *status = BT_ADAPTER_DISABLED;
1545
1546         adapter_path = _bt_get_adapter_path();
1547
1548
1549         if (adapter_path != NULL)
1550                 *status = BT_ADAPTER_ENABLED;
1551
1552         g_free(adapter_path);
1553         return BLUETOOTH_ERROR_NONE;
1554 } else {
1555         GDBusProxy *proxy;
1556         GError *error = NULL;
1557         GVariant *result;
1558         GVariant *temp;
1559         gboolean powered = FALSE;
1560
1561         BT_CHECK_PARAMETER(status, return);
1562
1563         *status = BT_ADAPTER_DISABLED;
1564
1565         proxy = _bt_get_adapter_properties_proxy();
1566         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1567
1568         result = g_dbus_proxy_call_sync(proxy,
1569                                 "Get",
1570                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
1571                                         "Powered"),
1572                                 G_DBUS_CALL_FLAGS_NONE,
1573                                 -1,
1574                                 NULL,
1575                                 &error);
1576
1577         if (!result) {
1578                 BT_ERR("Failed to get local address");
1579                 if (error != NULL) {
1580                         BT_ERR("Failed to get local address (Error: %s)", error->message);
1581                         g_clear_error(&error);
1582                 }
1583                 return BLUETOOTH_ERROR_INTERNAL;
1584         }
1585
1586         g_variant_get(result, "(v)", &temp);
1587         powered = g_variant_get_boolean(temp);
1588         BT_DBG("powered: %d", powered);
1589
1590         if (powered)
1591                 *status = BT_ADAPTER_ENABLED;
1592
1593         g_variant_unref(result);
1594         g_variant_unref(temp);
1595         return BLUETOOTH_ERROR_NONE;
1596 }
1597 }
1598
1599 int _bt_enable_adapter_le(void)
1600 {
1601         BT_DBG("+");
1602         GDBusProxy *proxy;
1603         GError *error = NULL;
1604         bt_status_t status = _bt_adapter_get_status();
1605         bt_le_status_t le_status = _bt_adapter_get_le_status();
1606         GVariant *result;
1607
1608         if (le_status == BT_LE_ACTIVATING) {
1609                 BT_ERR("Enabling in progress");
1610                 return BLUETOOTH_ERROR_IN_PROGRESS;
1611         }
1612
1613         if (le_status == BT_LE_ACTIVATED) {
1614                 BT_ERR("Already enabled");
1615                 return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED;
1616         }
1617
1618         if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) {
1619                 BT_ERR("Disabling in progress");
1620                 _bt_set_le_intended_status(FALSE);
1621                 return BLUETOOTH_ERROR_DEVICE_BUSY;
1622         }
1623
1624         _bt_adapter_set_le_status(BT_LE_ACTIVATING);
1625
1626         proxy = __bt_get_core_proxy();
1627         retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL);
1628
1629         result = g_dbus_proxy_call_sync(proxy, "EnableAdapterLe",
1630                                         NULL,
1631                                         G_DBUS_CALL_FLAGS_NONE, BT_ENABLE_TIMEOUT,
1632                                         NULL, &error);
1633         if (error) {
1634                 BT_ERR("EnableAdapterLe failed: %s", error->message);
1635                 _bt_adapter_set_le_status(BT_DEACTIVATED);
1636                 g_clear_error(&error);
1637
1638                 /* Clean up the process */
1639                 result = g_dbus_proxy_call_sync(proxy,
1640                                         "DisableAdapterLe",
1641                                         NULL,
1642                                         G_DBUS_CALL_FLAGS_NONE,
1643                                         -1,
1644                                         NULL,
1645                                         &error);
1646
1647                 if (!result) {
1648                                 BT_ERR("Bt core call failed");
1649                                 if (error) {
1650                                         BT_ERR("EnableAdapterLE Failed %s", error->message);
1651                                         g_clear_error(&error);
1652                                 }
1653                 }
1654                 g_variant_unref(result);
1655                 /* Terminate myself */
1656                 if (_bt_adapter_get_status() == BT_DEACTIVATED)
1657                         g_idle_add((GSourceFunc)_bt_terminate_service, NULL);
1658                 return BLUETOOTH_ERROR_INTERNAL;
1659         }
1660
1661         if (result)
1662                 g_variant_unref(result);
1663
1664         _bt_adapter_start_le_enable_timer();
1665
1666         if (status == BT_ACTIVATED) {
1667                 _bt_adapter_set_le_status(BT_LE_ACTIVATED);
1668                 __bt_set_le_enabled();
1669         }
1670         BT_DBG("le status : %d", _bt_adapter_get_le_status());
1671         BT_DBG("-");
1672         return BLUETOOTH_ERROR_NONE;
1673 }
1674
1675 int _bt_disable_adapter_le(void)
1676 {
1677         BT_DBG("+");
1678         GDBusProxy *proxy;
1679         bt_le_status_t bt_le_state;
1680         GVariant *result;
1681         GError *error = NULL;
1682
1683         bt_le_state = _bt_adapter_get_le_status();
1684         if (bt_le_state == BT_LE_DEACTIVATING) {
1685                 BT_DBG("Disabling in progress");
1686                 return BLUETOOTH_ERROR_IN_PROGRESS;
1687         }
1688
1689         if (bt_le_state == BT_LE_DEACTIVATED) {
1690                 BT_DBG("Already disabled");
1691                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
1692         }
1693
1694         _bt_adapter_set_le_status(BT_LE_DEACTIVATING);
1695
1696         proxy = __bt_get_core_proxy();
1697         if (!proxy)
1698                 return BLUETOOTH_ERROR_INTERNAL;
1699
1700         result = g_dbus_proxy_call_sync(proxy,
1701                                 "DisableAdapterLe",
1702                                 NULL,
1703                                 G_DBUS_CALL_FLAGS_NONE,
1704                                 -1,
1705                                 NULL,
1706                                 &error);
1707
1708         if (!result) {
1709                 if (error != NULL) {
1710                         BT_ERR("Bt core call failed (Error: %s)", error->message);
1711                         g_clear_error(&error);
1712                 } else
1713                         BT_ERR("Bt core call failed");
1714                 _bt_adapter_set_le_status(BT_LE_ACTIVATED);
1715                 return BLUETOOTH_ERROR_INTERNAL;
1716         }
1717
1718         g_variant_unref(result);
1719         _bt_set_le_disabled(BLUETOOTH_ERROR_NONE);
1720         BT_DBG("le status : %d", _bt_adapter_get_le_status());
1721         BT_DBG("-");
1722         return BLUETOOTH_ERROR_NONE;
1723 }
1724
1725 int _bt_get_local_address(bluetooth_device_address_t *local_address)
1726 {
1727
1728         GDBusProxy *proxy;
1729         GError *error = NULL;
1730         const char *address;
1731         GVariant *result;
1732         GVariant *temp;
1733
1734         BT_CHECK_PARAMETER(local_address, return);
1735
1736         proxy = _bt_get_adapter_properties_proxy();
1737         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1738
1739         result = g_dbus_proxy_call_sync(proxy,
1740                                 "Get",
1741                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
1742                                         "Address"),
1743                                 G_DBUS_CALL_FLAGS_NONE,
1744                                 -1,
1745                                 NULL,
1746                                 &error);
1747
1748         if (!result) {
1749                 BT_ERR("Failed to get local address");
1750                 if (error != NULL) {
1751                         BT_ERR("Failed to get local address (Error: %s)", error->message);
1752                         g_clear_error(&error);
1753                 }
1754                 return BLUETOOTH_ERROR_INTERNAL;
1755         }
1756
1757         g_variant_get(result, "(v)", &temp);
1758         address = g_variant_get_string(temp, NULL);
1759         BT_DBG("Address:%s", address);
1760
1761         if (address)
1762                 _bt_convert_addr_string_to_type(local_address->addr, address);
1763         else
1764                 return BLUETOOTH_ERROR_INTERNAL;
1765
1766         g_variant_unref(result);
1767         g_variant_unref(temp);
1768         return BLUETOOTH_ERROR_NONE;
1769 }
1770
1771 int _bt_get_local_version(bluetooth_version_t *local_version)
1772 {
1773         GDBusProxy *proxy;
1774         const char *ver = NULL;
1775         char *ptr = NULL;
1776         int ret = BLUETOOTH_ERROR_NONE;
1777         GVariant *result;
1778         GVariant *temp;
1779
1780         BT_CHECK_PARAMETER(local_version, return);
1781
1782         GError *error = NULL;
1783
1784         proxy = _bt_get_adapter_properties_proxy();
1785         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1786
1787         result = g_dbus_proxy_call_sync(proxy,
1788                                 "Get",
1789                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
1790                                         "Version"),
1791                                 G_DBUS_CALL_FLAGS_NONE,
1792                                 -1,
1793                                 NULL,
1794                                 &error);
1795
1796         if (!result) {
1797                 if (error != NULL) {
1798                         BT_ERR("Failed to get local version (Error: %s)", error->message);
1799                         g_clear_error(&error);
1800                 } else
1801                         BT_ERR("Failed to get local version");
1802                 return BLUETOOTH_ERROR_INTERNAL;
1803         }
1804
1805         g_variant_get(result, "(v)", &temp);
1806         ver = g_variant_get_string(temp, NULL);
1807         BT_DBG("VERSION: %s", ver);
1808
1809         if (ver && (strlen(ver) > 0)) {
1810                 /* Check the utf8 valitation & Fill the NULL in the invalid location*/
1811                 if (!g_utf8_validate(ver, -1, (const char **)&ptr))
1812                         *ptr = '\0';
1813
1814                 g_strlcpy(local_version->version, ver,
1815                                 BLUETOOTH_VERSION_LENGTH_MAX + 1);
1816
1817         } else {
1818                 ret = BLUETOOTH_ERROR_INTERNAL;
1819         }
1820
1821         g_variant_unref(result);
1822         g_variant_unref(temp);
1823         return ret;
1824 }
1825
1826 int _bt_get_local_name(bluetooth_device_name_t *local_name)
1827 {
1828         GDBusProxy *proxy;
1829         const char *name = NULL;
1830         char *ptr = NULL;
1831         int ret = BLUETOOTH_ERROR_NONE;
1832         GVariant *result;
1833         GVariant *temp;
1834         GError *error = NULL;
1835
1836         BT_CHECK_PARAMETER(local_name, return);
1837
1838         proxy = _bt_get_adapter_properties_proxy();
1839         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1840
1841         result = g_dbus_proxy_call_sync(proxy,
1842                                 "Get",
1843                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
1844                                         "Alias"),
1845                                 G_DBUS_CALL_FLAGS_NONE,
1846                                 -1,
1847                                 NULL,
1848                                 &error);
1849
1850         if (!result) {
1851                 if (error != NULL) {
1852                         BT_ERR("Failed to get local name (Error: %s)", error->message);
1853                         g_clear_error(&error);
1854                 } else
1855                         BT_ERR("Failed to get local name");
1856                 return BLUETOOTH_ERROR_INTERNAL;
1857         }
1858
1859         g_variant_get(result, "(v)", &temp);
1860         name = g_variant_get_string(temp, NULL);
1861         BT_DBG("LOCAL NAME:%s", name);
1862
1863         if (name && (strlen(name) > 0)) {
1864                 /* Check the utf8 valitation & Fill the NULL in the invalid location*/
1865                 if (!g_utf8_validate(name, -1, (const char **)&ptr))
1866                         *ptr = '\0';
1867
1868                 g_strlcpy(local_name->name, name,
1869                                 BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1);
1870         } else {
1871                 ret = BLUETOOTH_ERROR_INTERNAL;
1872         }
1873         g_variant_unref(result);
1874         g_variant_unref(temp);
1875         return ret;
1876 }
1877
1878 int _bt_set_local_name(char *local_name)
1879 {
1880         GDBusProxy *proxy;
1881         GError *error = NULL;
1882         char *ptr = NULL;
1883         GVariant *result;
1884
1885         BT_CHECK_PARAMETER(local_name, return);
1886
1887         proxy = _bt_get_adapter_properties_proxy();
1888
1889         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1890
1891         if (!g_utf8_validate(local_name, -1, (const char **)&ptr))
1892                 *ptr = '\0';
1893
1894         result = g_dbus_proxy_call_sync(proxy,
1895                                 "Set",
1896                                 g_variant_new("(ssv)", BT_ADAPTER_INTERFACE,
1897                                         "Alias", g_variant_new("s", local_name)),
1898                                 G_DBUS_CALL_FLAGS_NONE,
1899                                 -1,
1900                                 NULL,
1901                                 &error);
1902
1903         if (!result) {
1904                 if (error != NULL) {
1905                         BT_ERR("Failed to set Alias (Error: %s)", error->message);
1906                         g_clear_error(&error);
1907                 } else
1908                         BT_ERR("Failed to set Alias");
1909                 return BLUETOOTH_ERROR_INTERNAL;
1910         }
1911
1912         g_variant_unref(result);
1913         return BLUETOOTH_ERROR_NONE;
1914 }
1915
1916 int _bt_is_service_used(char *service_uuid, gboolean *used)
1917 {
1918         GDBusProxy *proxy;
1919         GError *error = NULL;
1920         int ret = BLUETOOTH_ERROR_NONE;
1921         GVariant *result;
1922         GVariant *temp = NULL;
1923         GVariantIter *iter = NULL;
1924         gchar *uuid = NULL;
1925
1926         BT_DBG("+");
1927         BT_CHECK_PARAMETER(service_uuid, return);
1928         BT_CHECK_PARAMETER(used, return);
1929
1930         proxy = _bt_get_adapter_properties_proxy();
1931         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1932
1933         result = g_dbus_proxy_call_sync(proxy,
1934                                 "Get",
1935                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
1936                                         "UUIDs"),
1937                                 G_DBUS_CALL_FLAGS_NONE,
1938                                 -1,
1939                                 NULL,
1940                                 &error);
1941
1942         if (!result) {
1943                 if (error != NULL) {
1944                         BT_ERR("Failed to get UUIDs (Error: %s)", error->message);
1945                         g_clear_error(&error);
1946                 } else
1947                         BT_ERR("Failed to get UUIDs");
1948                 return BLUETOOTH_ERROR_INTERNAL;
1949         }
1950
1951         g_variant_get(result, "(v)", &temp);
1952         g_variant_get(temp, "as", &iter);
1953
1954         *used = FALSE;
1955         while (g_variant_iter_loop(iter, "&s", &uuid)) {
1956                 if (strcasecmp(uuid, service_uuid) == 0) {
1957                         *used = TRUE;
1958                         break;
1959                 }
1960         }
1961         g_variant_iter_free(iter);
1962         g_variant_unref(result);
1963
1964         BT_DBG("Service Used? %d", *used);
1965
1966         return ret;
1967 }
1968
1969 static gboolean __bt_get_discoverable_property(void)
1970 {
1971         GDBusProxy *proxy;
1972         gboolean discoverable_v;
1973         GError *error = NULL;
1974         GVariant *result;
1975         GVariant *temp;
1976
1977         proxy = _bt_get_adapter_properties_proxy();
1978         retv_if(proxy == NULL, FALSE);
1979
1980         result = g_dbus_proxy_call_sync(proxy,
1981                                 "Get",
1982                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
1983                                         "Discoverable"),
1984                                 G_DBUS_CALL_FLAGS_NONE,
1985                                 -1,
1986                                 NULL,
1987                                 &error);
1988
1989         if (!result) {
1990                 if (error != NULL) {
1991                         BT_ERR("Failed to get Discoverable property (Error: %s)", error->message);
1992                         g_clear_error(&error);
1993                 } else
1994                         BT_ERR("Failed to get Discoverable property");
1995                 return BLUETOOTH_ERROR_INTERNAL;
1996         }
1997
1998         g_variant_get(result, "(v)", &temp);
1999         discoverable_v = g_variant_get_boolean(temp);
2000         BT_DBG("discoverable_v:%d", discoverable_v);
2001
2002         g_variant_unref(result);
2003         g_variant_unref(temp);
2004
2005         return discoverable_v;
2006 }
2007
2008 int _bt_get_discoverable_mode(int *mode)
2009 {
2010         gboolean discoverable;
2011         unsigned int timeout;
2012
2013         BT_CHECK_PARAMETER(mode, return);
2014
2015         discoverable = __bt_get_discoverable_property();
2016         timeout = _bt_get_discoverable_timeout_property();
2017
2018         if (discoverable == TRUE) {
2019                 if (timeout == 0)
2020                         *mode = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE;
2021                 else
2022                         *mode = BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE;
2023         } else {
2024                 *mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE;
2025         }
2026         return BLUETOOTH_ERROR_NONE;
2027 }
2028
2029
2030 int _bt_set_discoverable_mode(int discoverable_mode, int timeout)
2031 {
2032         int ret = BLUETOOTH_ERROR_NONE;
2033         gboolean inq_scan;
2034         gboolean pg_scan;
2035         GError *error = NULL;
2036         GDBusProxy *proxy;
2037         GVariant *result;
2038 #ifdef TIZEN_FEATURE_BT_DPM
2039         int discoverable_state = DPM_BT_ERROR;
2040 #endif
2041
2042         proxy = _bt_get_adapter_properties_proxy();
2043
2044         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2045
2046 #ifdef TIZEN_FEATURE_BT_DPM
2047         _bt_dpm_get_bluetooth_limited_discoverable_state(&discoverable_state);
2048         if (discoverable_mode != BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE &&
2049             discoverable_state == DPM_RESTRICTED) {
2050                 if (headed_plugin_info->plugin_headed_enabled)
2051                         headed_plugin_info->headed_plugin->bt_launch_dpmpopup("DPM_POLICY_DISABLE_BT_HANDSFREE");
2052
2053                 return BLUETOOTH_ERROR_ACCESS_DENIED;
2054         }
2055
2056         if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE &&
2057             discoverable_state == DPM_RESTRICTED) {
2058                 if (headed_plugin_info->plugin_headed_enabled)
2059                         headed_plugin_info->headed_plugin->bt_launch_dpmpopup("DPM_POLICY_DISABLE_BT");
2060
2061                 return BLUETOOTH_ERROR_ACCESS_DENIED;
2062         }
2063 #endif
2064
2065         switch (discoverable_mode) {
2066         case BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE:
2067                 pg_scan = TRUE;
2068                 inq_scan = FALSE;
2069                 timeout = 0;
2070                 break;
2071         case BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE:
2072                 pg_scan = TRUE;
2073                 inq_scan = TRUE;
2074                 timeout = 0;
2075                 break;
2076         case BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE:
2077                 inq_scan = TRUE;
2078                 pg_scan = TRUE;
2079                 break;
2080         default:
2081                 return BLUETOOTH_ERROR_INVALID_PARAM;
2082         }
2083
2084         BT_INFO("Req. discoverable_mode : %d, timeout : %d",
2085                         discoverable_mode, timeout);
2086
2087         result = g_dbus_proxy_call_sync(proxy,
2088                                 "Set",
2089                                 g_variant_new("(ssv)", BT_ADAPTER_INTERFACE,
2090                                         "Connectable", g_variant_new("b", pg_scan)),
2091                                 G_DBUS_CALL_FLAGS_NONE,
2092                                 -1,
2093                                 NULL,
2094                                 &error);
2095
2096         if (!result) {
2097                 if (error != NULL) {
2098                         BT_ERR("Failed to set connectable property (Error: %s)", error->message);
2099                         g_clear_error(&error);
2100                 } else
2101                         BT_ERR("Failed to set connectable property");
2102                 return BLUETOOTH_ERROR_INTERNAL;
2103         }
2104         g_variant_unref(result);
2105         result = g_dbus_proxy_call_sync(proxy,
2106                                 "Set",
2107                                 g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, "Discoverable",
2108                                                 g_variant_new("b", inq_scan)),
2109                                 G_DBUS_CALL_FLAGS_NONE,
2110                                 -1,
2111                                 NULL,
2112                                 &error);
2113
2114         if (!result) {
2115                 if (error != NULL) {
2116                         BT_ERR("Failed to set Discoverable property (Error: %s)", error->message);
2117                         g_clear_error(&error);
2118                 } else
2119                         BT_ERR("Failed to set Discoverable property");
2120                 return BLUETOOTH_ERROR_INTERNAL;
2121         }
2122         g_variant_unref(result);
2123         result = g_dbus_proxy_call_sync(proxy,
2124                                 "Set",
2125                                 g_variant_new("(ssv)", BT_ADAPTER_INTERFACE,
2126                                         "DiscoverableTimeout", g_variant_new("u", timeout)),
2127                                 G_DBUS_CALL_FLAGS_NONE,
2128                                 -1,
2129                                 NULL,
2130                                 &error);
2131
2132         if (!result) {
2133                 if (error != NULL) {
2134                         BT_ERR("Failed to set DiscoverableTimeout property (Error: %s)", error->message);
2135                         g_clear_error(&error);
2136                 } else
2137                         BT_ERR("Failed to set DiscoverableTimeout property");
2138                 return BLUETOOTH_ERROR_INTERNAL;
2139         }
2140
2141         if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE) {
2142                 ret = _bt_stop_visibility_timer();
2143                 if (!TIZEN_PROFILE_WEARABLE) {
2144                         if (vconf_set_int(BT_FILE_VISIBLE_TIME, -1) != 0)
2145                                 BT_ERR("Set vconf failed");
2146                 }
2147         } else if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE) {
2148                 ret = _bt_start_visibility_timer(timeout);
2149         } else {
2150                 ret = _bt_stop_visibility_timer();
2151         }
2152
2153         g_variant_unref(result);
2154
2155         return ret;
2156 }
2157
2158 int _bt_start_discovery(void)
2159 {
2160         GDBusProxy *proxy;
2161         GError *error = NULL;
2162         GVariant *result;
2163
2164         if (_bt_is_discovering() == TRUE) {
2165                 BT_ERR("BT is already in discovering");
2166                 return BLUETOOTH_ERROR_IN_PROGRESS;
2167         } else if (_bt_is_device_creating() == TRUE) {
2168                 BT_ERR("Bonding device is going on");
2169                 return BLUETOOTH_ERROR_DEVICE_BUSY;
2170         }
2171
2172         proxy = _bt_get_adapter_proxy();
2173         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2174
2175         result = g_dbus_proxy_call_sync(proxy,
2176                                 "StartDiscovery",
2177                                 NULL,
2178                                 G_DBUS_CALL_FLAGS_NONE,
2179                                 -1,
2180                                 NULL,
2181                                 &error);
2182
2183         if (!result) {
2184                 if (error != NULL) {
2185                         BT_ERR("StartDiscovery failed (Error: %s)", error->message);
2186                         g_clear_error(&error);
2187                 } else
2188                         BT_ERR("StartDiscovery failed");
2189                 return BLUETOOTH_ERROR_INTERNAL;
2190         }
2191
2192         discovery_req = TRUE;
2193         cancel_by_user = FALSE;
2194         /* discovery status will be change in event */
2195         g_variant_unref(result);
2196         return BLUETOOTH_ERROR_NONE;
2197 }
2198
2199 int _bt_start_custom_discovery(bt_discovery_role_type_t role)
2200 {
2201         GDBusProxy *proxy;
2202         GVariant *result;
2203         GError *error = NULL;
2204         const gchar *disc_type;
2205
2206         if (_bt_is_discovering() == TRUE) {
2207                 BT_ERR("BT is already in discovering");
2208                 return BLUETOOTH_ERROR_IN_PROGRESS;
2209         }
2210
2211         proxy = _bt_get_adapter_proxy();
2212         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2213
2214         if (role == DISCOVERY_ROLE_BREDR)
2215                 disc_type = "BREDR";
2216         else if (role == DISCOVERY_ROLE_LE)
2217                 disc_type = "LE";
2218         else if (role == DISCOVERY_ROLE_LE_BREDR)
2219                 disc_type = "LE_BREDR";
2220         else
2221                 return BLUETOOTH_ERROR_INVALID_PARAM;
2222
2223         result = g_dbus_proxy_call_sync(proxy,
2224                                 "StartCustomDiscovery",
2225                                 g_variant_new("s", disc_type),
2226                                 G_DBUS_CALL_FLAGS_NONE,
2227                                 -1,
2228                                 NULL,
2229                                 &error);
2230
2231         if (!result) {
2232                 if (error != NULL) {
2233                         BT_ERR("StartCustomDiscovery failed (Error: %s)", error->message);
2234                         g_clear_error(&error);
2235                 } else
2236                         BT_ERR("StartCustomDiscovery failed");
2237                 return BLUETOOTH_ERROR_INTERNAL;
2238         }
2239
2240         discovery_req = TRUE;
2241         cancel_by_user = FALSE;
2242         /* discovery status will be change in event */
2243         g_variant_unref(result);
2244         return BLUETOOTH_ERROR_NONE;
2245 }
2246
2247 int _bt_cancel_discovery(void)
2248 {
2249         GDBusProxy *proxy;
2250         GError *error = NULL;
2251         GVariant *result;
2252
2253         if (_bt_is_discovering() == FALSE) {
2254                 BT_ERR("BT is not in discovering");
2255                 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
2256         }
2257
2258         proxy = _bt_get_adapter_proxy();
2259         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2260
2261         result = g_dbus_proxy_call_sync(proxy,
2262                                 "StopDiscovery",
2263                                 NULL,
2264                                 G_DBUS_CALL_FLAGS_NONE,
2265                                 -1,
2266                                 NULL,
2267                                 &error);
2268
2269         if (!result) {
2270                 int ret = BLUETOOTH_ERROR_INTERNAL;
2271                 if (error != NULL) {
2272                         BT_ERR("StopDiscovery failed (Error: %s)", error->message);
2273
2274                         if (g_strrstr(error->message, "No discovery started"))
2275                                 ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
2276
2277                         g_clear_error(&error);
2278                 } else {
2279                         BT_ERR("StopDiscovery failed");
2280                 }
2281
2282                 return ret;
2283         }
2284
2285         discovery_req = FALSE;
2286         cancel_by_user = TRUE;
2287         /* discovery status will be change in event */
2288         g_variant_unref(result);
2289         return BLUETOOTH_ERROR_NONE;
2290 }
2291
2292 gboolean _bt_is_discovering(void)
2293 {
2294         return (is_discovering || discovery_req);
2295 }
2296
2297 gboolean _bt_is_connectable(void)
2298 {
2299         GDBusProxy *proxy;
2300         GError *error = NULL;
2301         gboolean is_connectable = FALSE;
2302         GVariant *result;
2303         GVariant *temp;
2304
2305         proxy = _bt_get_adapter_properties_proxy();
2306         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2307
2308         result = g_dbus_proxy_call_sync(proxy,
2309                                 "Get",
2310                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
2311                                         "Connectable"),
2312                                 G_DBUS_CALL_FLAGS_NONE,
2313                                 -1,
2314                                 NULL,
2315                                 &error);
2316
2317         if (!result) {
2318                 if (error != NULL) {
2319                         BT_ERR("Failed to get connectable property (Error: %s)", error->message);
2320                         g_clear_error(&error);
2321                 } else
2322                         BT_ERR("Failed to get connectable property");
2323                 return BLUETOOTH_ERROR_INTERNAL;
2324         }
2325
2326         g_variant_get(result, "(v)", &temp);
2327         is_connectable = g_variant_get_boolean(temp);
2328         BT_DBG("discoverable_v:%d", is_connectable);
2329
2330         g_variant_unref(result);
2331         g_variant_unref(temp);
2332
2333         BT_INFO("Get connectable [%d]", is_connectable);
2334         return is_connectable;
2335 }
2336
2337 int _bt_set_connectable(gboolean is_connectable)
2338 {
2339         GDBusProxy *proxy;
2340         GError *error = NULL;
2341         GVariant *result;
2342
2343         if (__bt_is_factory_test_mode()) {
2344                 BT_ERR("Unable to set connectable in factory binary !!");
2345                 return BLUETOOTH_ERROR_NOT_SUPPORT;
2346         }
2347
2348         proxy = _bt_get_adapter_properties_proxy();
2349
2350         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2351
2352         result = g_dbus_proxy_call_sync(proxy,
2353                                 "Set",
2354                                 g_variant_new("(ssv)", BT_ADAPTER_INTERFACE, "Connectable",
2355                                                 g_variant_new("b", is_connectable)),
2356                                 G_DBUS_CALL_FLAGS_NONE,
2357                                 -1,
2358                                 NULL,
2359                                 &error);
2360
2361         if (!result) {
2362                 if (error != NULL) {
2363                         BT_ERR("Failed to set connectable property (Error: %s)", error->message);
2364                         g_clear_error(&error);
2365                 } else
2366                         BT_ERR("Failed to set connectable property");
2367                 return BLUETOOTH_ERROR_INTERNAL;
2368         }
2369
2370         BT_INFO_C("### Set connectable [%d]", is_connectable);
2371         g_variant_unref(result);
2372         return BLUETOOTH_ERROR_NONE;
2373 }
2374
2375 gboolean _bt_get_discovering_property(bt_discovery_role_type_t discovery_type)
2376 {
2377         GDBusProxy *proxy;
2378         gboolean discovering_v;
2379         GError *error = NULL;
2380         char *discovering_type =  NULL;
2381         GVariant *result;
2382         GVariant *temp;
2383
2384         proxy = _bt_get_adapter_properties_proxy();
2385         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2386
2387         if (discovery_type == DISCOVERY_ROLE_BREDR)
2388                 discovering_type = "Discovering";
2389         else if (discovery_type == DISCOVERY_ROLE_LE)
2390                 discovering_type = "LEDiscovering";
2391
2392         result = g_dbus_proxy_call_sync(proxy,
2393                                 "Get",
2394                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
2395                                         discovering_type),
2396                                 G_DBUS_CALL_FLAGS_NONE,
2397                                 -1,
2398                                 NULL,
2399                                 &error);
2400
2401         if (!result) {
2402                 if (error != NULL) {
2403                         BT_ERR("Failed to get discovering property (Error: %s)", error->message);
2404                         g_clear_error(&error);
2405                 } else
2406                         BT_ERR("Failed to get discovering property");
2407                 return BLUETOOTH_ERROR_INTERNAL;
2408         }
2409
2410         g_variant_get(result, "(v)", &temp);
2411         discovering_v = g_variant_get_boolean(temp);
2412         BT_DBG("discoverable_v:%d", discovering_v);
2413
2414         g_variant_unref(result);
2415         g_variant_unref(temp);
2416
2417         return discovering_v;
2418 }
2419
2420 unsigned int _bt_get_discoverable_timeout_property(void)
2421 {
2422         GDBusProxy *proxy;
2423         unsigned int timeout_v;
2424         GError *error = NULL;
2425         GVariant *result;
2426         GVariant *temp;
2427
2428         proxy = _bt_get_adapter_properties_proxy();
2429         retv_if(proxy == NULL, 0);
2430
2431         result = g_dbus_proxy_call_sync(proxy,
2432                                 "Get",
2433                                 g_variant_new("(ss)", BT_ADAPTER_INTERFACE,
2434                                         "DiscoverableTimeout"),
2435                                 G_DBUS_CALL_FLAGS_NONE,
2436                                 -1,
2437                                 NULL,
2438                                 &error);
2439
2440         if (!result) {
2441                 BT_ERR("Fail to get discoverable timeout");
2442                 if (error != NULL) {
2443                         BT_ERR("Fail to get discoverable timeout (Error: %s)", error->message);
2444                         g_clear_error(&error);
2445                 }
2446                 return 0;
2447         }
2448
2449         g_variant_get(result, "(v)", &temp);
2450         timeout_v = g_variant_get_uint32(temp);
2451         BT_DBG("discoverable_v:%d", timeout_v);
2452
2453         g_variant_unref(result);
2454         g_variant_unref(temp);
2455
2456         return timeout_v;
2457 }
2458
2459 static bluetooth_device_info_t *__bt_parse_device_info(GVariantIter *item_iter)
2460 {
2461         bluetooth_device_info_t *dev_info;
2462         GVariant *value;
2463         const gchar *key;
2464         GByteArray *manufacturer_data = NULL;
2465         guint8 char_value;
2466         GVariantIter *char_value_iter;
2467
2468         dev_info = g_malloc0(sizeof(bluetooth_device_info_t));
2469
2470         while (g_variant_iter_loop(item_iter, "{sv}", &key, &value)) {
2471
2472                 if (key == NULL)
2473                         continue;
2474
2475                 if (!g_strcmp0(key, "Address")) {
2476                         const char *address = NULL;
2477                         address = g_variant_get_string(value, NULL);
2478                         _bt_convert_addr_string_to_type(dev_info->device_address.addr,
2479                                                         address);
2480                 } else if (!g_strcmp0(key, "Class")) {
2481                         unsigned int cod;
2482                         cod = g_variant_get_uint32(value);
2483                         _bt_divide_device_class(&dev_info->device_class, cod);
2484                 } else if (!g_strcmp0(key, "Name")) {
2485                         const char *name = NULL;
2486                         name = g_variant_get_string(value, NULL);
2487                         /* If there is no Alias */
2488                         if (strlen(dev_info->device_name.name) == 0) {
2489                                 g_strlcpy(dev_info->device_name.name, name,
2490                                                 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
2491                         }
2492                 } else if (!g_strcmp0(key, "Alias")) {
2493                         const char *alias = NULL;
2494                         alias = g_variant_get_string(value, NULL);
2495                         /* Overwrite the name */
2496                         if (alias) {
2497                                 memset(dev_info->device_name.name, 0x00,
2498                                                 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
2499                                 g_strlcpy(dev_info->device_name.name, alias,
2500                                                 BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1);
2501                         }
2502                 } else if (!g_strcmp0(key, "IsAliasSet")) {
2503                         dev_info->is_alias_set = g_variant_get_boolean(value);
2504                 } else if (!g_strcmp0(key, "Connected")) {
2505                         dev_info->connected = g_variant_get_byte(value);
2506                 } else if (!g_strcmp0(key, "Paired")) {
2507                         dev_info->paired = g_variant_get_boolean(value);
2508                 } else if (!g_strcmp0(key, "Trusted")) {
2509                         dev_info->trust = g_variant_get_boolean(value);
2510                 } else if (!g_strcmp0(key, "RSSI")) {
2511                         dev_info->rssi = g_variant_get_int16(value);
2512                 } else if (!g_strcmp0(key, "UUIDs")) {
2513                         GVariantIter *iter;
2514                         gchar *uuid = NULL;
2515                         char **parts;
2516                         int i = 0;
2517
2518                         dev_info->service_index = 0;
2519                         g_variant_get(value, "as", &iter);
2520                         while (g_variant_iter_loop(iter, "s", &uuid)) {
2521                                 g_strlcpy(dev_info->uuids[i], uuid, BLUETOOTH_UUID_STRING_MAX);
2522                                 parts = g_strsplit(uuid, "-", -1);
2523
2524                                 if (parts == NULL || parts[0] == NULL) {
2525                                         g_free(uuid);
2526                                         break;
2527                                 }
2528
2529                                 dev_info->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16);
2530                                 g_strfreev(parts);
2531
2532                                 i++;
2533                         }
2534                         dev_info->service_index = i;
2535                         g_variant_iter_free(iter);
2536                 } else if (strcasecmp(key, "ManufacturerDataLen") == 0) {
2537                         dev_info->manufacturer_data.data_len = g_variant_get_uint16(value);
2538                 } else if (strcasecmp(key, "ManufacturerData") == 0) {
2539                         manufacturer_data = g_byte_array_new();
2540                         g_variant_get(value, "ay", &char_value_iter);
2541                         while (g_variant_iter_loop(char_value_iter, "y",  &char_value))
2542                                 g_byte_array_append(manufacturer_data, &char_value, 1);
2543
2544                         if (manufacturer_data) {
2545                                 if (manufacturer_data->len > 0)
2546                                         memcpy(dev_info->manufacturer_data.data, manufacturer_data->data, manufacturer_data->len);
2547                         }
2548                         g_variant_iter_free(char_value_iter);
2549                         g_byte_array_free(manufacturer_data, TRUE);
2550                 }
2551         }
2552
2553         return dev_info;
2554 }
2555
2556 static void __bt_extract_device_info(GVariantIter *iter,
2557                                                         GArray **dev_list)
2558 {
2559         bluetooth_device_info_t *dev_info = NULL;
2560         char *object_path = NULL;
2561         GVariantIter *interface_iter;
2562         GVariantIter *svc_iter;
2563         char *interface_str = NULL;
2564
2565         /* Parse the signature:  oa{sa{sv}}} */
2566         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
2567                 &interface_iter)) {
2568
2569                 if (object_path == NULL)
2570                         continue;
2571
2572                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
2573                                 &interface_str, &svc_iter)) {
2574                         if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
2575                                 BT_DBG("Found a device: %s", object_path);
2576                                 dev_info = __bt_parse_device_info(svc_iter);
2577                                 if (dev_info) {
2578                                         if (dev_info->paired == TRUE) {
2579                                                 g_array_append_vals(*dev_list, dev_info,
2580                                                                 sizeof(bluetooth_device_info_t));
2581                                         }
2582                                         g_free(dev_info);
2583                                 }
2584                                 g_free(interface_str);
2585                                 g_variant_iter_free(svc_iter);
2586                                 break;
2587                         }
2588                 }
2589         }
2590         BT_DBG("-");
2591 }
2592
2593 int _bt_get_bonded_devices(GArray **dev_list)
2594 {
2595         BT_DBG("+");
2596         GDBusConnection *conn;
2597         GDBusProxy *manager_proxy;
2598         GVariant *result = NULL;
2599         GVariantIter *iter = NULL;
2600         GError *error = NULL;
2601
2602         conn = _bt_gdbus_get_system_gconn();
2603         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
2604
2605         manager_proxy = _bt_get_manager_proxy();
2606         retv_if(manager_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2607
2608         result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
2609                                 NULL,
2610                                 G_DBUS_CALL_FLAGS_NONE,
2611                                 -1,
2612                                 NULL,
2613                                 NULL);
2614
2615         if (!result) {
2616                 if (error != NULL) {
2617                         BT_ERR("Failed to GetManagedObjects (Error: %s)", error->message);
2618                         g_clear_error(&error);
2619                 } else
2620                         BT_ERR("Failed to Failed to GetManagedObjects");
2621                 return BLUETOOTH_ERROR_INTERNAL;
2622         }
2623
2624         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
2625         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
2626
2627         __bt_extract_device_info(iter, dev_list);
2628         g_variant_iter_free(iter);
2629         g_variant_unref(result);
2630
2631         BT_DBG("-");
2632         return BLUETOOTH_ERROR_NONE;
2633 }
2634
2635 int _bt_get_profile_connected_devices(char *profile_uuid, GArray **addr_list)
2636 {
2637         BT_DBG("+");
2638         GDBusConnection *conn;
2639         GDBusProxy *manager_proxy;
2640         GVariant *result = NULL;
2641         GVariant *result1 = NULL;
2642         GVariantIter *iter = NULL;
2643         GError *error = NULL;
2644         char *object_path = NULL;
2645         GVariantIter *interface_iter;
2646         char *interface_str = NULL;
2647         GDBusProxy *device_proxy = NULL;
2648         gboolean is_connected = FALSE;
2649
2650         conn = _bt_gdbus_get_system_gconn();
2651         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
2652
2653         manager_proxy = _bt_get_manager_proxy();
2654         retv_if(manager_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2655
2656         result = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects",
2657                                 NULL,
2658                                 G_DBUS_CALL_FLAGS_NONE,
2659                                 -1,
2660                                 NULL,
2661                                 NULL);
2662
2663         if (!result) {
2664                 if (error != NULL) {
2665                         BT_ERR("Failed to GetManagedObjects (Error: %s)", error->message);
2666                         g_clear_error(&error);
2667                         error = NULL;
2668                 } else
2669                         BT_ERR("Failed to Failed to GetManagedObjects");
2670                 return BLUETOOTH_ERROR_INTERNAL;
2671         }
2672
2673         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
2674         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
2675
2676         /* Parse the signature:  oa{sa{sv}}} */
2677         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, &interface_iter)) {
2678                 if (object_path == NULL)
2679                         continue;
2680
2681                 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
2682                                 &interface_str, NULL)) {
2683                         if (g_strcmp0(interface_str, "org.bluez.Device1") == 0) {
2684                                 BT_DBG("Found a device: %s", object_path);
2685                                 g_free(interface_str);
2686
2687                                 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2688                                                                                         NULL, BT_BLUEZ_NAME,
2689                                                                                         object_path, BT_DEVICE_INTERFACE,  NULL, NULL);
2690
2691                                 if (device_proxy == NULL) {
2692                                         BT_DBG("Device don't have this service");
2693                                         break;
2694                                 }
2695
2696                                 result1 = g_dbus_proxy_call_sync(device_proxy, "IsConnectedProfile",
2697                                                         g_variant_new("(s)", profile_uuid),
2698                                                         G_DBUS_CALL_FLAGS_NONE,
2699                                                         -1,
2700                                                         NULL,
2701                                                         &error);
2702
2703                                 if (result1 == NULL) {
2704                                         BT_ERR("Error occured in Proxy call");
2705                                         if (error) {
2706                                                 BT_ERR("Error occured in Proxy call [%s]\n", error->message);
2707                                                 g_error_free(error);
2708                                                 error = NULL;
2709                                         }
2710                                         g_object_unref(device_proxy);
2711                                         break;
2712                                 }
2713                                 g_variant_get(result1, "(b)", &is_connected);
2714
2715                                 if (is_connected == TRUE) {
2716                                         char address[BT_ADDRESS_STRING_SIZE];
2717                                         bluetooth_device_address_t *addr = NULL;
2718
2719                                         _bt_convert_device_path_to_address(object_path, address);
2720
2721                                         addr = g_malloc0(sizeof(bluetooth_device_address_t));
2722                                         _bt_convert_addr_string_to_type(addr->addr, address);
2723
2724                                         g_array_append_vals(*addr_list, addr,
2725                                                         sizeof(bluetooth_device_address_t));
2726                                 }
2727
2728                                 g_variant_unref(result1);
2729                                 g_object_unref(device_proxy);
2730
2731                                 break;
2732                         }
2733                 }
2734         }
2735
2736         g_variant_unref(result);
2737         g_variant_iter_free(iter);
2738
2739         BT_DBG("-");
2740         return BLUETOOTH_ERROR_NONE;
2741 }
2742
2743 int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address,
2744                                 bluetooth_device_info_t *dev_info)
2745 {
2746         char *object_path = NULL;
2747         GDBusProxy *adapter_proxy;
2748         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
2749         int ret = BLUETOOTH_ERROR_NONE;
2750
2751         BT_CHECK_PARAMETER(device_address, return);
2752         BT_CHECK_PARAMETER(dev_info, return);
2753
2754         adapter_proxy = _bt_get_adapter_proxy();
2755         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2756
2757         _bt_convert_addr_type_to_string(address, device_address->addr);
2758
2759         object_path = _bt_get_device_object_path(address);
2760
2761         retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
2762
2763         ret = __bt_get_bonded_device_info(object_path, dev_info);
2764         g_free(object_path);
2765
2766         return ret;
2767 }
2768
2769 int _bt_is_alias_set(bluetooth_device_address_t *device_address, gboolean *is_alias_set)
2770 {
2771         char *object_path = NULL;
2772         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
2773         gboolean alias_set = FALSE;
2774
2775         GDBusConnection *conn;
2776         GDBusProxy *device_proxy;
2777         GError *error = NULL;
2778         GVariant *result = NULL;
2779         GVariant *temp = NULL;
2780
2781
2782         BT_CHECK_PARAMETER(device_address, return);
2783         BT_CHECK_PARAMETER(is_alias_set, return);
2784
2785         _bt_convert_addr_type_to_string(address, device_address->addr);
2786
2787         object_path = _bt_get_device_object_path(address);
2788         retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
2789
2790         conn = _bt_gdbus_get_system_gconn();
2791         if (conn == NULL) {
2792                 g_free(object_path);
2793                 return BLUETOOTH_ERROR_INTERNAL;
2794         }
2795
2796         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2797                         NULL,
2798                         BT_BLUEZ_NAME,
2799                         object_path,
2800                         BT_PROPERTIES_INTERFACE,
2801                         NULL, NULL);
2802         if (device_proxy == NULL) {
2803                 g_free(object_path);
2804                 return BLUETOOTH_ERROR_INTERNAL;
2805         }
2806
2807         result = g_dbus_proxy_call_sync(device_proxy, "Get",
2808                         g_variant_new("(ss)", BT_DEVICE_INTERFACE, "IsAliasSet"),
2809                         G_DBUS_CALL_FLAGS_NONE,
2810                         -1,
2811                         NULL,
2812                         &error);
2813
2814         if (!result) {
2815                 BT_ERR("Error occured in Proxy call");
2816                 if (error != NULL) {
2817                         BT_ERR("Getting is_alias_set property failed: [%s]\n", error->message);
2818                         g_error_free(error);
2819                 }
2820                 g_object_unref(device_proxy);
2821                 g_free(object_path);
2822                 return BLUETOOTH_ERROR_INTERNAL;
2823         }
2824
2825         g_variant_get(result, "(v)", &temp);
2826         alias_set = g_variant_get_boolean(temp);
2827         *is_alias_set = alias_set;
2828         BT_DBG("address: [%s] | *is_alias_set: %s", address, *is_alias_set ? "TRUE" : "FALSE");
2829         g_variant_unref(temp);
2830         g_variant_unref(result);
2831         g_object_unref(device_proxy);
2832
2833         g_free(object_path);
2834
2835         return BLUETOOTH_ERROR_NONE;
2836 }
2837
2838 int _bt_get_timeout_value(int *timeout)
2839 {
2840         time_t current_time;
2841         int time_diff;
2842
2843         /* Take current time */
2844         time(&current_time);
2845         time_diff = difftime(current_time, visible_timer.start_time);
2846
2847         BT_DBG("Time diff = %d\n", time_diff);
2848
2849         *timeout = visible_timer.timeout - time_diff;
2850
2851         return BLUETOOTH_ERROR_NONE;
2852 }
2853
2854 int _bt_set_le_privacy(gboolean set_privacy)
2855 {
2856         GDBusProxy *proxy;
2857         GError *error = NULL;
2858         GVariant *result = NULL;
2859
2860         if (__bt_is_factory_test_mode()) {
2861                 BT_ERR("Unable to set le privacy in factory binary !!");
2862                 return BLUETOOTH_ERROR_NOT_SUPPORT;
2863         }
2864
2865         if (_bt_adapter_get_status() != BT_ACTIVATED &&
2866                 _bt_adapter_get_le_status() != BT_LE_ACTIVATED) {
2867                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
2868         }
2869
2870         proxy = _bt_get_adapter_proxy();
2871         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2872
2873         result = g_dbus_proxy_call_sync(proxy,
2874                                 "SetLePrivacy",
2875                                 g_variant_new("(b)", set_privacy),
2876                                 G_DBUS_CALL_FLAGS_NONE,
2877                                 -1,
2878                                 NULL,
2879                                 &error);
2880
2881         if (!result) {
2882                 if (error != NULL) {
2883                         BT_ERR("Failed to SetLePrivacy (Error: %s)", error->message);
2884                         g_clear_error(&error);
2885                 } else
2886                         BT_ERR("Failed to SetLePrivacy");
2887                 return BLUETOOTH_ERROR_INTERNAL;
2888         }
2889
2890         g_variant_unref(result);
2891         BT_INFO("SetLePrivacy as %d", set_privacy);
2892         return BLUETOOTH_ERROR_NONE;
2893 }
2894
2895 int _bt_set_le_static_random_address(gboolean is_enable)
2896 {
2897         GDBusProxy *proxy;
2898         GError *error = NULL;
2899         GVariant *result = NULL;
2900
2901         if (__bt_is_factory_test_mode()) {
2902                 BT_ERR("Unable to set le random address in factory binary !!");
2903                 return BLUETOOTH_ERROR_NOT_SUPPORT;
2904         }
2905
2906         if (_bt_adapter_get_status() != BT_ACTIVATED &&
2907                 _bt_adapter_get_le_status() != BT_LE_ACTIVATED) {
2908                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
2909         }
2910
2911         proxy = _bt_get_adapter_proxy();
2912         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2913
2914         result = g_dbus_proxy_call_sync(proxy,
2915                                 "SetLeStaticRandomAddress",
2916                                 g_variant_new("(b)", is_enable),
2917                                 G_DBUS_CALL_FLAGS_NONE,
2918                                 -1,
2919                                 NULL,
2920                                 &error);
2921
2922         if (!result) {
2923                 if (error != NULL) {
2924                         BT_ERR("Failed to SetLeStaticRandomAddress (Error: %s)", error->message);
2925                         g_clear_error(&error);
2926                 } else
2927                         BT_ERR("Failed to SetLeStaticRandomAddress");
2928                 return BLUETOOTH_ERROR_INTERNAL;
2929         }
2930
2931         g_variant_unref(result);
2932         BT_INFO("SetLeStaticRandomAddress as %d", is_enable);
2933         return BLUETOOTH_ERROR_NONE;
2934 }
2935
2936 int _bt_set_manufacturer_data(bluetooth_manufacturer_data_t *m_data)
2937 {
2938         GDBusProxy *proxy;
2939         GError *error = NULL;
2940         int i;
2941         GVariant *val;
2942         GVariant *result;
2943         GVariantBuilder *builder;
2944
2945         BT_CHECK_PARAMETER(m_data, return);
2946
2947         if (_bt_adapter_get_status() != BT_ACTIVATED &&
2948                 _bt_adapter_get_le_status() != BT_LE_ACTIVATED) {
2949                 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
2950         }
2951
2952         proxy = _bt_get_adapter_proxy();
2953         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
2954
2955         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2956
2957         for (i = 0; i < (m_data->data_len) + 2; i++)
2958                 g_variant_builder_add(builder, "y", m_data->data[i]);
2959
2960         val = g_variant_new("(ay)", builder);
2961
2962         result = g_dbus_proxy_call_sync(proxy,
2963                                 "SetManufacturerData",
2964                                 val,
2965                                 G_DBUS_CALL_FLAGS_NONE,
2966                                 -1,
2967                                 NULL,
2968                                 &error);
2969         g_variant_builder_unref(builder);
2970         if (!result) {
2971                 if (error != NULL) {
2972                         BT_ERR("Failed to SetManufacturerData (Error: %s)", error->message);
2973                         g_clear_error(&error);
2974                 } else {
2975                         BT_ERR("Failed to SetManufacturerData");
2976                 }
2977                 return BLUETOOTH_ERROR_INTERNAL;
2978         }
2979         builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2980
2981         for (i = 0; i < (m_data->data_len) + 2; i++)
2982                 g_variant_builder_add(builder, "y", m_data->data[i]);
2983
2984         val = g_variant_new("(ay)", builder);
2985
2986         _bt_send_event(BT_ADAPTER_EVENT,
2987                         BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED,
2988                         val);
2989
2990         BT_INFO("Set manufacturer data");
2991
2992         g_variant_builder_unref(builder);
2993         g_variant_unref(result);
2994
2995         return BLUETOOTH_ERROR_NONE;
2996 }
2997
2998
2999 int _bt_service_set_alarm(int timeout, bt_set_alarm_cb call_back, void *user_data, alarm_id_t *alarm_id)
3000 {
3001         int result = BLUETOOTH_ERROR_NONE;
3002         bt_service_alarm_t *alarm = NULL;
3003
3004         if (!call_back || !alarm_id)
3005                 return BLUETOOTH_ERROR_INVALID_PARAM;
3006
3007         if (!alarm_mgr.is_alarm_initialized) {
3008                 result = alarmmgr_init("bt-service");
3009                 if (result != 0) {
3010                         BT_ERR("Failed to initialize alarm = %d", result);
3011                         result = BLUETOOTH_ERROR_INTERNAL;
3012                         goto finish;
3013                 }
3014                 result = alarmmgr_set_cb(alarm_cb, NULL);
3015                 if (result != 0) {
3016                         BT_ERR("Failed to set the callback = %d", result);
3017                         result = BLUETOOTH_ERROR_INTERNAL;
3018                         goto finish;
3019                 }
3020                 alarm_mgr.is_alarm_initialized = TRUE;
3021         }
3022
3023         alarm = g_malloc0(sizeof(bt_service_alarm_t));
3024         if (!alarm)
3025                 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
3026
3027         result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, timeout,
3028                                                 0, NULL, alarm_id);
3029         if (result != 0) {
3030                 BT_ERR("Failed to create alarm error = %d", result);
3031                 result = BLUETOOTH_ERROR_INTERNAL;
3032                 g_free(alarm);
3033                 goto finish;
3034         }
3035         alarm->alarm_id = *alarm_id;
3036         alarm->callback = call_back;
3037         alarm->user_data = user_data;
3038
3039         alarm_mgr.g_alarm_list = g_list_append(alarm_mgr.g_alarm_list, alarm);
3040         result = BLUETOOTH_ERROR_NONE;
3041 finish:
3042         return result;
3043 }
3044
3045 static int alarm_cb(alarm_id_t alarm_id, void* user_param)
3046 {
3047         GList *node = NULL;
3048         bt_service_alarm_t *p_data;
3049         bt_set_alarm_cb callback = NULL;
3050         void *user_data = NULL;
3051
3052         node = g_list_find_custom(alarm_mgr.g_alarm_list,
3053                         GINT_TO_POINTER(alarm_id), compare_alarm);
3054         if (!node)
3055                 return 0;
3056
3057         p_data = (bt_service_alarm_t *)node->data;
3058         alarm_mgr.g_alarm_list = g_list_delete_link(alarm_mgr.g_alarm_list,
3059                         node);
3060
3061         if (!p_data)
3062                 return 0;
3063
3064         callback = p_data->callback;
3065         user_data = p_data->user_data;
3066         g_free(p_data);
3067
3068         if (callback)
3069                 callback(alarm_id, user_data);
3070
3071         return 0;
3072 }
3073
3074 int _bt_service_remove_alarm(alarm_id_t alarm_id)
3075 {
3076         GList *list = NULL;
3077         bt_service_alarm_t *p_data;
3078         list = g_list_find_custom(alarm_mgr.g_alarm_list, GINT_TO_POINTER(alarm_id), compare_alarm);
3079
3080         if (list != NULL) {
3081                 alarmmgr_remove_alarm(alarm_id);
3082                 p_data = (bt_service_alarm_t *)list->data;
3083                 alarm_mgr.g_alarm_list = g_list_remove(alarm_mgr.g_alarm_list, list->data);
3084                 g_free(p_data);
3085         }
3086
3087         return 0;
3088 }
3089
3090 gint compare_alarm(gconstpointer list_data, gconstpointer data)
3091 {
3092 #ifdef ARCH64
3093         alarm_id_t alarm_id = (alarm_id_t)(uintptr_t)data;
3094 #else
3095         alarm_id_t alarm_id = (alarm_id_t)data;
3096 #endif
3097         bt_service_alarm_t *p_data = (bt_service_alarm_t *)list_data;
3098
3099         if (p_data->alarm_id == alarm_id)
3100                 return 0;
3101
3102         return 1;
3103 }
3104
3105 static void alarm_data_free(void *data)
3106 {
3107         bt_service_alarm_t *p_data = (bt_service_alarm_t *)data;
3108         g_free(p_data);
3109         return;
3110 }
3111
3112 static gboolean _bt_adapter_request_delayed_cb(gpointer user_data)
3113 {
3114         int result;
3115 #ifdef ARCH64
3116         int function = (int)(uintptr_t)user_data;
3117 #else
3118         int function = (int)user_data;
3119 #endif
3120
3121         switch (function) {
3122         case BT_ENABLE_ADAPTER:
3123                 result = _bt_enable_adapter();
3124                 if (result != BLUETOOTH_ERROR_NONE) {
3125                         BT_ERR("_bt_enable_adapter is failed");
3126                         /* Send enabled event to API */
3127                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED,
3128                                         g_variant_new("(i)", result));
3129                 }
3130                 break;
3131         case BT_DISABLE_ADAPTER:
3132                 result = _bt_disable_adapter();
3133                 if (result != BLUETOOTH_ERROR_NONE) {
3134                         BT_ERR("_bt_disable_adapter is failed");
3135                         /* Send disabled event to API */
3136                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED,
3137                                         g_variant_new("(i)", result));
3138                 }
3139                 break;
3140         default:
3141                 BT_ERR("function is NOT matched");
3142                 break;
3143         }
3144
3145         return FALSE;
3146 }
3147
3148 int _bt_adapter_request_delayed(int function)
3149 {
3150         int ret;
3151
3152         switch (function) {
3153         case BT_ENABLE_ADAPTER:
3154                 ret = _bt_enable_adapter_check_status();
3155                 if (ret == BLUETOOTH_ERROR_NONE)
3156                         _bt_adapter_set_status(BT_ACTIVATING);
3157                 else
3158                         return ret;
3159
3160                 break;
3161         case BT_DISABLE_ADAPTER:
3162                 ret = _bt_disable_adapter_check_status();
3163                 if (ret == BLUETOOTH_ERROR_NONE)
3164                         _bt_adapter_set_status(BT_DEACTIVATING);
3165                 else
3166                         return ret;
3167
3168                 break;
3169         default:
3170                 BT_ERR("function is NOT matched");
3171                 return BLUETOOTH_ERROR_INTERNAL;
3172         }
3173
3174 #ifdef ARCH64
3175         g_idle_add((GSourceFunc)_bt_adapter_request_delayed_cb, (void *)(uintptr_t)function);
3176 #else
3177         g_idle_add((GSourceFunc)_bt_adapter_request_delayed_cb, (void *)function);
3178 #endif
3179
3180         return BLUETOOTH_ERROR_NONE;
3181 }
3182
3183 int _bt_get_enable_timer_id(void)
3184 {
3185         return timer_id;
3186 }