[Boiler Plate] Update Boiler plate to remove unwanted information
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-common.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 <string.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <stdlib.h>
23 #include <sys/socket.h>
24
25
26 #include <gio/gunixfdlist.h>
27
28
29 #include "bluetooth-api.h"
30 #include "bluetooth-audio-api.h"
31 #include "bluetooth-hid-api.h"
32 #include "bluetooth-media-control.h"
33 #include "bt-internal-types.h"
34 #include "bluetooth-ipsp-api.h"
35
36 #include "bt-common.h"
37 #include "bt-request-sender.h"
38 #include "bt-event-handler.h"
39
40 static bt_user_info_t user_info[BT_MAX_USER_INFO];
41 static DBusConnection *system_conn = NULL;
42 static GDBusConnection *system_gdbus_conn = NULL;
43
44
45 static guint bus_id;
46
47 static GDBusConnection *system_gconn = NULL;
48
49 #define DBUS_TIMEOUT 20 * 1000 /* 20 Seconds */
50
51 GDBusConnection *g_bus_get_private_conn(void)
52 {
53         GError *error = NULL;
54         char *address;
55         GDBusConnection *private_gconn = NULL;
56
57         address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
58         if (address == NULL) {
59                 if (error) {
60                         BT_ERR ("Failed to get bus address: %s", error->message);
61                         g_clear_error(&error);
62                 }
63                 return NULL;
64         }
65
66         private_gconn = g_dbus_connection_new_for_address_sync (address,
67                                 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
68                                 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
69                                 NULL, /* GDBusAuthObserver */
70                                 NULL,
71                                 &error);
72         if (!private_gconn) {
73                 if (error) {
74                         BT_ERR("Unable to connect to dbus: %s", error->message);
75                         g_clear_error(&error);
76                 }
77                 return NULL;
78         }
79
80         return private_gconn;
81 }
82
83 GDBusConnection *_bt_gdbus_init_system_gconn(void)
84 {
85         dbus_threads_init_default();
86
87         g_type_init();
88
89         if (system_gconn != NULL)
90                 return system_gconn;
91
92         system_gconn = g_bus_get_private_conn();
93
94         return system_gconn;
95 }
96
97 GDBusConnection *_bt_gdbus_get_system_gconn(void)
98 {
99         if (system_gconn == NULL) {
100                 system_gconn = _bt_gdbus_init_system_gconn();
101         } else if (g_dbus_connection_is_closed(system_gconn)){
102                 system_gconn = g_bus_get_private_conn();
103         }
104
105         return system_gconn;
106 }
107
108 void _bt_print_device_address_t(const bluetooth_device_address_t *addr)
109 {
110         BT_DBG("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", addr->addr[0], addr->addr[1], addr->addr[2],
111                                 addr->addr[3], addr->addr[4], addr->addr[5]);
112 }
113
114 void _bt_set_user_data(int type, void *callback, void *user_data)
115 {
116         user_info[type].cb = callback;
117         user_info[type].user_data = user_data;
118 }
119
120 bt_user_info_t *_bt_get_user_data(int type)
121 {
122         return &user_info[type];
123 }
124
125 void _bt_common_event_cb(int event, int result, void *param,
126                                         void *callback, void *user_data)
127 {
128         bluetooth_event_param_t bt_event = { 0, };
129         bt_event.event = event;
130         bt_event.result = result;
131         bt_event.param_data = param;
132
133         if (callback)
134                 ((bluetooth_cb_func_ptr)callback)(bt_event.event, &bt_event,
135                                         user_data);
136 }
137
138 void _bt_input_event_cb(int event, int result, void *param,
139                                         void *callback, void *user_data)
140 {
141         hid_event_param_t bt_event = { 0, };
142         bt_event.event = event;
143         bt_event.result = result;
144         bt_event.param_data = param;
145
146         if (callback)
147                 ((hid_cb_func_ptr)callback)(bt_event.event, &bt_event,
148                                         user_data);
149 }
150
151 void _bt_headset_event_cb(int event, int result, void *param,
152                                         void *callback, void *user_data)
153 {
154         bt_audio_event_param_t bt_event = { 0, };
155         bt_event.event = event;
156         bt_event.result = result;
157         bt_event.param_data = param;
158
159         if (callback)
160                 ((bt_audio_func_ptr)callback)(bt_event.event, &bt_event,
161                                         user_data);
162 }
163
164 void _bt_a2dp_source_event_cb(int event, int result, void *param,
165                                         void *callback, void *user_data)
166 {
167         bt_audio_event_param_t bt_event = { 0, };
168         bt_event.event = event;
169         bt_event.result = result;
170         bt_event.param_data = param;
171         if (callback)
172                 ((bt_audio_func_ptr)callback)(bt_event.event, &bt_event,
173                                         user_data);
174 }
175
176 void _bt_hf_event_cb(int event, int result, void *param,
177                                         void *callback, void *user_data)
178 {
179         bt_hf_event_param_t bt_event = { 0, };
180         bt_event.event = event;
181         bt_event.result = result;
182         bt_event.param_data = param;
183
184         if (callback)
185                 ((bt_hf_func_ptr)callback)(bt_event.event, &bt_event,
186                                         user_data);
187 }
188
189
190 void _bt_avrcp_event_cb(int event, int result, void *param,
191                                         void *callback, void *user_data)
192 {
193         media_event_param_t bt_event = { 0, };
194         bt_event.event = event;
195         bt_event.result = result;
196         bt_event.param_data = param;
197
198         if (callback)
199                 ((media_cb_func_ptr)callback)(bt_event.event, &bt_event,
200                                         user_data);
201 }
202
203 void _bt_divide_device_class(bluetooth_device_class_t *device_class,
204                                 unsigned int cod)
205 {
206         ret_if(device_class == NULL);
207
208         device_class->major_class = (unsigned short)(cod & 0x00001F00) >> 8;
209         device_class->minor_class = (unsigned short)((cod & 0x000000FC));
210         device_class->service_class = (unsigned long)((cod & 0x00FF0000));
211
212         if (cod & 0x002000) {
213                 device_class->service_class |=
214                 BLUETOOTH_DEVICE_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE;
215         }
216 }
217
218 void _bt_convert_addr_string_to_type(unsigned char *addr,
219                                         const char *address)
220 {
221         int i;
222         char *ptr = NULL;
223
224         ret_if(address == NULL);
225         ret_if(addr == NULL);
226
227         for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) {
228                 addr[i] = strtol(address, &ptr, 16);
229                 if (ptr[0] != '\0') {
230                         if (ptr[0] != ':')
231                                 return;
232
233                         address = ptr + 1;
234                 }
235         }
236 }
237
238 void _bt_convert_addr_type_to_string(char *address,
239                                 unsigned char *addr)
240 {
241         ret_if(address == NULL);
242         ret_if(addr == NULL);
243
244         g_snprintf(address, BT_ADDRESS_STRING_SIZE,
245                         "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
246                         addr[0], addr[1], addr[2],
247                         addr[3], addr[4], addr[5]);
248 }
249
250 int _bt_copy_utf8_string(char *dest, const char *src, unsigned int length)
251 {
252         int i;
253         const char *p = src;
254         char *next;
255         int count;
256
257         if (dest == NULL || src == NULL)
258                 return BLUETOOTH_ERROR_INVALID_PARAM;
259
260         i = 0;
261         while (*p != '\0' && i < length) {
262                 next = g_utf8_next_char(p);
263                 count = next - p;
264
265                 while (count > 0 && ((i + count) < length)) {
266                         dest[i++] = *p;
267                         p++;
268                         count --;
269                 }
270                 p = next;
271         }
272         return BLUETOOTH_ERROR_NONE;
273 }
274
275 gboolean _bt_utf8_validate(char *name)
276 {
277         BT_DBG("+");
278         gunichar2 *u16;
279         glong items_written = 0;
280
281         if (FALSE == g_utf8_validate(name, -1, NULL))
282                 return FALSE;
283
284         u16 = g_utf8_to_utf16(name, -1, NULL, &items_written, NULL);
285         if (u16 == NULL)
286                 return FALSE;
287
288         g_free(u16);
289
290         if (items_written != g_utf8_strlen(name, -1))
291                 return FALSE;
292
293         BT_DBG("-");
294         return TRUE;
295 }
296
297
298 static GDBusProxy *profile_gproxy;
299 static GDBusConnection *gconn;
300 static int latest_id = -1;
301 #define BT_RFCOMM_ID_MAX 245
302 static gboolean id_used[BT_RFCOMM_ID_MAX];
303 GDBusNodeInfo *new_conn_node;
304
305 static const gchar rfcomm_agent_xml[] =
306 "<node name='/'>"
307 " <interface name='org.bluez.Profile1'>"
308 "     <method name='NewConnection'>"
309 "          <arg type='o' name='object' direction='in'/>"
310 "          <arg type='h' name='fd' direction='in'/>"
311 "          <arg type='a{sv}' name='properties' direction='in'/>"
312 "     </method>"
313 "     <method name='RequestDisconnection'>"
314 "          <arg type='o' name='device' direction='in'/>"
315 "     </method>"
316 "  </interface>"
317 "</node>";
318
319 static void __new_connection_method(GDBusConnection *connection,
320                                             const gchar *sender,
321                                             const gchar *object_path,
322                                             const gchar *interface_name,
323                                             const gchar *method_name,
324                                             GVariant *parameters,
325                                             GDBusMethodInvocation *invocation,
326                                             gpointer user_data)
327 {
328         BT_DBG("method %s", method_name);
329         if (g_strcmp0(method_name, "NewConnection") == 0) {
330                 int index;
331                 GDBusMessage *msg;
332                 GUnixFDList *fd_list;
333                 GVariantBuilder *properties;
334                 char *obj_path;
335                 char addr[20];
336                 bluetooth_device_address_t  remote_addr1;
337                 bt_new_connection_cb cb = user_data;
338                 int fd;
339
340                 g_variant_get(parameters, "(oha{sv})", &obj_path, &index,
341                                                                 &properties);
342
343                 msg = g_dbus_method_invocation_get_message(invocation);
344                 fd_list = g_dbus_message_get_unix_fd_list(msg);
345                 if (fd_list == NULL) {
346                         GQuark quark = g_quark_from_string("rfcomm-app");
347                         GError *err = g_error_new(quark, 0, "No fd in message");
348                         g_dbus_method_invocation_return_gerror(invocation, err);
349                         g_error_free(err);
350                         return;
351                 }
352
353
354                 fd = g_unix_fd_list_get(fd_list, index, NULL);
355                 if (fd == -1) {
356                         BT_ERR("Invalid fd return");
357                         GQuark quark = g_quark_from_string("rfcomm-app");
358                         GError *err = g_error_new(quark, 0, "Invalid FD return");
359                         g_dbus_method_invocation_return_gerror(invocation, err);
360                         g_error_free(err);
361                         return;
362                 }
363                 BT_INFO("Object Path %s", obj_path);
364
365                 _bt_device_path_to_address(obj_path, addr);
366                 _bt_convert_addr_string_to_type(remote_addr1.addr, (const char *)addr);
367                 BT_INFO("fd: %d, address %s", fd, addr);
368
369                 g_dbus_method_invocation_return_value(invocation, NULL);
370
371                 if (cb)
372                         cb(object_path, fd, &remote_addr1);
373         } else if (g_strcmp0(method_name, "RequestDisconnection") == 0) {
374                 g_dbus_method_invocation_return_value(invocation, NULL);
375         }
376 }
377
378
379 static const GDBusInterfaceVTable method_table = {
380         __new_connection_method,
381         NULL,
382         NULL,
383 };
384
385 void _bt_swap_addr(unsigned char *dst, const unsigned char *src)
386 {
387         int i;
388
389         for (i = 0; i < 6; i++)
390                 dst[i] = src[5-i];
391 }
392
393 int __rfcomm_assign_id(void)
394 {
395         int index;
396
397         BT_DBG("latest_id: %d", latest_id);
398
399         index = latest_id + 1;
400
401         if (index >= BT_RFCOMM_ID_MAX)
402                 index = 0;
403
404         BT_DBG("index: %d", index);
405
406         while (id_used[index] == TRUE) {
407                 if (index == latest_id) {
408                         /* No available ID */
409                         BT_ERR("All request ID is used");
410                         return -1;
411                 }
412
413                 index++;
414
415                 if (index >= BT_RFCOMM_ID_MAX)
416                         index = 0;
417         }
418
419         latest_id = index;
420         id_used[index] = TRUE;
421
422         BT_DBG("Assigned Id: %d", latest_id);
423
424         return latest_id;
425 }
426
427 void __rfcomm_delete_id(int id)
428 {
429         ret_if(id >= BT_RFCOMM_ID_MAX);
430         ret_if(id < 0);
431
432         id_used[id] = FALSE;
433
434         /* Next server will use this ID */
435         latest_id = id - 1;
436 }
437
438 static GDBusConnection *__get_gdbus_connection()
439 {
440         if (gconn == NULL)
441                 gconn = g_bus_get_private_conn();
442
443         return gconn;
444 }
445
446 static GDBusProxy *__bt_gdbus_get_profile_proxy(void)
447 {
448         GDBusConnection *gconn;
449         GError *err = NULL;
450
451         if (profile_gproxy)
452                 return profile_gproxy;
453
454         gconn = __get_gdbus_connection();
455         if (gconn == NULL)
456                 return NULL;
457
458         profile_gproxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE,
459                                                 NULL, BT_BLUEZ_NAME,
460                                                 "/org/bluez",
461                                                 "org.bluez.ProfileManager1",
462                                                 NULL, &err);
463         if (err) {
464                 BT_ERR("Unable to create proxy: %s", err->message);
465                 g_clear_error(&err);
466                 return NULL;
467         }
468
469         return profile_gproxy;
470 }
471
472 static GDBusProxy *__bt_gdbus_get_device_proxy(char *object_path)
473 {
474         GDBusConnection *gconn;
475         GError *err = NULL;
476         GDBusProxy *device_gproxy;
477
478         gconn = __get_gdbus_connection();
479         if (gconn == NULL)
480                 return NULL;
481
482         device_gproxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE,
483                                                 NULL, BT_BLUEZ_NAME,
484                                                 object_path,
485                                                 BT_DEVICE_INTERFACE,
486                                                 NULL, &err);
487
488         if (err) {
489                 BT_ERR("Unable to create proxy: %s", err->message);
490                 g_clear_error(&err);
491                 return NULL;
492         }
493
494         return device_gproxy;
495 }
496
497 void _bt_unregister_gdbus(int object_id)
498 {
499         GDBusConnection *gconn;
500
501         gconn = __get_gdbus_connection();
502         if (gconn == NULL)
503                 return;
504
505         g_dbus_connection_unregister_object(gconn, object_id);
506 }
507
508 int _bt_register_new_conn(const char *path, bt_new_connection_cb cb)
509 {
510         GDBusConnection *gconn;
511         int id;
512         GError *error = NULL;
513
514         gconn = __get_gdbus_connection();
515         if (gconn == NULL)
516                 return -1;
517
518         if (new_conn_node == NULL)
519                 new_conn_node = _bt_get_gdbus_node(rfcomm_agent_xml);
520
521         if (new_conn_node == NULL)
522                 return -1;
523
524         id = g_dbus_connection_register_object(gconn, path,
525                                                 new_conn_node->interfaces[0],
526                                                 &method_table,
527                                                 cb, NULL, &error);
528         if (id == 0) {
529                 BT_ERR("Failed to register: %s", error->message);
530                 g_error_free(error);
531                 return -1;
532         }
533
534         BT_DBG("NEW CONNECTION ID %d", id);
535
536         return id;
537 }
538
539 static GDBusProxy * __bt_gdbus_get_adapter_proxy()
540 {
541         GError *err = NULL;
542         GDBusProxy *manager_proxy = NULL;
543         GDBusProxy *adapter_proxy = NULL;
544         GDBusConnection *conn;
545         GVariant *result = NULL;
546         char *adapter_path = NULL;
547
548         conn = __get_gdbus_connection();
549         retv_if(conn == NULL, NULL);
550
551         manager_proxy =  g_dbus_proxy_new_sync(conn,
552                         G_DBUS_PROXY_FLAGS_NONE, NULL,
553                         BT_BLUEZ_NAME,
554                         BT_MANAGER_PATH,
555                         BT_MANAGER_INTERFACE,
556                         NULL, &err);
557
558         if (!manager_proxy) {
559                 BT_ERR("Unable to create proxy: %s", err->message);
560                 goto fail;
561         }
562
563         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
564                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
565         if (!result) {
566                 if (err != NULL)
567                         BT_ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
568                 else
569                         BT_ERR("Fail to get DefaultAdapter");
570
571                 goto fail;
572         }
573
574         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
575                 BT_ERR("Incorrect result\n");
576                 goto fail;
577         }
578
579         g_variant_get(result, "(&o)", &adapter_path);
580
581         if (adapter_path == NULL ||
582                 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
583                 BT_ERR("Adapter path is inproper\n");
584                 goto fail;
585         }
586
587         BT_INFO("Adapter Path %s", adapter_path);
588
589         adapter_proxy = g_dbus_proxy_new_sync(conn,
590                                         G_DBUS_PROXY_FLAGS_NONE, NULL,
591                                         BT_BLUEZ_NAME,
592                                         adapter_path,
593                                         BT_ADAPTER_INTERFACE,
594                                         NULL, &err);
595         if (err) {
596                 BT_ERR("DBus Error message: [%s]", err->message);
597                 g_clear_error(&err);
598         }
599
600 fail:
601         if (manager_proxy)
602                 g_object_unref(manager_proxy);
603         if (result)
604                 g_variant_unref(result);
605         return adapter_proxy;
606 }
607
608 int _bt_register_new_conn_ex(const char *path, const char *bus_name,bt_new_connection_cb cb)
609 {
610         GDBusConnection *gconn;
611         int id;
612         GError *error = NULL;
613
614         gconn = __get_gdbus_connection();
615         if (gconn == NULL)
616                 return -1;
617
618         if (new_conn_node == NULL)
619                 new_conn_node = _bt_get_gdbus_node_ex(rfcomm_agent_xml, bus_name);
620
621         if (new_conn_node == NULL)
622                 return -1;
623
624         id = g_dbus_connection_register_object(gconn, path,
625                                                 new_conn_node->interfaces[0],
626                                                 &method_table,
627                                                 cb, NULL, &error);
628         if (id == 0) {
629                 BT_ERR("Failed to register: %s", error->message);
630                 g_error_free(error);
631                 return -1;
632         }
633
634         BT_DBG("NEW CONNECTION ID %d", id);
635
636         return id;
637 }
638
639 int _bt_register_profile(bt_register_profile_info_t *info, gboolean use_default_rfcomm)
640 {
641         GVariantBuilder *option_builder;
642         GVariant *ret;
643         GDBusProxy *proxy;
644         GError *err = NULL;
645         int result = BLUETOOTH_ERROR_NONE;
646
647         proxy = __bt_gdbus_get_profile_proxy();
648         if (proxy == NULL) {
649                 BT_ERR("Getting profile proxy failed");
650                 return BLUETOOTH_ERROR_INTERNAL;
651         }
652
653         option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
654         if (info->authentication)
655                 g_variant_builder_add(option_builder, "{sv}",
656                                                 "RequireAuthentication",
657                                                 g_variant_new_boolean(TRUE));
658         if (info->authorization)
659                 g_variant_builder_add(option_builder, "{sv}",
660                                                 "RequireAuthorization",
661                                                 g_variant_new_boolean(TRUE));
662         if (info->role)
663                 g_variant_builder_add(option_builder, "{sv}",
664                                                 "Role",
665                                                 g_variant_new_string(info->role));
666
667         /* Setting RFCOMM channel to default value 0; would allow bluez to assign
668          * RFCOMM channels based on the availability when two services want
669          * to use the RFCOMM along with SPP. Hence bluez makes sure that no
670          * two services use the same SPP RFCOMM channel. */
671         if (use_default_rfcomm)
672                 g_variant_builder_add(option_builder, "{sv}",
673                                                 "Channel",
674                                                 g_variant_new_uint16(RFCOMM_DEFAULT_PROFILE_CHANNEL));
675         if (info->service)
676                 g_variant_builder_add(option_builder, "{sv}",
677                                                 "Service",
678                                                 g_variant_new_string(info->service));
679
680         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
681                                         g_variant_new("(osa{sv})", info->obj_path,
682                                                                 info->uuid,
683                                                                 option_builder),
684                                         G_DBUS_CALL_FLAGS_NONE, -1,
685                                         NULL, &err);
686         if (err) {
687                 g_dbus_error_strip_remote_error(err);
688                 BT_ERR("RegisterProfile failed: %s", err->message);
689
690                 if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
691                         result = BLUETOOTH_ERROR_ACCESS_DENIED;
692                 else
693                         result = BLUETOOTH_ERROR_INTERNAL;
694
695                 g_clear_error(&err);
696         }
697
698         g_variant_builder_unref(option_builder);
699
700         if (ret)
701                 g_variant_unref(ret);
702
703         return result;
704 }
705
706 int _bt_register_profile_ex(bt_register_profile_info_t *info, gboolean use_default_rfcomm, const char *name, const char *path)
707 {
708         GVariantBuilder *option_builder;
709         GVariant *ret;
710         GDBusProxy *proxy;
711         GError *err = NULL;
712         int result = BLUETOOTH_ERROR_NONE;
713
714         proxy = __bt_gdbus_get_profile_proxy();
715         if (proxy == NULL) {
716                 BT_ERR("Getting profile proxy failed");
717                 return BLUETOOTH_ERROR_INTERNAL;
718         }
719
720         option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
721         if (info->authentication)
722                 g_variant_builder_add(option_builder, "{sv}",
723                                                 "RequireAuthentication",
724                                                 g_variant_new_boolean(TRUE));
725         if (info->authorization)
726                 g_variant_builder_add(option_builder, "{sv}",
727                                                 "RequireAuthorization",
728                                                 g_variant_new_boolean(TRUE));
729         if (info->role)
730                 g_variant_builder_add(option_builder, "{sv}",
731                                                 "Role",
732                                                 g_variant_new_string(info->role));
733
734         /* Setting RFCOMM channel to default value 0; would allow bluez to assign
735          * RFCOMM channels based on the availability when two services want
736          * to use the RFCOMM along with SPP. Hence bluez makes sure that no
737          * two services use the same SPP RFCOMM channel. */
738         if (use_default_rfcomm)
739                 g_variant_builder_add(option_builder, "{sv}",
740                                                 "Channel",
741                                                 g_variant_new_uint16(RFCOMM_DEFAULT_PROFILE_CHANNEL));
742         if (info->service)
743                 g_variant_builder_add(option_builder, "{sv}",
744                                                 "Service",
745                                                 g_variant_new_string(info->service));
746
747         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile2",
748                                         g_variant_new("(osssa{sv})", info->obj_path,
749                                                                 info->uuid,
750                                                                 name,
751                                                                 path,
752                                                                 option_builder),
753                                         G_DBUS_CALL_FLAGS_NONE, -1,
754                                         NULL, &err);
755         if (err) {
756                 g_dbus_error_strip_remote_error(err);
757                 BT_ERR("RegisterProfile failed: %s", err->message);
758
759                 if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
760                         result = BLUETOOTH_ERROR_ACCESS_DENIED;
761                 else
762                         result = BLUETOOTH_ERROR_INTERNAL;
763
764                 g_clear_error(&err);
765         }
766
767         g_variant_builder_unref(option_builder);
768
769         if (ret)
770                 g_variant_unref(ret);
771
772         return result;
773 }
774
775 int _bt_register_profile_platform(bt_register_profile_info_t *info, gboolean use_default_rfcomm)
776 {
777         GVariantBuilder *option_builder;
778         GVariant *ret;
779         GDBusProxy *proxy;
780         GError *err = NULL;
781         int result = BLUETOOTH_ERROR_NONE;
782
783         proxy = __bt_gdbus_get_profile_proxy();
784         if (proxy == NULL) {
785                 BT_ERR("Getting profile proxy failed");
786                 return BLUETOOTH_ERROR_INTERNAL;
787         }
788
789         option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
790         if (info->authentication)
791                 g_variant_builder_add(option_builder, "{sv}",
792                                                 "RequireAuthentication",
793                                                 g_variant_new_boolean(TRUE));
794         if (info->authorization)
795                 g_variant_builder_add(option_builder, "{sv}",
796                                                 "RequireAuthorization",
797                                                 g_variant_new_boolean(TRUE));
798         if (info->role)
799                 g_variant_builder_add(option_builder, "{sv}",
800                                                 "Role",
801                                                 g_variant_new_string(info->role));
802
803         /* Setting RFCOMM channel to default value 0; would allow bluez to assign
804          * RFCOMM channels based on the availability when two services want
805          * to use the RFCOMM along with SPP. Hence bluez makes sure that no
806          * two services use the same SPP RFCOMM channel. */
807         if (use_default_rfcomm)
808                 g_variant_builder_add(option_builder, "{sv}",
809                                                 "Channel",
810                                                 g_variant_new_uint16(RFCOMM_DEFAULT_PROFILE_CHANNEL));
811         if (info->service)
812                 g_variant_builder_add(option_builder, "{sv}",
813                                                 "Service",
814                                                 g_variant_new_string(info->service));
815
816         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile1",
817                                         g_variant_new("(osa{sv})", info->obj_path,
818                                                                 info->uuid,
819                                                                 option_builder),
820                                         G_DBUS_CALL_FLAGS_NONE, -1,
821                                         NULL, &err);
822
823         if (err) {
824                 g_dbus_error_strip_remote_error(err);
825                 BT_ERR("RegisterProfile failed: %s", err->message);
826
827                 if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG))
828                         result = BLUETOOTH_ERROR_ACCESS_DENIED;
829                 else
830                         result = BLUETOOTH_ERROR_INTERNAL;
831
832                 g_clear_error(&err);
833         }
834
835         g_variant_builder_unref(option_builder);
836
837         if (ret)
838                 g_variant_unref(ret);
839
840         return result;
841 }
842
843
844 void _bt_unregister_profile(char *path)
845 {
846         GVariant *ret;
847         GDBusProxy *proxy;
848         GError *err = NULL;
849
850         proxy = __bt_gdbus_get_profile_proxy();
851         if (proxy == NULL) {
852                 BT_ERR("Getting profile proxy failed");
853                 return;
854         }
855
856         ret = g_dbus_proxy_call_sync(proxy, "UnregisterProfile",
857                         g_variant_new("(o)", path),
858                         G_DBUS_CALL_FLAGS_NONE, -1,
859                         NULL, &err);
860         if (err) {
861                 BT_ERR("UnregisterProfile failed : %s", err->message);
862                 g_clear_error(&err);
863         }
864
865         if (ret)
866                 g_variant_unref(ret);
867
868         return;
869 }
870
871 GDBusNodeInfo * _bt_get_gdbus_node(const gchar *xml_data)
872 {
873         if (bus_id == 0) {
874                 char *name = g_strdup_printf("org.bt.frwk%d", getpid());
875
876                 bus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
877                                                 name,
878                                                 G_BUS_NAME_OWNER_FLAGS_NONE,
879                                                 NULL,
880                                                 NULL,
881                                                 NULL,
882                                                 NULL,
883                                                 NULL);
884                 BT_DBG("Got bus id %d", bus_id);
885                 g_free(name);
886         }
887
888         return g_dbus_node_info_new_for_xml(xml_data, NULL);
889 }
890
891 GDBusNodeInfo * _bt_get_gdbus_node_ex(const gchar *xml_data, const char *bus_name)
892 {
893         if (bus_id == 0) {
894                 char *name = g_strdup(bus_name);
895                 bus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
896                                                 name,
897                                                 G_BUS_NAME_OWNER_FLAGS_NONE,
898                                                 NULL,
899                                                 NULL,
900                                                 NULL,
901                                                 NULL,
902                                                 NULL);
903                 BT_DBG("Got bus id %d", bus_id);
904                 g_free(name);
905         }
906
907         return g_dbus_node_info_new_for_xml(xml_data, NULL);
908 }
909
910 int _bt_connect_profile(char *address, char *uuid, void *cb,
911                                                         gpointer func_data)
912 {
913         GDBusProxy *proxy;
914         GDBusProxy *adapter_proxy;
915         char *object_path;
916         GError *err = NULL;
917
918         object_path = _bt_get_device_object_path(address);
919
920         if (object_path == NULL) {
921                 GVariant *ret = NULL;
922                 BT_ERR("No searched device");
923                 adapter_proxy = __bt_gdbus_get_adapter_proxy();
924
925                 if (adapter_proxy == NULL) {
926                         BT_ERR("adapter proxy is NULL");
927                         return BLUETOOTH_ERROR_INTERNAL;
928                 }
929
930                 ret = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
931                                 g_variant_new("(s)", address),
932                                 G_DBUS_CALL_FLAGS_NONE,
933                                 DBUS_TIMEOUT, NULL,
934                                 &err);
935
936                 if (err != NULL) {
937                         BT_ERR("CreateDevice Failed: %s", err->message);
938                         g_clear_error(&err);
939                 }
940                 if (ret)
941                         g_variant_unref(ret);
942                 g_object_unref(adapter_proxy);
943                 object_path = _bt_get_device_object_path(address);
944
945                 if (object_path == NULL)
946                         return BLUETOOTH_ERROR_INTERNAL;
947         }
948
949         proxy = __bt_gdbus_get_device_proxy(object_path);
950         g_free(object_path);
951
952         if (proxy == NULL) {
953                 BT_ERR("Error while getting proxy");
954                 return BLUETOOTH_ERROR_INTERNAL;
955         }
956
957         g_dbus_proxy_call(proxy, "ConnectProfile",
958                         g_variant_new("(s)", uuid),
959                         G_DBUS_CALL_FLAGS_NONE,
960                         DBUS_TIMEOUT, NULL,
961                         (GAsyncReadyCallback)cb,
962                         func_data);
963         BT_DBG("-");
964         return BLUETOOTH_ERROR_NONE;
965 }
966
967 int _bt_discover_services(char *address, char *uuid, void *cb,
968                 gpointer func_data)
969 {
970         char *object_path;
971         GDBusProxy *proxy;
972         GDBusProxy *adapter_proxy;
973         GError *err = NULL;
974         object_path = _bt_get_device_object_path(address);
975         if (object_path == NULL) {
976                 GVariant *ret = NULL;
977                 BT_ERR("No searched device");
978                 adapter_proxy = __bt_gdbus_get_adapter_proxy();
979                 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
980                 ret = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
981                                 g_variant_new("(s)", address),
982                                 G_DBUS_CALL_FLAGS_NONE,
983                                 DBUS_TIMEOUT, NULL,
984                                 &err);
985                 if (err != NULL) {
986                         BT_ERR("CreateDevice Failed: %s", err->message);
987                         g_clear_error(&err);
988                 }
989                 if (ret)
990                         g_variant_unref(ret);
991
992                 g_object_unref(adapter_proxy);
993
994                 object_path = _bt_get_device_object_path(address);
995                 if (object_path == NULL)
996                         return BLUETOOTH_ERROR_INTERNAL;
997         }
998         proxy = __bt_gdbus_get_device_proxy(object_path);
999         g_free(object_path);
1000         if (proxy == NULL) {
1001                 BT_ERR("Error while getting proxy");
1002                 return BLUETOOTH_ERROR_INTERNAL;
1003         }
1004         g_dbus_proxy_call(proxy, "DiscoverServices",
1005                         g_variant_new("(s)", uuid),
1006                         G_DBUS_CALL_FLAGS_NONE,
1007                         DBUS_TIMEOUT, NULL,
1008                         (GAsyncReadyCallback)cb,
1009                         func_data);
1010         BT_DBG("-");
1011         return BLUETOOTH_ERROR_NONE;
1012 }
1013
1014 int _bt_cancel_discovers(char *address)
1015 {
1016         char *object_path;
1017         GDBusProxy *proxy;
1018         GDBusProxy *adapter_proxy;
1019         GError *err = NULL;
1020         object_path = _bt_get_device_object_path(address);
1021         if (object_path == NULL) {
1022                 GVariant *ret = NULL;
1023                 BT_ERR("No searched device");
1024                 adapter_proxy = __bt_gdbus_get_adapter_proxy();
1025                 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1026                 ret = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
1027                                 g_variant_new("(s)", address),
1028                                 G_DBUS_CALL_FLAGS_NONE,
1029                                 DBUS_TIMEOUT, NULL,
1030                                 &err);
1031                 if (err != NULL) {
1032                         BT_ERR("CreateDevice Failed: %s", err->message);
1033                         g_clear_error(&err);
1034                 }
1035                 if (ret)
1036                         g_variant_unref(ret);
1037
1038                 g_object_unref(adapter_proxy);
1039
1040                 object_path = _bt_get_device_object_path(address);
1041                 if (object_path == NULL)
1042                         return BLUETOOTH_ERROR_INTERNAL;
1043         }
1044         proxy = __bt_gdbus_get_device_proxy(object_path);
1045         g_free(object_path);
1046         g_dbus_proxy_call_sync(proxy, "CancelDiscovery",
1047                 NULL,
1048                 G_DBUS_CALL_FLAGS_NONE,
1049                 DBUS_TIMEOUT, NULL,
1050                 &err);
1051         if (err) {
1052                 BT_ERR("DBus Error message: [%s]", err->message);
1053                 g_clear_error(&err);
1054                 return BLUETOOTH_ERROR_INTERNAL;
1055         }
1056         if (proxy)
1057                 g_object_unref(proxy);
1058         return BLUETOOTH_ERROR_NONE;
1059 }
1060
1061 int _bt_discover_service_uuids(char *address, char *remote_uuid)
1062 {
1063         char *object_path;
1064         GDBusProxy *proxy;
1065         GDBusConnection *gconn;
1066         GError *err = NULL;
1067         char **uuid_value = NULL;
1068         gsize size = 0;
1069         int i =0;
1070         GVariant *value = NULL;
1071         GVariant *ret = NULL;
1072         int result = BLUETOOTH_ERROR_INTERNAL;
1073         BT_INFO("+");
1074         retv_if(remote_uuid == NULL, BLUETOOTH_ERROR_INTERNAL);
1075         gconn = __get_gdbus_connection();
1076         retv_if(gconn == NULL, BLUETOOTH_ERROR_INTERNAL);
1077         object_path = _bt_get_device_object_path(address);
1078         retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL);
1079
1080         proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1081                                 BT_BLUEZ_NAME, object_path, BT_PROPERTIES_INTERFACE, NULL,
1082                                 &err);
1083         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1084         if (err) {
1085                 BT_ERR("DBus Error: [%s]", err->message);
1086                 g_clear_error(&err);
1087         }
1088         ret = g_dbus_proxy_call_sync(proxy, "GetAll",
1089                         g_variant_new("(s)", BT_DEVICE_INTERFACE),
1090                         G_DBUS_CALL_FLAGS_NONE,
1091                         DBUS_TIMEOUT, NULL,
1092                         &err);
1093         if (err) {
1094                 result = BLUETOOTH_ERROR_INTERNAL;
1095                 BT_ERR("DBus Error : %s", err->message);
1096                 g_clear_error(&err);
1097                 goto done;
1098         }
1099         if (ret == NULL) {
1100                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
1101                 result = BLUETOOTH_ERROR_INTERNAL;
1102                 goto done;
1103         }
1104
1105         g_variant_get(ret, "(@a{sv})", &value);
1106         g_variant_unref(ret);
1107         if (value) {
1108                 GVariant *temp_value = g_variant_lookup_value(value, "UUIDs",
1109                         G_VARIANT_TYPE_STRING_ARRAY);
1110
1111                 if (temp_value) {
1112                         size = g_variant_get_size(temp_value);
1113                         if (size > 0) {
1114                                 uuid_value = (char **)g_variant_get_strv(temp_value, &size);
1115                                 BT_DBG("Size items %d", size);
1116
1117                                 if (uuid_value) {
1118                                         for (i = 0; uuid_value[i] != NULL; i++) {
1119                                                 BT_DBG("Remote uuids %s", uuid_value[i]);
1120                                                 if (strcasecmp(uuid_value[i], remote_uuid) == 0) {
1121                                                         result = BLUETOOTH_ERROR_NONE;
1122                                                         g_variant_unref(temp_value);
1123                                                         goto done;
1124                                                 }
1125                                         }
1126                                 }
1127                         }
1128                         g_variant_unref(temp_value);
1129                 }
1130         }
1131 done:
1132         if (proxy)
1133                 g_object_unref(proxy);
1134         if (value)
1135                 g_variant_unref(value);
1136         if (uuid_value)
1137                 g_free(uuid_value);
1138
1139         BT_DBG("-");
1140         return result;
1141 }
1142
1143 int _bt_get_cod_by_address(char *address, bluetooth_device_class_t *dev_class)
1144 {
1145         char *object_path;
1146         GDBusProxy *proxy;
1147         GDBusConnection *gconn;
1148         GError *err = NULL;
1149         GVariant *value = NULL;
1150         GVariant *result = NULL;
1151         unsigned int  class = 0x00;
1152         int ret = BLUETOOTH_ERROR_INTERNAL;
1153
1154         gconn = __get_gdbus_connection();
1155         retv_if(gconn == NULL, BLUETOOTH_ERROR_INTERNAL);
1156                 object_path = _bt_get_device_object_path(address);
1157
1158         retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL);
1159
1160         proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1161                                 BT_BLUEZ_NAME, object_path, BT_PROPERTIES_INTERFACE, NULL,
1162                                 &err);
1163         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1164         if (err) {
1165                 BT_ERR("DBus Error: [%s]", err->message);
1166                 g_clear_error(&err);
1167         }
1168
1169         result = g_dbus_proxy_call_sync(proxy, "GetAll",
1170                         g_variant_new("(s)", BT_DEVICE_INTERFACE),
1171                         G_DBUS_CALL_FLAGS_NONE,
1172                         DBUS_TIMEOUT, NULL,
1173                         &err);
1174         if (err) {
1175                 ret = BLUETOOTH_ERROR_INTERNAL;
1176                 BT_ERR("DBus Error : %s", err->message);
1177                 g_clear_error(&err);
1178                 goto done;
1179         }
1180         if (result == NULL) {
1181                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
1182                 ret = BLUETOOTH_ERROR_INTERNAL;
1183                 goto done;
1184         }
1185         g_variant_get(result, "(@a{sv})", &value);
1186         g_variant_unref(result);
1187         if (value) {
1188                 GVariant *temp_value = g_variant_lookup_value(value, "Class",
1189                         G_VARIANT_TYPE_UINT32);
1190                 class = g_variant_get_uint32(temp_value);
1191                 _bt_divide_device_class(dev_class, class);
1192                 if (temp_value)
1193                         g_variant_unref(temp_value);
1194         }
1195
1196 done:
1197         if (proxy)
1198                 g_object_unref(proxy);
1199         if (value)
1200                 g_variant_unref(value);
1201
1202         BT_DBG("-");
1203         return ret;
1204 }
1205
1206 int _bt_disconnect_profile(char *address, char *uuid, void *cb,
1207                                                         gpointer func_data)
1208 {
1209         GDBusProxy *proxy;
1210         char *object_path;
1211         GError *err = NULL;
1212         GDBusProxy *adapter_proxy;
1213         object_path = _bt_get_device_object_path(address);
1214         if (object_path == NULL) {
1215                 GVariant *ret = NULL;
1216                 BT_ERR("No searched device");
1217                 adapter_proxy = __bt_gdbus_get_adapter_proxy();
1218                 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1219                 ret = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
1220                                 g_variant_new("(s)", address),
1221                                 G_DBUS_CALL_FLAGS_NONE,
1222                                 DBUS_TIMEOUT, NULL,
1223                                 &err);
1224                 if (err != NULL) {
1225                         BT_ERR("CreateDevice Failed: %s", err->message);
1226                         g_error_free(err);
1227                 }
1228                 if (ret)
1229                         g_variant_unref(ret);
1230                 g_object_unref(adapter_proxy);
1231                 object_path = _bt_get_device_object_path(address);
1232                 if (object_path == NULL)
1233                         return BLUETOOTH_ERROR_INTERNAL;
1234         }
1235         proxy = __bt_gdbus_get_device_proxy(object_path);
1236         g_free(object_path);
1237         if (proxy == NULL) {
1238                 BT_ERR("Error while getting proxy");
1239                 return BLUETOOTH_ERROR_INTERNAL;
1240         }
1241         g_dbus_proxy_call(proxy, "DisconnectProfile",
1242                         g_variant_new("(s)", uuid),
1243                         G_DBUS_CALL_FLAGS_NONE,
1244                         DBUS_TIMEOUT, NULL,
1245                         (GAsyncReadyCallback)cb,
1246                         func_data);
1247         BT_DBG("-");
1248         return BLUETOOTH_ERROR_NONE;
1249 }
1250
1251 int _bt_get_adapter_path(GDBusConnection *conn, char *path)
1252 {
1253         GError *err = NULL;
1254         GDBusProxy *manager_proxy = NULL;
1255         GVariant *result = NULL;
1256         char *adapter_path = NULL;
1257
1258         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1259
1260         manager_proxy =  g_dbus_proxy_new_sync(conn,
1261                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1262                         BT_BLUEZ_NAME,
1263                         BT_MANAGER_PATH,
1264                         BT_MANAGER_INTERFACE,
1265                         NULL, &err);
1266
1267         if (!manager_proxy) {
1268                 BT_ERR("Unable to create proxy: %s", err->message);
1269                 goto fail;
1270         }
1271
1272         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
1273                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
1274         if (!result) {
1275                 if (err != NULL)
1276                         BT_ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
1277                 else
1278                         BT_ERR("Fail to get DefaultAdapter");
1279
1280                 goto fail;
1281         }
1282
1283         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
1284                 BT_ERR("Incorrect result\n");
1285                 goto fail;
1286         }
1287
1288         g_variant_get(result, "(&o)", &adapter_path);
1289
1290         if (adapter_path == NULL ||
1291                 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
1292                 BT_ERR("Adapter path is inproper\n");
1293                 goto fail;
1294         }
1295
1296         if (path)
1297                 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
1298
1299         g_variant_unref(result);
1300         g_object_unref(manager_proxy);
1301
1302         return BLUETOOTH_ERROR_NONE;
1303
1304 fail:
1305         g_clear_error(&err);
1306
1307         if (result)
1308                 g_variant_unref(result);
1309
1310         if (manager_proxy)
1311                 g_object_unref(manager_proxy);
1312
1313         return BLUETOOTH_ERROR_INTERNAL;
1314
1315 }
1316
1317 void _bt_convert_device_path_to_address(const char *device_path,
1318                                                 char *device_address)
1319 {
1320         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1321         char *dev_addr;
1322
1323         ret_if(device_path == NULL);
1324         ret_if(device_address == NULL);
1325
1326         dev_addr = strstr(device_path, "dev_");
1327         if (dev_addr != NULL) {
1328                 char *pos = NULL;
1329                 dev_addr += 4;
1330                 g_strlcpy(address, dev_addr, sizeof(address));
1331
1332                 while ((pos = strchr(address, '_')) != NULL) {
1333                         *pos = ':';
1334                 }
1335
1336                 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
1337         }
1338 }
1339
1340 static char *__bt_extract_device_path(GVariantIter *iter, char *address)
1341 {
1342         char *object_path = NULL;
1343         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1344         /* Parse the signature:  oa{sa{sv}}} */
1345         while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
1346                         NULL)) {
1347                 retv_if(object_path == NULL, NULL);
1348                 _bt_convert_device_path_to_address(object_path, device_address);
1349
1350                 if (g_strcmp0(address, device_address) == 0) {
1351                         return g_strdup(object_path);
1352                 }
1353         }
1354         return NULL;
1355 }
1356
1357 char *_bt_get_device_object_path(char *address)
1358 {
1359         GError *err = NULL;
1360         GDBusProxy *proxy = NULL;
1361         GVariant *result = NULL;
1362         GVariantIter *iter = NULL;
1363         GDBusConnection *conn = NULL;
1364         char *object_path = NULL;
1365
1366         conn = _bt_gdbus_get_system_gconn();
1367         retv_if(conn == NULL, NULL);
1368
1369         proxy =  g_dbus_proxy_new_sync(conn,
1370                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1371                         BT_BLUEZ_NAME,
1372                         BT_MANAGER_PATH,
1373                         BT_MANAGER_INTERFACE,
1374                         NULL, &err);
1375
1376         if (!proxy) {
1377                 BT_ERR("Unable to create proxy: %s", err->message);
1378                 goto fail;
1379         }
1380
1381         result = g_dbus_proxy_call_sync(proxy, "GetManagedObjects", NULL,
1382                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
1383         if (!result) {
1384                 if (err != NULL)
1385                         BT_ERR("Fail to get GetManagedObjects (Error: %s)", err->message);
1386                 else
1387                         BT_ERR("Fail to get GetManagedObjects");
1388
1389                 goto fail;
1390         }
1391
1392         g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
1393         object_path = __bt_extract_device_path(iter, address);
1394
1395         g_variant_unref(result);
1396         g_object_unref(proxy);
1397         g_variant_iter_free(iter);
1398         return object_path;
1399
1400 fail:
1401         g_clear_error(&err);
1402
1403         if (proxy)
1404                 g_object_unref(proxy);
1405
1406         return object_path;
1407 }
1408
1409 void _bt_device_path_to_address(const char *device_path, char *device_address)
1410 {
1411         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1412         char *dev_addr = NULL;
1413
1414         if (!device_path || !device_address)
1415                 return;
1416
1417         dev_addr = strstr(device_path, "dev_");
1418         if (dev_addr != NULL) {
1419                 char *pos = NULL;
1420                 dev_addr += 4;
1421                 g_strlcpy(address, dev_addr, sizeof(address));
1422
1423                 while ((pos = strchr(address, '_')) != NULL) {
1424                         *pos = ':';
1425                 }
1426
1427                 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
1428         }
1429 }
1430
1431 /* TODO : replace the dbus-glib APIs to gdbus APIs */
1432 DBusConnection *__bt_init_system_conn(void)
1433 {
1434         if (system_conn == NULL)
1435                 system_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
1436
1437         if (system_conn) {
1438                 dbus_connection_setup_with_g_main(system_conn, NULL);
1439                 dbus_connection_set_exit_on_disconnect(system_conn, FALSE);
1440         }
1441
1442         return system_conn;
1443 }
1444
1445 DBusConnection *_bt_get_system_conn(void)
1446 {
1447         DBusConnection *conn = NULL;
1448
1449         if (system_conn == NULL) {
1450                 conn = __bt_init_system_conn();
1451         } else {
1452                 conn = system_conn;
1453         }
1454
1455         return conn;
1456 }
1457
1458
1459 int _bt_register_osp_server_in_agent(int type, char *uuid, char *path, int fd)
1460 {
1461         int ret;
1462         char uuid_str[BLUETOOTH_UUID_STRING_MAX] = { 0, };
1463         char path_str[BLUETOOTH_PATH_STRING] = { 0, };
1464
1465         BT_DBG("+");
1466         BT_INIT_PARAMS();
1467         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1468
1469         g_array_append_vals(in_param1, &type, sizeof(int));
1470         g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
1471         g_array_append_vals(in_param2, &uuid_str, BLUETOOTH_UUID_STRING_MAX);
1472         g_strlcpy(path_str, path, sizeof(path_str));
1473         g_array_append_vals(in_param3, &path_str, BLUETOOTH_PATH_STRING);
1474         g_array_append_vals(in_param4, &fd, sizeof(int));
1475
1476         ret =  _bt_send_request(BT_AGENT_SERVICE, BT_SET_AUTHORIZATION,
1477                 in_param1, in_param2, in_param3, in_param4, &out_param);
1478
1479         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1480         BT_DBG("-");
1481         return ret;
1482 }
1483
1484 int _bt_unregister_osp_server_in_agent(int type, char *uuid)
1485 {
1486         int ret;
1487         char uuid_str[BLUETOOTH_UUID_STRING_MAX] = { 0, };
1488
1489         BT_DBG("+");
1490         BT_INIT_PARAMS();
1491         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1492
1493         g_array_append_vals(in_param1, &type, sizeof(int));
1494         g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
1495         g_array_append_vals(in_param2, &uuid_str, BLUETOOTH_UUID_STRING_MAX);
1496
1497         ret =  _bt_send_request(BT_AGENT_SERVICE, BT_UNSET_AUTHORIZATION,
1498                 in_param1, in_param2, in_param3, in_param4, &out_param);
1499
1500         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1501         BT_DBG("-");
1502         return ret;
1503 }
1504
1505 int _bt_check_privilege(int service_type, int service_function)
1506 {
1507         int result;
1508
1509         BT_INIT_PARAMS();
1510         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1511
1512         result = _bt_send_request(service_type, service_function,
1513                 in_param1, in_param2, in_param3, in_param4, &out_param);
1514
1515         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1516
1517         return result;
1518 }
1519
1520 GVariant *_bt_get_managed_objects(void)
1521 {
1522         GDBusConnection *g_conn;
1523         GDBusProxy *manager_proxy = NULL;
1524         GVariant *result = NULL;
1525         GError *error = NULL;
1526
1527         BT_DBG("+");
1528
1529         g_conn = _bt_gdbus_get_system_gconn();
1530         retv_if(g_conn == NULL, NULL);
1531
1532         manager_proxy = g_dbus_proxy_new_sync(g_conn,
1533                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1534                         BT_BLUEZ_NAME,
1535                         BT_MANAGER_PATH,
1536                         BT_MANAGER_INTERFACE,
1537                         NULL, &error);
1538
1539         if (error) {
1540                 BT_ERR("Unable to create proxy: %s", error->message);
1541                 g_clear_error(&error);
1542                 return NULL;
1543         }
1544
1545         result = g_dbus_proxy_call_sync (manager_proxy,
1546                         "GetManagedObjects", NULL,
1547                         G_DBUS_CALL_FLAGS_NONE, -1,
1548                         NULL, &error);
1549
1550         if (error) {
1551                 BT_ERR("Fail to get ManagedObjects (Error: %s)", error->message);
1552                 g_clear_error(&error);
1553         }
1554
1555         g_object_unref(manager_proxy);
1556
1557         BT_DBG("-");
1558         return result;
1559 }
1560
1561 BT_EXPORT_API int bluetooth_is_supported(void)
1562 {
1563         int is_supported = 0;
1564         int len = 0;
1565         int fd = -1;
1566         rfkill_event event;
1567
1568         fd = open(RFKILL_NODE, O_RDONLY);
1569         if (fd < 0) {
1570                 BT_ERR("Fail to open RFKILL node");
1571                 return BLUETOOTH_ERROR_INTERNAL;
1572         }
1573
1574         if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
1575                 BT_ERR("Fail to set RFKILL node to non-blocking");
1576                 close(fd);
1577                 return BLUETOOTH_ERROR_INTERNAL;
1578         }
1579
1580         while (1) {
1581                 len = read(fd, &event, sizeof(event));
1582                 if (len < 0) {
1583                         BT_ERR("Fail to read events");
1584                         break;
1585                 }
1586
1587                 if (len != RFKILL_EVENT_SIZE) {
1588                         BT_ERR("The size is wrong\n");
1589                         continue;
1590                 }
1591
1592                 if (event.type == RFKILL_TYPE_BLUETOOTH) {
1593                         is_supported = 1;
1594                         break;
1595                 }
1596         }
1597
1598         close(fd);
1599
1600         BT_DBG("supported: %d", is_supported);
1601
1602         return is_supported;
1603 }
1604
1605 BT_EXPORT_API int bluetooth_register_callback(bluetooth_cb_func_ptr callback_ptr, void *user_data)
1606 {
1607         int ret;
1608
1609         _bt_gdbus_init_system_gconn();
1610         __bt_init_system_conn();
1611
1612         ret = _bt_init_event_handler();
1613         if (ret != BLUETOOTH_ERROR_NONE &&
1614              ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
1615                 BT_ERR("Fail to init the event handler");
1616                 return ret;
1617         }
1618
1619
1620         _bt_set_user_data(BT_COMMON, (void *)callback_ptr, user_data);
1621
1622         /* Register All events */
1623         ret = _bt_register_event(BT_ADAPTER_EVENT, (void *)callback_ptr, user_data);
1624         if (ret != BLUETOOTH_ERROR_NONE)
1625                 goto fail;
1626         ret = _bt_register_event(BT_DEVICE_EVENT, (void *)callback_ptr, user_data);
1627         if (ret != BLUETOOTH_ERROR_NONE)
1628                 goto fail;
1629         ret = _bt_register_event(BT_NETWORK_EVENT, (void *)callback_ptr, user_data);
1630         if (ret != BLUETOOTH_ERROR_NONE)
1631                 goto fail;
1632         ret = _bt_register_event(BT_RFCOMM_CLIENT_EVENT, (void *)callback_ptr, user_data);
1633         if (ret != BLUETOOTH_ERROR_NONE)
1634                 goto fail;
1635         ret = _bt_register_event(BT_RFCOMM_SERVER_EVENT, (void *)callback_ptr, user_data);
1636         if (ret != BLUETOOTH_ERROR_NONE)
1637                 goto fail;
1638 #ifdef GATT_NO_RELAY
1639         ret = _bt_register_event(BT_GATT_BLUEZ_EVENT, (void *)callback_ptr, user_data);
1640         if (ret != BLUETOOTH_ERROR_NONE)
1641                 goto fail;
1642 #endif
1643
1644         _bt_register_name_owner_changed();
1645
1646         return BLUETOOTH_ERROR_NONE;
1647 fail:
1648         BT_ERR("Fail to do _bt_register_event()");
1649         bluetooth_unregister_callback();
1650         return ret;
1651 }
1652
1653 BT_EXPORT_API int bluetooth_unregister_callback(void)
1654 {
1655         int ret;
1656
1657
1658         ret = _bt_deinit_event_handler();
1659         if (ret != BLUETOOTH_ERROR_NONE) {
1660                 BT_ERR("Fail to deinit the event handler");
1661         }
1662
1663         _bt_unregister_name_owner_changed();
1664
1665         _bt_set_user_data(BT_COMMON, NULL, NULL);
1666
1667         if (system_conn) {
1668                 dbus_connection_flush(system_conn);
1669                 dbus_connection_close(system_conn);
1670                 dbus_connection_unref(system_conn);
1671                 system_conn = NULL;
1672         }
1673         if (system_gconn) {
1674                 g_object_unref(system_gconn);
1675                 system_gconn = NULL;
1676         }
1677         _bt_gdbus_deinit_proxys();
1678         return BLUETOOTH_ERROR_NONE;
1679 }
1680